diff options
Diffstat (limited to 'zebra/interface.c')
| -rw-r--r-- | zebra/interface.c | 2918 |
1 files changed, 958 insertions, 1960 deletions
diff --git a/zebra/interface.c b/zebra/interface.c index 496a85e676..b824977f9e 100644 --- a/zebra/interface.c +++ b/zebra/interface.c @@ -18,7 +18,6 @@ #include "log.h" #include "zclient.h" #include "vrf.h" -#include "lib/northbound_cli.h" #include "zebra/rtadv.h" #include "zebra_ns.h" @@ -44,8 +43,6 @@ DEFINE_MTYPE_STATIC(ZEBRA, ZINFO, "Zebra Interface Information"); DEFINE_HOOK(zebra_if_extra_info, (struct vty * vty, struct interface *ifp), (vty, ifp)); -DEFINE_HOOK(zebra_if_config_wr, (struct vty * vty, struct interface *ifp), - (vty, ifp)); DEFINE_MTYPE(ZEBRA, ZIF_DESC, "Intf desc"); @@ -65,7 +62,7 @@ static void if_zebra_speed_update(struct event *thread) * interfaces not available. * note that loopback & virtual interfaces can return 0 as speed */ - if (error < 0) + if (error == INTERFACE_SPEED_ERROR_READ) return; if (new_speed != ifp->speed) { @@ -76,7 +73,7 @@ static void if_zebra_speed_update(struct event *thread) changed = true; } - if (changed || new_speed == UINT32_MAX) { + if (changed || error == INTERFACE_SPEED_ERROR_UNKNOWN) { #define SPEED_UPDATE_SLEEP_TIME 5 #define SPEED_UPDATE_COUNT_MAX (4 * 60 / SPEED_UPDATE_SLEEP_TIME) /* @@ -91,7 +88,7 @@ static void if_zebra_speed_update(struct event *thread) * to not update the system to keep track of that. This * is far simpler to just stop trying after 4 minutes */ - if (new_speed == UINT32_MAX && + if (error == INTERFACE_SPEED_ERROR_UNKNOWN && zif->speed_update_count == SPEED_UPDATE_COUNT_MAX) return; @@ -111,17 +108,6 @@ static void zebra_if_node_destroy(route_table_delegate_t *delegate, route_node_destroy(delegate, table, node); } -static void zebra_if_nhg_dependents_free(struct zebra_if *zebra_if) -{ - nhg_connected_tree_free(&zebra_if->nhg_dependents); -} - -static void zebra_if_nhg_dependents_init(struct zebra_if *zebra_if) -{ - nhg_connected_tree_init(&zebra_if->nhg_dependents); -} - - route_table_delegate_t zebra_if_table_delegate = { .create_node = route_node_create, .destroy_node = zebra_if_node_destroy}; @@ -135,11 +121,12 @@ static int if_zebra_new_hook(struct interface *ifp) zebra_if->ifp = ifp; zebra_if->multicast = IF_ZEBRA_DATA_UNSPEC; - zebra_if->shutdown = IF_ZEBRA_DATA_OFF; + zebra_if->mpls_config = IF_ZEBRA_DATA_UNSPEC; + zebra_if->shutdown = IF_ZEBRA_DATA_UNSPEC; zebra_if->link_nsid = NS_UNKNOWN; - zebra_if_nhg_dependents_init(zebra_if); + nhg_connected_tree_init(&zebra_if->nhg_dependents); zebra_ptm_if_init(zebra_if); @@ -147,6 +134,8 @@ static int if_zebra_new_hook(struct interface *ifp) rtadv_if_init(zebra_if); + zebra_evpn_mh_if_init(zebra_if); + memset(&zebra_if->neigh_mac[0], 0, 6); /* Initialize installed address chains tree. */ @@ -170,18 +159,13 @@ static int if_zebra_new_hook(struct interface *ifp) return 0; } -static void if_nhg_dependents_check_valid(struct nhg_hash_entry *nhe) -{ - zebra_nhg_check_valid(nhe); -} - static void if_down_nhg_dependents(const struct interface *ifp) { struct nhg_connected *rb_node_dep = NULL; struct zebra_if *zif = (struct zebra_if *)ifp->info; frr_each(nhg_connected_tree, &zif->nhg_dependents, rb_node_dep) - if_nhg_dependents_check_valid(rb_node_dep->nhe); + zebra_nhg_check_valid(rb_node_dep->nhe); } static void if_nhg_dependents_release(const struct interface *ifp) @@ -191,7 +175,11 @@ static void if_nhg_dependents_release(const struct interface *ifp) frr_each(nhg_connected_tree, &zif->nhg_dependents, rb_node_dep) { rb_node_dep->nhe->ifp = NULL; /* Null it out */ - if_nhg_dependents_check_valid(rb_node_dep->nhe); + zebra_nhg_check_valid(rb_node_dep->nhe); + if (CHECK_FLAG(rb_node_dep->nhe->flags, + NEXTHOP_GROUP_KEEP_AROUND) && + rb_node_dep->nhe->refcnt == 1) + zebra_nhg_decrement_ref(rb_node_dep->nhe); } } @@ -199,6 +187,7 @@ static void if_nhg_dependents_release(const struct interface *ifp) static int if_zebra_delete_hook(struct interface *ifp) { struct zebra_if *zebra_if; + struct zebra_l2info_bond *bond; if (ifp->info) { zebra_if = ifp->info; @@ -216,12 +205,16 @@ static int if_zebra_delete_hook(struct interface *ifp) rtadv_if_fini(zebra_if); + bond = &zebra_if->bond_info; + if (bond && bond->mbr_zifs) + list_delete(&bond->mbr_zifs); + zebra_l2_bridge_if_cleanup(ifp); zebra_evpn_if_cleanup(zebra_if); zebra_evpn_mac_ifp_del(ifp); if_nhg_dependents_release(ifp); - zebra_if_nhg_dependents_free(zebra_if); + nhg_connected_tree_free(&zebra_if->nhg_dependents); XFREE(MTYPE_ZIF_DESC, zebra_if->desc); @@ -267,6 +260,9 @@ struct interface *if_link_per_ns(struct zebra_ns *ns, struct interface *ifp) /* Delete a VRF. This is called in vrf_terminate(). */ void if_unlink_per_ns(struct interface *ifp) { + if (!ifp->node) + return; + ifp->node->info = NULL; route_unlock_node(ifp->node); ifp->node = NULL; @@ -480,12 +476,11 @@ void if_flags_update(struct interface *ifp, uint64_t newflags) address. */ void if_addr_wakeup(struct interface *ifp) { - struct listnode *node, *nnode; struct connected *ifc; struct prefix *p; enum zebra_dplane_result dplane_res; - for (ALL_LIST_ELEMENTS(ifp->connected, node, nnode, ifc)) { + frr_each_safe (if_connected, ifp->connected, ifc) { p = ifc->address; if (CHECK_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED) @@ -606,6 +601,11 @@ void if_add_update(struct interface *ifp) if_addr_wakeup(ifp); + if (if_data->mpls_config == IF_ZEBRA_DATA_ON) + dplane_intf_mpls_modify_state(ifp, true); + else if (if_data->mpls_config == IF_ZEBRA_DATA_OFF) + dplane_intf_mpls_modify_state(ifp, false); + if (IS_ZEBRA_DEBUG_KERNEL) zlog_debug( "interface %s vrf %s(%u) index %d becomes active.", @@ -623,32 +623,24 @@ void if_add_update(struct interface *ifp) /* Install connected routes corresponding to an interface. */ static void if_install_connected(struct interface *ifp) { - struct listnode *node; - struct listnode *next; struct connected *ifc; - if (ifp->connected) { - for (ALL_LIST_ELEMENTS(ifp->connected, node, next, ifc)) { - if (CHECK_FLAG(ifc->conf, ZEBRA_IFC_REAL)) - zebra_interface_address_add_update(ifp, ifc); + frr_each (if_connected, ifp->connected, ifc) { + if (CHECK_FLAG(ifc->conf, ZEBRA_IFC_REAL)) + zebra_interface_address_add_update(ifp, ifc); - connected_up(ifp, ifc); - } + connected_up(ifp, ifc); } } /* Uninstall connected routes corresponding to an interface. */ static void if_uninstall_connected(struct interface *ifp) { - struct listnode *node; - struct listnode *next; struct connected *ifc; - if (ifp->connected) { - for (ALL_LIST_ELEMENTS(ifp->connected, node, next, ifc)) { - zebra_interface_address_delete_update(ifp, ifc); - connected_down(ifp, ifc); - } + frr_each_safe (if_connected, ifp->connected, ifc) { + zebra_interface_address_delete_update(ifp, ifc); + connected_down(ifp, ifc); } } @@ -656,20 +648,15 @@ static void if_uninstall_connected(struct interface *ifp) /* TODO - Check why IPv4 handling here is different from install or if_down */ static void if_delete_connected(struct interface *ifp) { - struct connected *ifc; + struct connected *ifc, *ifc_next; struct prefix cp; struct route_node *rn; struct zebra_if *zebra_if; - struct listnode *node; - struct listnode *last = NULL; zebra_if = ifp->info; - if (!ifp->connected) - return; - - while ((node = (last ? last->next : listhead(ifp->connected)))) { - ifc = listgetdata(node); + for (ifc = if_connected_first(ifp->connected); ifc; ifc = ifc_next) { + ifc_next = if_connected_next(ifp->connected, ifc); cp = *CONNECTED_PREFIX(ifc); apply_mask(&cp); @@ -718,11 +705,15 @@ static void if_delete_connected(struct interface *ifp) * (unconditionally). */ if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED)) { - listnode_delete(ifp->connected, + if (ifc == ifc_next) + ifc_next = if_connected_next( + ifp->connected, ifc); + + if_connected_del(ifp->connected, + ifc); connected_free(&ifc); - } else - last = node; + } } /* Free chain list and respective route node. */ @@ -737,14 +728,10 @@ static void if_delete_connected(struct interface *ifp) UNSET_FLAG(ifc->conf, ZEBRA_IFC_REAL); UNSET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED); - if (CHECK_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED)) - last = node; - else { - listnode_delete(ifp->connected, ifc); + if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED)) { + if_connected_del(ifp->connected, ifc); connected_free(&ifc); } - } else { - last = node; } } } @@ -778,6 +765,15 @@ void if_delete_update(struct interface **pifp) /* Delete connected routes from the kernel. */ if_delete_connected(ifp); + /* if the ifp is in a vrf, move it to default so vrf can be deleted if + * desired. This operation is not done for netns implementation to avoid + * collision with interface with the same name in the default vrf (can + * occur with this implementation whereas it is not possible with + * vrf-lite). + */ + if (ifp->vrf->vrf_id && !vrf_is_backend_netns()) + if_handle_vrf_change(ifp, VRF_DEFAULT); + /* Send out notification on interface delete. */ zebra_interface_delete_update(ifp); @@ -791,14 +787,7 @@ void if_delete_update(struct interface **pifp) if_set_index(ifp, IFINDEX_INTERNAL); ifp->node = NULL; - /* if the ifp is in a vrf, move it to default so vrf can be deleted if - * desired. This operation is not done for netns implementation to avoid - * collision with interface with the same name in the default vrf (can - * occur with this implementation whereas it is not possible with - * vrf-lite). - */ - if (ifp->vrf->vrf_id && !vrf_is_backend_netns()) - if_handle_vrf_change(ifp, VRF_DEFAULT); + UNSET_FLAG(ifp->status, ZEBRA_INTERFACE_VRF_LOOPBACK); /* Reset some zebra interface params to default values. */ zif = ifp->info; @@ -837,9 +826,12 @@ void if_handle_vrf_change(struct interface *ifp, vrf_id_t vrf_id) if_down_del_nbr_connected(ifp); /* Send out notification on interface VRF change. */ - /* This is to issue an UPDATE or a DELETE, as appropriate. */ + /* This is to issue a DELETE, as appropriate. */ zebra_interface_vrf_update_del(ifp, vrf_id); + if (if_is_vrf(ifp)) + return; + /* update VRF */ if_update_to_new_vrf(ifp, vrf_id); @@ -955,47 +947,6 @@ static void if_down_del_nbr_connected(struct interface *ifp) } } -void if_nhg_dependents_add(struct interface *ifp, struct nhg_hash_entry *nhe) -{ - if (ifp->info) { - struct zebra_if *zif = (struct zebra_if *)ifp->info; - - nhg_connected_tree_add_nhe(&zif->nhg_dependents, nhe); - } -} - -void if_nhg_dependents_del(struct interface *ifp, struct nhg_hash_entry *nhe) -{ - if (ifp->info) { - struct zebra_if *zif = (struct zebra_if *)ifp->info; - - nhg_connected_tree_del_nhe(&zif->nhg_dependents, nhe); - } -} - -unsigned int if_nhg_dependents_count(const struct interface *ifp) -{ - if (ifp->info) { - struct zebra_if *zif = (struct zebra_if *)ifp->info; - - return nhg_connected_tree_count(&zif->nhg_dependents); - } - - return 0; -} - - -bool if_nhg_dependents_is_empty(const struct interface *ifp) -{ - if (ifp->info) { - struct zebra_if *zif = (struct zebra_if *)ifp->info; - - return nhg_connected_tree_is_empty(&zif->nhg_dependents); - } - - return false; -} - /* Interface is up. */ void if_up(struct interface *ifp, bool install_connected) { @@ -1023,6 +974,14 @@ void if_up(struct interface *ifp, bool install_connected) if (install_connected) if_install_connected(ifp); + /* + * Interface associated NHG's have been deleted on + * interface down events, now that this interface + * is coming back up, let's resync the zebra -> dplane + * nhg's so that they can be continued to be used. + */ + zebra_interface_nhg_reinstall(ifp); + /* Handle interface up for specific types for EVPN. Non-VxLAN interfaces * are checked to see if (remote) neighbor entries need to be installed * on them for ARP suppression. @@ -1049,6 +1008,8 @@ void if_up(struct interface *ifp, bool install_connected) event_add_timer(zrouter.master, if_zebra_speed_update, ifp, 0, &zif->speed_update); event_ignore_late_timer(zif->speed_update); + + if_addr_wakeup(ifp); } /* Interface goes down. We have to manage different behavior of based @@ -1112,8 +1073,6 @@ void zebra_if_update_link(struct interface *ifp, ifindex_t link_ifindex, { struct zebra_if *zif; - if (IS_ZEBRA_IF_VETH(ifp)) - return; zif = (struct zebra_if *)ifp->info; zif->link_nsid = ns_id; zif->link_ifindex = link_ifindex; @@ -1176,6 +1135,12 @@ static bool if_ignore_set_protodown(const struct interface *ifp, bool new_down, zif = ifp->info; + /* + * FRR does not have enough data to make this request + */ + if (ifp->ifindex == IFINDEX_INTERNAL) + return true; + /* Current state as we know it */ old_down = !!(ZEBRA_IF_IS_PROTODOWN(zif)); old_set_down = !!CHECK_FLAG(zif->flags, ZIF_FLAG_SET_PROTODOWN); @@ -1285,6 +1250,9 @@ static void zebra_if_addr_update_ctx(struct zebra_dplane_ctx *ctx, const struct prefix *addr, *dest = NULL; enum dplane_op_e op; + if (!ifp) + return; + op = dplane_ctx_get_op(ctx); addr = dplane_ctx_get_intf_addr(ctx); @@ -1305,6 +1273,9 @@ static void zebra_if_addr_update_ctx(struct zebra_dplane_ctx *ctx, if (dplane_ctx_intf_is_secondary(ctx)) SET_FLAG(flags, ZEBRA_IFA_SECONDARY); + if (dplane_ctx_intf_is_noprefixroute(ctx)) + SET_FLAG(flags, ZEBRA_IFA_NOPREFIXROUTE); + /* Label? */ if (dplane_ctx_intf_has_label(ctx)) label = dplane_ctx_get_intf_label(ctx); @@ -1356,6 +1327,13 @@ static void zebra_if_update_ctx(struct zebra_dplane_ctx *ctx, bool pd_reason_val; bool down; + if (!ifp) { + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug("%s: Can't find ifp", __func__); + + return; + } + dp_res = dplane_ctx_get_status(ctx); pd_reason_val = dplane_ctx_get_intf_pd_reason_val(ctx); down = dplane_ctx_intf_is_protodown(ctx); @@ -1403,6 +1381,13 @@ static void zebra_if_netconf_update_ctx(struct zebra_dplane_ctx *ctx, enum dplane_netconf_status_e mpls, mcast_on, linkdown; bool *mcast_set, *linkdown_set; + if (!ifp && ifindex != -1 && ifindex != -2) { + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug("%s: Can't find ifp(%u)", __func__, ifindex); + + return; + } + afi = dplane_ctx_get_afi(ctx); mpls = dplane_ctx_get_netconf_mpls(ctx); linkdown = dplane_ctx_get_netconf_linkdown(ctx); @@ -1425,7 +1410,7 @@ static void zebra_if_netconf_update_ctx(struct zebra_dplane_ctx *ctx, linkdown_set = &zrouter.default_linkdownv6; } } else { - zif = ifp ? ifp->info : NULL; + zif = ifp->info; if (!zif) { if (IS_ZEBRA_DEBUG_KERNEL) zlog_debug( @@ -1472,6 +1457,762 @@ static void zebra_if_netconf_update_ctx(struct zebra_dplane_ctx *ctx, (*linkdown_set ? "ON" : "OFF")); } +static void interface_vrf_change(enum dplane_op_e op, ifindex_t ifindex, + const char *name, uint32_t tableid, + ns_id_t ns_id) +{ + struct vrf *vrf; + struct zebra_vrf *zvrf = NULL; + + if (op == DPLANE_OP_INTF_DELETE) { + if (IS_ZEBRA_DEBUG_DPLANE) + zlog_debug("DPLANE_OP_INTF_DELETE for VRF %s(%u)", name, + ifindex); + + vrf = vrf_lookup_by_id((vrf_id_t)ifindex); + if (!vrf) { + flog_warn(EC_ZEBRA_VRF_NOT_FOUND, + "%s(%u): vrf not found", name, ifindex); + return; + } + + vrf_delete(vrf); + } else { + if (IS_ZEBRA_DEBUG_DPLANE) + zlog_debug( + "DPLANE_OP_INTF_UPDATE for VRF %s(%u) table %u", + name, ifindex, tableid); + + if (!vrf_lookup_by_id((vrf_id_t)ifindex)) { + vrf_id_t exist_id; + + exist_id = zebra_vrf_lookup_by_table(tableid, ns_id); + if (exist_id != VRF_DEFAULT) { + vrf = vrf_lookup_by_id(exist_id); + + if (vrf) + flog_err(EC_ZEBRA_VRF_MISCONFIGURED, + "VRF %s id %u table id overlaps existing vrf %s(%d), misconfiguration exiting", + name, ifindex, vrf->name, + vrf->vrf_id); + else + flog_err(EC_ZEBRA_VRF_NOT_FOUND, + "VRF %s id %u does not exist", + name, ifindex); + + exit(-1); + } + } + + vrf = vrf_update((vrf_id_t)ifindex, name); + if (!vrf) { + flog_err(EC_LIB_INTERFACE, "VRF %s id %u not created", + name, ifindex); + return; + } + + /* + * This is the only place that we get the actual kernel table_id + * being used. We need it to set the table_id of the routes + * we are passing to the kernel.... And to throw some totally + * awesome parties. that too. + * + * At this point we *must* have a zvrf because the vrf_create + * callback creates one. We *must* set the table id + * before the vrf_enable because of( at the very least ) + * static routes being delayed for installation until + * during the vrf_enable callbacks. + */ + zvrf = (struct zebra_vrf *)vrf->info; + zvrf->table_id = tableid; + + /* Enable the created VRF. */ + if (!vrf_enable(vrf)) { + flog_err(EC_LIB_INTERFACE, + "Failed to enable VRF %s id %u", name, + ifindex); + return; + } + } +} + +/* + * Note: on netlink systems, there should be a 1-to-1 mapping + * between interface names and ifindex values. + */ +static void set_ifindex(struct interface *ifp, ifindex_t ifi_index, + struct zebra_ns *zns) +{ + struct interface *oifp; + + oifp = if_lookup_by_index_per_ns(zns, ifi_index); + if ((oifp != NULL) && (oifp != ifp)) { + if (ifi_index == IFINDEX_INTERNAL) + flog_err( + EC_LIB_INTERFACE, + "Netlink is setting interface %s ifindex to reserved internal value %u", + ifp->name, ifi_index); + else { + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug( + "interface index %d was renamed from %s to %s", + ifi_index, oifp->name, ifp->name); + if (if_is_up(oifp)) + flog_err( + EC_LIB_INTERFACE, + "interface rename detected on up interface: index %d was renamed from %s to %s, results are uncertain!", + ifi_index, oifp->name, ifp->name); + if_delete_update(&oifp); + } + } + if_set_index(ifp, ifi_index); +} + +static inline void zebra_if_set_ziftype(struct interface *ifp, + enum zebra_iftype zif_type, + enum zebra_slave_iftype zif_slave_type) +{ + struct zebra_if *zif; + + zif = (struct zebra_if *)ifp->info; + zif->zif_slave_type = zif_slave_type; + + if (zif->zif_type != zif_type) { + zif->zif_type = zif_type; + /* If the if_type has been set to bond initialize ES info + * against it. XXX - note that we don't handle the case where + * a zif changes from bond to non-bond; it is really + * an unexpected/error condition. + */ + zebra_evpn_if_init(zif); + } +} + +static void interface_update_hw_addr(struct zebra_dplane_ctx *ctx, + struct interface *ifp) +{ + int i; + + ifp->hw_addr_len = dplane_ctx_get_ifp_hw_addr_len(ctx); + memcpy(ifp->hw_addr, dplane_ctx_get_ifp_hw_addr(ctx), ifp->hw_addr_len); + + for (i = 0; i < ifp->hw_addr_len; i++) + if (ifp->hw_addr[i] != 0) + break; + + if (i == ifp->hw_addr_len) + ifp->hw_addr_len = 0; +} + +static void interface_update_l2info(struct zebra_dplane_ctx *ctx, + struct interface *ifp, + enum zebra_iftype zif_type, int add, + ns_id_t link_nsid) +{ + const struct zebra_l2info_vxlan *vxlan_info; + const struct zebra_l2info_gre *gre_info; + + switch (zif_type) { + case ZEBRA_IF_BRIDGE: + zebra_l2_bridge_add_update(ifp, + dplane_ctx_get_ifp_bridge_info(ctx)); + break; + case ZEBRA_IF_VLAN: + zebra_l2_vlanif_update(ifp, dplane_ctx_get_ifp_vlan_info(ctx)); + zebra_evpn_acc_bd_svi_set(ifp->info, NULL, + !!if_is_operative(ifp)); + break; + case ZEBRA_IF_VXLAN: + vxlan_info = dplane_ctx_get_ifp_vxlan_info(ctx); + zebra_l2_vxlanif_add_update(ifp, vxlan_info, add); + if (link_nsid != NS_UNKNOWN && vxlan_info->ifindex_link) + zebra_if_update_link(ifp, vxlan_info->ifindex_link, + link_nsid); + break; + case ZEBRA_IF_GRE: + gre_info = dplane_ctx_get_ifp_gre_info(ctx); + zebra_l2_greif_add_update(ifp, gre_info, add); + if (link_nsid != NS_UNKNOWN && gre_info->ifindex_link) + zebra_if_update_link(ifp, gre_info->ifindex_link, + link_nsid); + break; + case ZEBRA_IF_OTHER: + case ZEBRA_IF_VRF: + case ZEBRA_IF_MACVLAN: + case ZEBRA_IF_VETH: + case ZEBRA_IF_BOND: + break; + } +} + +static bool is_if_protodown_reason_only_frr(uint32_t rc_bitfield) +{ + uint8_t frr_protodown_r_bit = if_netlink_get_frr_protodown_r_bit(); + + return (rc_bitfield == (((uint32_t)1) << frr_protodown_r_bit)); +} + +static void interface_if_protodown(struct interface *ifp, bool protodown, + uint32_t rc_bitfield) +{ + struct zebra_if *zif = ifp->info; + bool old_protodown; + + /* + * Set our reason code to note it wasn't us. + * If the reason we got from the kernel is ONLY frr though, don't + * set it. + */ + COND_FLAG(zif->protodown_rc, ZEBRA_PROTODOWN_EXTERNAL, + protodown && rc_bitfield && + !is_if_protodown_reason_only_frr(rc_bitfield)); + + + old_protodown = !!ZEBRA_IF_IS_PROTODOWN(zif); + if (protodown == old_protodown) + return; + + if (IS_ZEBRA_DEBUG_EVPN_MH_ES || IS_ZEBRA_DEBUG_DPLANE) + zlog_debug("interface %s dplane change, protodown %s", + ifp->name, protodown ? "on" : "off"); + + /* Set protodown, respectively */ + COND_FLAG(zif->flags, ZIF_FLAG_PROTODOWN, protodown); + + if (zebra_evpn_is_es_bond_member(ifp)) { + /* Check it's not already being sent to the dplane first */ + if (protodown && + CHECK_FLAG(zif->flags, ZIF_FLAG_SET_PROTODOWN)) { + if (IS_ZEBRA_DEBUG_EVPN_MH_ES || IS_ZEBRA_DEBUG_KERNEL) + zlog_debug( + "bond mbr %s protodown on recv'd but already sent protodown on to the dplane", + ifp->name); + return; + } + + if (!protodown && + CHECK_FLAG(zif->flags, ZIF_FLAG_UNSET_PROTODOWN)) { + if (IS_ZEBRA_DEBUG_EVPN_MH_ES || IS_ZEBRA_DEBUG_KERNEL) + zlog_debug( + "bond mbr %s protodown off recv'd but already sent protodown off to the dplane", + ifp->name); + return; + } + + if (IS_ZEBRA_DEBUG_EVPN_MH_ES || IS_ZEBRA_DEBUG_KERNEL) + zlog_debug( + "bond mbr %s reinstate protodown %s in the dplane", + ifp->name, old_protodown ? "on" : "off"); + + if (old_protodown) + SET_FLAG(zif->flags, ZIF_FLAG_SET_PROTODOWN); + else + SET_FLAG(zif->flags, ZIF_FLAG_UNSET_PROTODOWN); + + dplane_intf_update(zif->ifp); + } +} + +static void if_sweep_protodown(struct zebra_if *zif) +{ + bool protodown; + + protodown = !!ZEBRA_IF_IS_PROTODOWN(zif); + + if (!protodown) + return; + + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug("interface %s sweeping protodown %s reason 0x%x", + zif->ifp->name, protodown ? "on" : "off", + zif->protodown_rc); + + /* Only clear our reason codes, leave external if it was set */ + UNSET_FLAG(zif->protodown_rc, ZEBRA_PROTODOWN_ALL); + dplane_intf_update(zif->ifp); +} + +static void +interface_bridge_vxlan_vlan_vni_map_update(struct zebra_dplane_ctx *ctx, + struct interface *ifp) +{ + const struct zebra_vxlan_vni_array *vniarray = + dplane_ctx_get_ifp_vxlan_vni_array(ctx); + struct zebra_vxlan_vni vni_start, vni_end; + struct hash *vni_table = NULL; + struct zebra_vxlan_vni vni, *vnip; + vni_t vni_id; + vlanid_t vid; + int i; + + if (vniarray == NULL) + return; + + memset(&vni_start, 0, sizeof(vni_start)); + memset(&vni_end, 0, sizeof(vni_end)); + + for (i = 0; i < vniarray->count; i++) { + uint16_t flags = vniarray->vnis[i].flags; + + if (flags & DPLANE_BRIDGE_VLAN_INFO_RANGE_BEGIN) { + vni_start = vniarray->vnis[i]; + continue; + } + + if (flags & DPLANE_BRIDGE_VLAN_INFO_RANGE_END) + vni_end = vniarray->vnis[i]; + + if (!(flags & DPLANE_BRIDGE_VLAN_INFO_RANGE_END)) { + vni_start = vniarray->vnis[i]; + vni_end = vniarray->vnis[i]; + } + + if (IS_ZEBRA_DEBUG_DPLANE) + zlog_debug( + "Vlan-Vni(%d:%d-%d:%d) update for VxLAN IF %s(%u)", + vni_start.access_vlan, vni_end.access_vlan, + vni_start.vni, vni_end.vni, ifp->name, + ifp->ifindex); + + if (!vni_table) { + vni_table = zebra_vxlan_vni_table_create(); + if (!vni_table) + return; + } + + for (vid = vni_start.access_vlan, vni_id = vni_start.vni; + vid <= vni_end.access_vlan; vid++, vni_id++) { + + memset(&vni, 0, sizeof(vni)); + vni.vni = vni_id; + vni.access_vlan = vid; + vnip = hash_get(vni_table, &vni, zebra_vxlan_vni_alloc); + if (!vnip) + return; + } + + memset(&vni_start, 0, sizeof(vni_start)); + memset(&vni_end, 0, sizeof(vni_end)); + } + + if (vni_table) + zebra_vxlan_if_vni_table_add_update(ifp, vni_table); +} + +static void interface_bridge_vxlan_update(struct zebra_dplane_ctx *ctx, + struct interface *ifp) +{ + struct zebra_if *zif = ifp->info; + const struct zebra_dplane_bridge_vlan_info *bvinfo; + + if (dplane_ctx_get_ifp_no_afspec(ctx)) + return; + + if (IS_ZEBRA_VXLAN_IF_SVD(zif)) + interface_bridge_vxlan_vlan_vni_map_update(ctx, ifp); + + if (dplane_ctx_get_ifp_no_bridge_vlan_info(ctx)) + return; + + bvinfo = dplane_ctx_get_ifp_bridge_vlan_info(ctx); + + if (!(bvinfo->flags & DPLANE_BRIDGE_VLAN_INFO_PVID)) + return; + + if (IS_ZEBRA_DEBUG_DPLANE) + zlog_debug("Access VLAN %u for VxLAN IF %s(%u)", bvinfo->vid, + ifp->name, ifp->ifindex); + + zebra_l2_vxlanif_update_access_vlan(ifp, bvinfo->vid); +} + +static void interface_bridge_vlan_update(struct zebra_dplane_ctx *ctx, + struct interface *ifp) +{ + struct zebra_if *zif = ifp->info; + const struct zebra_dplane_bridge_vlan_info_array *bvarray; + struct zebra_dplane_bridge_vlan_info bvinfo; + bitfield_t old_vlan_bitmap; + uint16_t vid_range_start = 0; + int32_t i; + + /* cache the old bitmap addrs */ + old_vlan_bitmap = zif->vlan_bitmap; + /* create a new bitmap space for re-eval */ + bf_init(zif->vlan_bitmap, IF_VLAN_BITMAP_MAX); + + /* Could we have multiple bridge vlan infos? */ + bvarray = dplane_ctx_get_ifp_bridge_vlan_info_array(ctx); + if (!bvarray) + return; + + for (i = 0; i < bvarray->count; i++) { + bvinfo = bvarray->array[i]; + + if (bvinfo.flags & DPLANE_BRIDGE_VLAN_INFO_RANGE_BEGIN) { + vid_range_start = bvinfo.vid; + continue; + } + + if (!(bvinfo.flags & DPLANE_BRIDGE_VLAN_INFO_RANGE_END)) + vid_range_start = bvinfo.vid; + + zebra_vlan_bitmap_compute(ifp, vid_range_start, bvinfo.vid); + } + + zebra_vlan_mbr_re_eval(ifp, old_vlan_bitmap); + bf_free(old_vlan_bitmap); +} + +static void interface_bridge_handling(struct zebra_dplane_ctx *ctx, + struct interface *ifp, + enum zebra_iftype zif_type) +{ + struct zebra_if *zif; + + if (!ifp) { + zlog_warn("Cannot find bridge if %s(%u)", + dplane_ctx_get_ifname(ctx), + dplane_ctx_get_ifindex(ctx)); + return; + } + + if (IS_ZEBRA_IF_VXLAN(ifp)) + return interface_bridge_vxlan_update(ctx, ifp); + + /* + * build vlan bitmap associated with this interface if that + * device type is interested in the vlans + */ + zif = ifp->info; + if (bf_is_inited(zif->vlan_bitmap)) + interface_bridge_vlan_update(ctx, ifp); +} + +static void zebra_if_dplane_ifp_handling(struct zebra_dplane_ctx *ctx) +{ + enum dplane_op_e op = dplane_ctx_get_op(ctx); + const char *name = dplane_ctx_get_ifname(ctx); + ns_id_t ns_id = dplane_ctx_get_ns_id(ctx); + ifindex_t ifindex = dplane_ctx_get_ifindex(ctx); + ifindex_t bond_ifindex = dplane_ctx_get_ifp_bond_ifindex(ctx); + uint32_t tableid = dplane_ctx_get_ifp_table_id(ctx); + enum zebra_iftype zif_type = dplane_ctx_get_ifp_zif_type(ctx); + struct interface *ifp; + struct zebra_ns *zns; + + zns = zebra_ns_lookup(ns_id); + if (!zns) { + zlog_err("Where is our namespace?"); + return; + } + + if (IS_ZEBRA_DEBUG_DPLANE) + zlog_debug("%s for %s(%u)", dplane_op2str(op), name, ifindex); + + ifp = if_lookup_by_name_per_ns(zns, name); + if (op == DPLANE_OP_INTF_DELETE) { + /* Delete interface notification from kernel */ + if (ifp == NULL) { + if (IS_ZEBRA_DEBUG_EVENT) + zlog_debug( + "Delete LINK received for unknown interface %s(%u)", + name, ifindex); + return; + } + + if (IS_ZEBRA_IF_BOND(ifp)) + zebra_l2if_update_bond(ifp, false); + if (IS_ZEBRA_IF_BOND_SLAVE(ifp)) + zebra_l2if_update_bond_slave(ifp, bond_ifindex, false); + /* Special handling for bridge or VxLAN interfaces. */ + if (IS_ZEBRA_IF_BRIDGE(ifp)) + zebra_l2_bridge_del(ifp); + else if (IS_ZEBRA_IF_VXLAN(ifp)) + zebra_l2_vxlanif_del(ifp); + + if_delete_update(&ifp); + + if (zif_type == ZEBRA_IF_VRF && !vrf_is_backend_netns()) + interface_vrf_change(op, ifindex, name, tableid, ns_id); + } else { + ifindex_t master_ifindex, bridge_ifindex, bond_ifindex, + link_ifindex; + enum zebra_slave_iftype zif_slave_type; + uint8_t bypass; + uint64_t flags; + vrf_id_t vrf_id; + uint32_t mtu; + ns_id_t link_nsid; + struct zebra_if *zif; + bool protodown, protodown_set, startup; + uint32_t rc_bitfield; + uint8_t old_hw_addr[INTERFACE_HWADDR_MAX]; + char *desc; + uint8_t family; + + /* If VRF, create or update the VRF structure itself. */ + if (zif_type == ZEBRA_IF_VRF && !vrf_is_backend_netns()) + interface_vrf_change(op, ifindex, name, tableid, ns_id); + + master_ifindex = dplane_ctx_get_ifp_master_ifindex(ctx); + zif_slave_type = dplane_ctx_get_ifp_zif_slave_type(ctx); + bridge_ifindex = dplane_ctx_get_ifp_bridge_ifindex(ctx); + bond_ifindex = dplane_ctx_get_ifp_bond_ifindex(ctx); + bypass = dplane_ctx_get_ifp_bypass(ctx); + flags = dplane_ctx_get_ifp_flags(ctx); + vrf_id = dplane_ctx_get_ifp_vrf_id(ctx); + mtu = dplane_ctx_get_ifp_mtu(ctx); + link_ifindex = dplane_ctx_get_ifp_link_ifindex(ctx); + link_nsid = dplane_ctx_get_ifp_link_nsid(ctx); + protodown_set = dplane_ctx_get_ifp_protodown_set(ctx); + protodown = dplane_ctx_get_ifp_protodown(ctx); + rc_bitfield = dplane_ctx_get_ifp_rc_bitfield(ctx); + startup = dplane_ctx_get_ifp_startup(ctx); + desc = dplane_ctx_get_ifp_desc(ctx); + family = dplane_ctx_get_ifp_family(ctx); + +#ifndef AF_BRIDGE + /* + * Work around to make free bsd happy at the moment + */ +#define AF_BRIDGE 7 +#endif + if (family == AF_BRIDGE) + return interface_bridge_handling(ctx, ifp, zif_type); + + if (ifp == NULL || + !CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE)) { + /* Add interface notification from kernel */ + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug( + "RTM_NEWLINK ADD for %s(%u) vrf_id %u type %d sl_type %d master %u", + name, ifindex, vrf_id, zif_type, + zif_slave_type, master_ifindex); + + if (ifp == NULL) { + /* unknown interface */ + ifp = if_get_by_name(name, vrf_id, NULL); + } else { + /* pre-configured interface, learnt now */ + if (ifp->vrf->vrf_id != vrf_id) + if_update_to_new_vrf(ifp, vrf_id); + } + + zif = ifp->info; + + /* Update interface information. */ + set_ifindex(ifp, ifindex, zns); + ifp->flags = flags; + ifp->mtu6 = ifp->mtu = mtu; + ifp->metric = 0; + ifp->speed = kernel_get_speed(ifp, NULL); + ifp->ptm_status = ZEBRA_PTM_STATUS_UNKNOWN; + ifp->txqlen = dplane_ctx_get_intf_txqlen(ctx); + + /* Set interface type */ + zebra_if_set_ziftype(ifp, zif_type, zif_slave_type); + if (IS_ZEBRA_IF_VRF(ifp)) + SET_FLAG(ifp->status, + ZEBRA_INTERFACE_VRF_LOOPBACK); + + /* Update link. */ + zebra_if_update_link(ifp, link_ifindex, link_nsid); + + ifp->ll_type = dplane_ctx_get_ifp_zltype(ctx); + interface_update_hw_addr(ctx, ifp); + + /* Inform clients, install any configured addresses. */ + if_add_update(ifp); + + /* + * Extract and save L2 interface information, take + * additional actions. + */ + interface_update_l2info(ctx, ifp, zif_type, 1, + link_nsid); + if (IS_ZEBRA_IF_BOND(ifp)) + zebra_l2if_update_bond(ifp, true); + if (IS_ZEBRA_IF_BRIDGE_SLAVE(ifp)) + zebra_l2if_update_bridge_slave( + ifp, bridge_ifindex, ns_id, + ZEBRA_BRIDGE_NO_ACTION); + else if (IS_ZEBRA_IF_BOND_SLAVE(ifp)) + zebra_l2if_update_bond_slave(ifp, bond_ifindex, + !!bypass); + + if (protodown_set) { + interface_if_protodown(ifp, protodown, + rc_bitfield); + if (startup) + if_sweep_protodown(zif); + } + + if (IS_ZEBRA_IF_BRIDGE(ifp)) { + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug( + "RTM_NEWLINK ADD for %s(%u), vlan-aware %d", + name, ifp->ifindex, + IS_ZEBRA_IF_BRIDGE_VLAN_AWARE( + zif)); + } + } else if (ifp->vrf->vrf_id != vrf_id) { + /* VRF change for an interface. */ + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug( + "RTM_NEWLINK vrf-change for %s(%u) vrf_id %u -> %u", + name, ifp->ifindex, ifp->vrf->vrf_id, + vrf_id); + + if_handle_vrf_change(ifp, vrf_id); + } else { + bool was_bridge_slave, was_bond_slave; + uint8_t chgflags = ZEBRA_BRIDGE_NO_ACTION; + + zif = ifp->info; + + /* Interface update. */ + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug( + "RTM_NEWLINK update for %s(%u) sl_type %d master %u", + name, ifp->ifindex, zif_slave_type, + master_ifindex); + + set_ifindex(ifp, ifindex, zns); + ifp->mtu6 = ifp->mtu = mtu; + ifp->metric = 0; + ifp->txqlen = dplane_ctx_get_intf_txqlen(ctx); + + /* + * Update interface type - NOTE: Only slave_type can + * change. + */ + was_bridge_slave = IS_ZEBRA_IF_BRIDGE_SLAVE(ifp); + was_bond_slave = IS_ZEBRA_IF_BOND_SLAVE(ifp); + zebra_if_set_ziftype(ifp, zif_type, zif_slave_type); + + memcpy(old_hw_addr, ifp->hw_addr, INTERFACE_HWADDR_MAX); + + /* Update link. */ + zebra_if_update_link(ifp, link_ifindex, link_nsid); + + ifp->ll_type = dplane_ctx_get_ifp_zltype(ctx); + interface_update_hw_addr(ctx, ifp); + + if (protodown_set) + interface_if_protodown(ifp, protodown, + rc_bitfield); + + if (if_is_no_ptm_operative(ifp)) { + bool is_up = if_is_operative(ifp); + + ifp->flags = flags; + if (!if_is_no_ptm_operative(ifp) || + CHECK_FLAG(zif->flags, + ZIF_FLAG_PROTODOWN)) { + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug( + "Intf %s(%u) has gone DOWN", + name, ifp->ifindex); + if_down(ifp); + rib_update(RIB_UPDATE_KERNEL); + } else if (if_is_operative(ifp)) { + bool mac_updated = false; + + /* + * Must notify client daemons of new + * interface status. + */ + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug( + "Intf %s(%u) PTM up, notifying clients", + name, ifp->ifindex); + if_up(ifp, !is_up); + + /* + * Update EVPN VNI when SVI MAC change + */ + if (memcmp(old_hw_addr, ifp->hw_addr, + INTERFACE_HWADDR_MAX)) + mac_updated = true; + if (IS_ZEBRA_IF_VLAN(ifp) && + mac_updated) { + struct interface *link_if; + + link_if = if_lookup_by_index_per_ns( + zebra_ns_lookup( + NS_DEFAULT), + link_ifindex); + if (link_if) + zebra_vxlan_svi_up( + ifp, link_if); + } else if (mac_updated && + IS_ZEBRA_IF_BRIDGE(ifp)) { + zlog_debug( + "Intf %s(%u) bridge changed MAC address", + name, ifp->ifindex); + chgflags = + ZEBRA_BRIDGE_MASTER_MAC_CHANGE; + } + } + } else { + ifp->flags = flags; + if (if_is_operative(ifp) && + !CHECK_FLAG(zif->flags, + ZIF_FLAG_PROTODOWN)) { + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug( + "Intf %s(%u) has come UP", + name, ifp->ifindex); + if_up(ifp, true); + if (IS_ZEBRA_IF_BRIDGE(ifp)) + chgflags = + ZEBRA_BRIDGE_MASTER_UP; + } else { + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug( + "Intf %s(%u) has gone DOWN", + name, ifp->ifindex); + if_down(ifp); + rib_update(RIB_UPDATE_KERNEL); + } + } + + /* + * Extract and save L2 interface information, take + * additional actions. + */ + interface_update_l2info(ctx, ifp, zif_type, 0, + link_nsid); + if (IS_ZEBRA_IF_BRIDGE(ifp)) + zebra_l2if_update_bridge(ifp, chgflags); + if (IS_ZEBRA_IF_BOND(ifp)) + zebra_l2if_update_bond(ifp, true); + if (IS_ZEBRA_IF_BRIDGE_SLAVE(ifp) || was_bridge_slave) + zebra_l2if_update_bridge_slave( + ifp, bridge_ifindex, ns_id, chgflags); + else if (IS_ZEBRA_IF_BOND_SLAVE(ifp) || was_bond_slave) + zebra_l2if_update_bond_slave(ifp, bond_ifindex, + !!bypass); + if (IS_ZEBRA_IF_BRIDGE(ifp)) { + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug( + "RTM_NEWLINK update for %s(%u), vlan-aware %d", + name, ifp->ifindex, + IS_ZEBRA_IF_BRIDGE_VLAN_AWARE( + zif)); + } + } + + zif = ifp->info; + if (zif) { + XFREE(MTYPE_ZIF_DESC, zif->desc); + if (desc[0]) + zif->desc = XSTRDUP(MTYPE_ZIF_DESC, desc); + } + } +} + void zebra_if_dplane_result(struct zebra_dplane_ctx *ctx) { struct zebra_ns *zns; @@ -1501,83 +2242,22 @@ void zebra_if_dplane_result(struct zebra_dplane_ctx *ctx) } ifp = if_lookup_by_index_per_ns(zns, ifindex); - if (ifp == NULL) { - if (op != DPLANE_OP_INTF_NETCONFIG || - (ifindex != -1 && ifindex != -2)) { - if (IS_ZEBRA_DEBUG_KERNEL) - zlog_debug( - "%s: can't find ifp at nsid %u index %d", - __func__, ns_id, ifindex); - - return; - } - } - switch (op) { - case DPLANE_OP_INTF_ADDR_ADD: - case DPLANE_OP_INTF_ADDR_DEL: + if (op == DPLANE_OP_INTF_ADDR_ADD || op == DPLANE_OP_INTF_ADDR_DEL) { zebra_if_addr_update_ctx(ctx, ifp); - break; - - case DPLANE_OP_INTF_INSTALL: - case DPLANE_OP_INTF_UPDATE: - case DPLANE_OP_INTF_DELETE: - zebra_if_update_ctx(ctx, ifp); - break; - - case DPLANE_OP_INTF_NETCONFIG: + } else if (op == DPLANE_OP_INTF_INSTALL || + op == DPLANE_OP_INTF_UPDATE || op == DPLANE_OP_INTF_DELETE) { + /* + * Queued from the dplane means it is something + * that we need to handle( create/delete the + * interface as needed ) + */ + if (dp_res == ZEBRA_DPLANE_REQUEST_QUEUED) + zebra_if_dplane_ifp_handling(ctx); + else + zebra_if_update_ctx(ctx, ifp); + } else if (op == DPLANE_OP_INTF_NETCONFIG) { zebra_if_netconf_update_ctx(ctx, ifp, ifindex); - break; - - case DPLANE_OP_ROUTE_INSTALL: - case DPLANE_OP_ROUTE_UPDATE: - case DPLANE_OP_ROUTE_DELETE: - case DPLANE_OP_NH_DELETE: - case DPLANE_OP_NH_INSTALL: - case DPLANE_OP_NH_UPDATE: - case DPLANE_OP_ROUTE_NOTIFY: - case DPLANE_OP_LSP_INSTALL: - case DPLANE_OP_LSP_UPDATE: - case DPLANE_OP_LSP_DELETE: - case DPLANE_OP_LSP_NOTIFY: - case DPLANE_OP_PW_INSTALL: - case DPLANE_OP_PW_UNINSTALL: - case DPLANE_OP_SYS_ROUTE_ADD: - case DPLANE_OP_SYS_ROUTE_DELETE: - case DPLANE_OP_ADDR_INSTALL: - case DPLANE_OP_ADDR_UNINSTALL: - case DPLANE_OP_MAC_INSTALL: - case DPLANE_OP_MAC_DELETE: - case DPLANE_OP_NEIGH_INSTALL: - case DPLANE_OP_NEIGH_UPDATE: - case DPLANE_OP_NEIGH_DELETE: - case DPLANE_OP_NEIGH_IP_INSTALL: - case DPLANE_OP_NEIGH_IP_DELETE: - case DPLANE_OP_VTEP_ADD: - case DPLANE_OP_VTEP_DELETE: - case DPLANE_OP_RULE_ADD: - case DPLANE_OP_RULE_DELETE: - case DPLANE_OP_RULE_UPDATE: - case DPLANE_OP_NEIGH_DISCOVER: - case DPLANE_OP_BR_PORT_UPDATE: - case DPLANE_OP_NONE: - case DPLANE_OP_IPTABLE_ADD: - case DPLANE_OP_IPTABLE_DELETE: - case DPLANE_OP_IPSET_ADD: - case DPLANE_OP_IPSET_DELETE: - case DPLANE_OP_IPSET_ENTRY_ADD: - case DPLANE_OP_IPSET_ENTRY_DELETE: - case DPLANE_OP_NEIGH_TABLE_UPDATE: - case DPLANE_OP_GRE_SET: - case DPLANE_OP_TC_QDISC_INSTALL: - case DPLANE_OP_TC_QDISC_UNINSTALL: - case DPLANE_OP_TC_CLASS_ADD: - case DPLANE_OP_TC_CLASS_DELETE: - case DPLANE_OP_TC_CLASS_UPDATE: - case DPLANE_OP_TC_FILTER_ADD: - case DPLANE_OP_TC_FILTER_DELETE: - case DPLANE_OP_TC_FILTER_UPDATE: - break; /* should never hit here */ } } @@ -1617,6 +2297,12 @@ static void connected_dump_vty(struct vty *vty, json_object *json, vty_out(vty, " secondary"); if (json) + json_object_boolean_add(json_addr, "noPrefixRoute", + CHECK_FLAG(connected->flags, ZEBRA_IFA_NOPREFIXROUTE)); + else if (CHECK_FLAG(connected->flags, ZEBRA_IFA_NOPREFIXROUTE)) + vty_out(vty, " noprefixroute"); + + if (json) json_object_boolean_add( json_addr, "unnumbered", CHECK_FLAG(connected->flags, ZEBRA_IFA_UNNUMBERED)); @@ -1692,9 +2378,6 @@ static const char *zebra_ziftype_2str(enum zebra_iftype zif_type) case ZEBRA_IF_BOND: return "bond"; - case ZEBRA_IF_BOND_SLAVE: - return "bond_slave"; - case ZEBRA_IF_MACVLAN: return "macvlan"; @@ -1768,34 +2451,27 @@ static void ifs_dump_brief_vty(struct vty *vty, struct vrf *vrf) } uint32_t v6_list_size = 0; - for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, connected)) { + frr_each (if_connected, ifp->connected, connected) { if (CHECK_FLAG(connected->conf, ZEBRA_IFC_REAL) && (connected->address->family == AF_INET6)) v6_list_size++; } - for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, connected)) { - if (CHECK_FLAG(connected->conf, ZEBRA_IFC_REAL) - && !CHECK_FLAG(connected->flags, - ZEBRA_IFA_SECONDARY) - && (connected->address->family == AF_INET6)) { + frr_each (if_connected, ifp->connected, connected) { + if (!CHECK_FLAG(connected->flags, ZEBRA_IFA_SECONDARY) && + (connected->address->family == AF_INET6)) { p = connected->address; - /* Don't print link local pfx */ - if (!IN6_IS_ADDR_LINKLOCAL(&p->u.prefix6)) { - if (first_pfx_printed) { - /* padding to prepare row only - * for ip addr */ - vty_out(vty, "%-40s", ""); - if (v6_list_size > 1) - vty_out(vty, "+ "); - vty_out(vty, "%pFX\n", p); - } else { - if (v6_list_size > 1) - vty_out(vty, "+ "); - vty_out(vty, "%pFX\n", p); - } - first_pfx_printed = true; - break; + if (first_pfx_printed) { + vty_out(vty, "%-40s", ""); + if (v6_list_size > 1) + vty_out(vty, "+ "); + vty_out(vty, "%pFX\n", p); + } else { + if (v6_list_size > 1) + vty_out(vty, "+ "); + vty_out(vty, "%pFX\n", p); } + first_pfx_printed = true; + break; } } if (!first_pfx_printed) @@ -1807,7 +2483,6 @@ static void ifs_dump_brief_vty(struct vty *vty, struct vrf *vrf) static void ifs_dump_brief_vty_json(json_object *json, struct vrf *vrf) { struct connected *connected; - struct listnode *node; struct interface *ifp; FOR_ALL_INTERFACES (vrf, ifp) { @@ -1823,13 +2498,8 @@ static void ifs_dump_brief_vty_json(json_object *json, struct vrf *vrf) json_addrs = json_object_new_array(); json_object_object_add(json_if, "addresses", json_addrs); - for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, connected)) { - if (CHECK_FLAG(connected->conf, ZEBRA_IFC_REAL) - && !CHECK_FLAG(connected->flags, - ZEBRA_IFA_SECONDARY) - && !(connected->address->family == AF_INET6 - && IN6_IS_ADDR_LINKLOCAL( - &connected->address->u.prefix6))) { + frr_each (if_connected, ifp->connected, connected) { + if (!CHECK_FLAG(connected->flags, ZEBRA_IFA_SECONDARY)) { char buf[PREFIX2STR_BUFFER]; json_array_string_add( @@ -1990,8 +2660,8 @@ static void if_dump_vty(struct vty *vty, struct interface *ifp) return; } - vty_out(vty, " index %d metric %d mtu %d speed %u ", ifp->ifindex, - ifp->metric, ifp->mtu, ifp->speed); + vty_out(vty, " index %d metric %d mtu %d speed %u txqlen %u", + ifp->ifindex, ifp->metric, ifp->mtu, ifp->speed, ifp->txqlen); if (ifp->mtu6 != ifp->mtu) vty_out(vty, "mtu6 %d ", ifp->mtu6); vty_out(vty, "\n flags: %s\n", if_flag_dump(ifp->flags)); @@ -2036,9 +2706,8 @@ static void if_dump_vty(struct vty *vty, struct interface *ifp) connected_dump_vty(vty, NULL, connected); } - for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, connected)) { - if (CHECK_FLAG(connected->conf, ZEBRA_IFC_REAL) - && (connected->address->family == AF_INET6)) + frr_each (if_connected, ifp->connected, connected) { + if (connected->address->family == AF_INET6) connected_dump_vty(vty, NULL, connected); } @@ -2170,8 +2839,8 @@ static void if_dump_vty(struct vty *vty, struct interface *ifp) " Link Delay Variation %u (micro-sec.)\n", iflp->delay_var); if (IS_PARAM_SET(iflp, LP_PKT_LOSS)) - vty_out(vty, " Link Packet Loss %g (in %%)\n", - iflp->pkt_loss); + vty_out(vty, " Link Packet Loss %f (in %%)\n", + (double)iflp->pkt_loss * LOSS_PRECISION); if (IS_PARAM_SET(iflp, LP_AVA_BW)) vty_out(vty, " Available Bandwidth %g (Byte/s)\n", iflp->ava_bw); @@ -2345,7 +3014,7 @@ static void if_dump_vty_json(struct vty *vty, struct interface *ifp, json_object_string_add(json_if, "lastLinkDown", zebra_if->down_last); - zebra_ptm_show_status(vty, json, ifp); + zebra_ptm_show_status(vty, json_if, ifp); json_object_string_add(json_if, "vrfName", ifp->vrf->name); @@ -2378,6 +3047,7 @@ static void if_dump_vty_json(struct vty *vty, struct interface *ifp, if (ifp->mtu6 != ifp->mtu) json_object_int_add(json_if, "mtu6", ifp->mtu6); json_object_int_add(json_if, "speed", ifp->speed); + json_object_int_add(json_if, "txqlen", ifp->txqlen); json_object_string_add(json_if, "flags", if_flag_dump(ifp->flags)); /* Hardware address. */ @@ -2412,9 +3082,8 @@ static void if_dump_vty_json(struct vty *vty, struct interface *ifp, connected_dump_vty(vty, json_addrs, connected); } - for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, connected)) { - if (CHECK_FLAG(connected->conf, ZEBRA_IFC_REAL) - && (connected->address->family == AF_INET6)) + frr_each (if_connected, ifp->connected, connected) { + if (connected->address->family == AF_INET6) connected_dump_vty(vty, json_addrs, connected); } @@ -2571,7 +3240,8 @@ static void if_dump_vty_json(struct vty *vty, struct interface *ifp, iflp->delay_var); if (IS_PARAM_SET(iflp, LP_PKT_LOSS)) json_object_double_add(json_te, "linkPacketLoss", - iflp->pkt_loss); + (double)iflp->pkt_loss * + LOSS_PRECISION); if (IS_PARAM_SET(iflp, LP_AVA_BW)) json_object_double_add(json_te, "availableBandwidth", iflp->ava_bw); @@ -2955,66 +3625,43 @@ DEFUN (show_interface_desc_vrf_all, return CMD_SUCCESS; } -int if_multicast_set(struct interface *ifp) +void if_arp(struct interface *ifp, bool enable) { - struct zebra_if *if_data; + int ret; - if (CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE)) { - if (if_set_flags(ifp, IFF_MULTICAST) < 0) { - zlog_debug("Can't set multicast flag on interface %s", - ifp->name); - return -1; - } - if_refresh(ifp); + if (!CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE)) + return; + + if (enable) + ret = if_unset_flags(ifp, IFF_NOARP); + else + ret = if_set_flags(ifp, IFF_NOARP); + + if (ret < 0) { + zlog_debug("Can't %sset noarp flag on interface %s", + enable ? "" : "un", ifp->name); + return; } - if_data = ifp->info; - if_data->multicast = IF_ZEBRA_DATA_ON; - return 0; + if_refresh(ifp); } -DEFUN (multicast, - multicast_cmd, - "multicast", - "Set multicast flag to interface\n") +int if_multicast_set(struct interface *ifp) { - VTY_DECLVAR_CONTEXT(interface, ifp); - int ret; struct zebra_if *if_data; if (CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE)) { - ret = if_set_flags(ifp, IFF_MULTICAST); - if (ret < 0) { - vty_out(vty, "Can't set multicast flag\n"); - return CMD_WARNING_CONFIG_FAILED; + if (if_set_flags(ifp, IFF_MULTICAST) < 0) { + zlog_debug("Can't set multicast flag on interface %s", + ifp->name); + return -1; } if_refresh(ifp); } if_data = ifp->info; if_data->multicast = IF_ZEBRA_DATA_ON; - return CMD_SUCCESS; -} - -DEFPY (mpls, - mpls_cmd, - "[no] mpls enable", - NO_STR - MPLS_STR - "Set mpls to be on for the interface\n") -{ - VTY_DECLVAR_CONTEXT(interface, ifp); - struct zebra_if *if_data = ifp->info; - - if (no) { - dplane_intf_mpls_modify_state(ifp, false); - if_data->mpls = IF_ZEBRA_DATA_UNSPEC; - } else { - dplane_intf_mpls_modify_state(ifp, true); - if_data->mpls = IF_ZEBRA_DATA_ON; - } - - return CMD_SUCCESS; + return 0; } int if_multicast_unset(struct interface *ifp) @@ -3035,30 +3682,6 @@ int if_multicast_unset(struct interface *ifp) return 0; } -DEFUN (no_multicast, - no_multicast_cmd, - "no multicast", - NO_STR - "Unset multicast flag to interface\n") -{ - VTY_DECLVAR_CONTEXT(interface, ifp); - int ret; - struct zebra_if *if_data; - - if (CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE)) { - ret = if_unset_flags(ifp, IFF_MULTICAST); - if (ret < 0) { - vty_out(vty, "Can't unset multicast flag\n"); - return CMD_WARNING_CONFIG_FAILED; - } - if_refresh(ifp); - } - if_data = ifp->info; - if_data->multicast = IF_ZEBRA_DATA_OFF; - - return CMD_SUCCESS; -} - int if_linkdetect(struct interface *ifp, bool detect) { int if_was_operative; @@ -3082,30 +3705,6 @@ int if_linkdetect(struct interface *ifp, bool detect) return 0; } -DEFUN(linkdetect, linkdetect_cmd, "link-detect", - "Enable link detection on interface\n") -{ - VTY_DECLVAR_CONTEXT(interface, ifp); - - if_linkdetect(ifp, true); - - return CMD_SUCCESS; -} - - -DEFUN (no_linkdetect, - no_linkdetect_cmd, - "no link-detect", - NO_STR - "Disable link detection on interface\n") -{ - VTY_DECLVAR_CONTEXT(interface, ifp); - - if_linkdetect(ifp, false); - - return CMD_SUCCESS; -} - int if_shutdown(struct interface *ifp) { struct zebra_if *if_data; @@ -3125,31 +3724,6 @@ int if_shutdown(struct interface *ifp) return 0; } -DEFUN (shutdown_if, - shutdown_if_cmd, - "shutdown", - "Shutdown the selected interface\n") -{ - VTY_DECLVAR_CONTEXT(interface, ifp); - int ret; - struct zebra_if *if_data; - - if (ifp->ifindex != IFINDEX_INTERNAL) { - /* send RA lifetime of 0 before stopping. rfc4861/6.2.5 */ - rtadv_stop_ra(ifp); - ret = if_unset_flags(ifp, IFF_UP); - if (ret < 0) { - vty_out(vty, "Can't shutdown interface\n"); - return CMD_WARNING_CONFIG_FAILED; - } - if_refresh(ifp); - } - if_data = ifp->info; - if_data->shutdown = IF_ZEBRA_DATA_ON; - - return CMD_SUCCESS; -} - int if_no_shutdown(struct interface *ifp) { struct zebra_if *if_data; @@ -3174,984 +3748,56 @@ int if_no_shutdown(struct interface *ifp) return 0; } -DEFUN (no_shutdown_if, - no_shutdown_if_cmd, - "no shutdown", - NO_STR - "Shutdown the selected interface\n") -{ - VTY_DECLVAR_CONTEXT(interface, ifp); - int ret; - struct zebra_if *if_data; - - if (ifp->ifindex != IFINDEX_INTERNAL) { - ret = if_set_flags(ifp, IFF_UP | IFF_RUNNING); - if (ret < 0) { - vty_out(vty, "Can't up interface\n"); - return CMD_WARNING_CONFIG_FAILED; - } - if_refresh(ifp); - - /* Some addresses (in particular, IPv6 addresses on Linux) get - * removed when the interface goes down. They need to be - * readded. - */ - if_addr_wakeup(ifp); - } - - if_data = ifp->info; - if_data->shutdown = IF_ZEBRA_DATA_OFF; - - return CMD_SUCCESS; -} - -DEFUN (bandwidth_if, - bandwidth_if_cmd, - "bandwidth (1-100000)", - "Set bandwidth informational parameter\n" - "Bandwidth in megabits\n") -{ - int idx_number = 1; - VTY_DECLVAR_CONTEXT(interface, ifp); - unsigned int bandwidth; - - bandwidth = strtol(argv[idx_number]->arg, NULL, 10); - - /* bandwidth range is <1-100000> */ - if (bandwidth < 1 || bandwidth > 100000) { - vty_out(vty, "Bandwidth is invalid\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - ifp->bandwidth = bandwidth; - - /* force protocols to recalculate routes due to cost change */ - if (if_is_operative(ifp)) - zebra_interface_up_update(ifp); - - return CMD_SUCCESS; -} - -DEFUN (no_bandwidth_if, - no_bandwidth_if_cmd, - "no bandwidth [(1-100000)]", - NO_STR - "Set bandwidth informational parameter\n" - "Bandwidth in megabits\n") -{ - VTY_DECLVAR_CONTEXT(interface, ifp); - - ifp->bandwidth = 0; - - /* force protocols to recalculate routes due to cost change */ - if (if_is_operative(ifp)) - zebra_interface_up_update(ifp); - - return CMD_SUCCESS; -} - - -struct cmd_node link_params_node = { - .name = "link-params", - .node = LINK_PARAMS_NODE, - .parent_node = INTERFACE_NODE, - .prompt = "%s(config-link-params)# ", - .no_xpath = true, -}; - -static void link_param_cmd_set_uint32(struct interface *ifp, uint32_t *field, - uint32_t type, uint32_t value) +void link_param_cmd_set_uint32(struct interface *ifp, uint32_t *field, + uint32_t type, uint32_t value) { /* Update field as needed */ if (IS_PARAM_UNSET(ifp->link_params, type) || *field != value) { *field = value; SET_PARAM(ifp->link_params, type); - - /* force protocols to update LINK STATE due to parameters change - */ - if (if_is_operative(ifp)) - zebra_interface_parameters_update(ifp); } } -static void link_param_cmd_set_float(struct interface *ifp, float *field, - uint32_t type, float value) -{ +void link_param_cmd_set_float(struct interface *ifp, float *field, + uint32_t type, float value) +{ /* Update field as needed */ if (IS_PARAM_UNSET(ifp->link_params, type) || *field != value) { *field = value; SET_PARAM(ifp->link_params, type); - - /* force protocols to update LINK STATE due to parameters change - */ - if (if_is_operative(ifp)) - zebra_interface_parameters_update(ifp); } } -static void link_param_cmd_unset(struct interface *ifp, uint32_t type) +void link_param_cmd_unset(struct interface *ifp, uint32_t type) { if (ifp->link_params == NULL) return; /* Unset field */ UNSET_PARAM(ifp->link_params, type); - - /* force protocols to update LINK STATE due to parameters change */ - if (if_is_operative(ifp)) - zebra_interface_parameters_update(ifp); -} - -DEFUN_NOSH (link_params, - link_params_cmd, - "link-params", - LINK_PARAMS_STR) -{ - /* vty->qobj_index stays the same @ interface pointer */ - vty->node = LINK_PARAMS_NODE; - - return CMD_SUCCESS; -} - -DEFUN_NOSH (exit_link_params, - exit_link_params_cmd, - "exit-link-params", - "Exit from Link Params configuration mode\n") -{ - if (vty->node == LINK_PARAMS_NODE) - vty->node = INTERFACE_NODE; - return CMD_SUCCESS; -} - -/* Specific Traffic Engineering parameters commands */ -DEFUN (link_params_enable, - link_params_enable_cmd, - "enable", - "Activate link parameters on this interface\n") -{ - VTY_DECLVAR_CONTEXT(interface, ifp); - - /* This command could be issue at startup, when activate MPLS TE */ - /* on a new interface or after a ON / OFF / ON toggle */ - /* In all case, TE parameters are reset to their default factory */ - if (IS_ZEBRA_DEBUG_EVENT || IS_ZEBRA_DEBUG_MPLS) - zlog_debug( - "Link-params: enable TE link parameters on interface %s", - ifp->name); - - if (!if_link_params_get(ifp)) - if_link_params_enable(ifp); - - /* force protocols to update LINK STATE due to parameters change */ - if (if_is_operative(ifp)) - zebra_interface_parameters_update(ifp); - - return CMD_SUCCESS; -} - -DEFUN (no_link_params_enable, - no_link_params_enable_cmd, - "no enable", - NO_STR - "Disable link parameters on this interface\n") -{ - char xpath[XPATH_MAXLEN]; - int ret; - VTY_DECLVAR_CONTEXT(interface, ifp); - - if (IS_ZEBRA_DEBUG_EVENT || IS_ZEBRA_DEBUG_MPLS) - zlog_debug("MPLS-TE: disable TE link parameters on interface %s", - ifp->name); - - if_link_params_free(ifp); - - snprintf( - xpath, sizeof(xpath), - "/frr-interface:lib/interface[name='%s']/frr-zebra:zebra/link-params/affinities", - ifp->name); - if (yang_dnode_exists(running_config->dnode, xpath)) - nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL); - - ret = nb_cli_apply_changes(vty, NULL); - - if (ret != CMD_SUCCESS) - return ret; - - /* force protocols to update LINK STATE due to parameters change */ - if (if_is_operative(ifp)) - zebra_interface_parameters_update(ifp); - - return CMD_SUCCESS; } -/* STANDARD TE metrics */ -DEFUN (link_params_metric, - link_params_metric_cmd, - "metric (0-4294967295)", - "Link metric for MPLS-TE purpose\n" - "Metric value in decimal\n") -{ - int idx_number = 1; - VTY_DECLVAR_CONTEXT(interface, ifp); - struct if_link_params *iflp = if_link_params_get(ifp); - uint32_t metric; - - metric = strtoul(argv[idx_number]->arg, NULL, 10); - - if (!iflp) - iflp = if_link_params_enable(ifp); - - /* Update TE metric if needed */ - link_param_cmd_set_uint32(ifp, &iflp->te_metric, LP_TE_METRIC, metric); - - return CMD_SUCCESS; -} - -DEFUN (no_link_params_metric, - no_link_params_metric_cmd, - "no metric", - NO_STR - "Disable Link Metric on this interface\n") -{ - VTY_DECLVAR_CONTEXT(interface, ifp); - - /* Unset TE Metric */ - link_param_cmd_unset(ifp, LP_TE_METRIC); - - return CMD_SUCCESS; -} - -DEFUN (link_params_maxbw, - link_params_maxbw_cmd, - "max-bw BANDWIDTH", - "Maximum bandwidth that can be used\n" - "Bytes/second (IEEE floating point format)\n") -{ - int idx_bandwidth = 1; - VTY_DECLVAR_CONTEXT(interface, ifp); - struct if_link_params *iflp = if_link_params_get(ifp); - - float bw; - - if (sscanf(argv[idx_bandwidth]->arg, "%g", &bw) != 1) { - vty_out(vty, "link_params_maxbw: fscanf: %s\n", - safe_strerror(errno)); - return CMD_WARNING_CONFIG_FAILED; - } - - /* Check that Maximum bandwidth is not lower than other bandwidth - * parameters */ - if (iflp && ((bw <= iflp->max_rsv_bw) || (bw <= iflp->unrsv_bw[0]) || - (bw <= iflp->unrsv_bw[1]) || (bw <= iflp->unrsv_bw[2]) || - (bw <= iflp->unrsv_bw[3]) || (bw <= iflp->unrsv_bw[4]) || - (bw <= iflp->unrsv_bw[5]) || (bw <= iflp->unrsv_bw[6]) || - (bw <= iflp->unrsv_bw[7]) || (bw <= iflp->ava_bw) || - (bw <= iflp->res_bw) || (bw <= iflp->use_bw))) { - vty_out(vty, - "Maximum Bandwidth could not be lower than others bandwidth\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - if (!iflp) - iflp = if_link_params_enable(ifp); - - /* Update Maximum Bandwidth if needed */ - link_param_cmd_set_float(ifp, &iflp->max_bw, LP_MAX_BW, bw); - - return CMD_SUCCESS; -} - -DEFUN (link_params_max_rsv_bw, - link_params_max_rsv_bw_cmd, - "max-rsv-bw BANDWIDTH", - "Maximum bandwidth that may be reserved\n" - "Bytes/second (IEEE floating point format)\n") -{ - int idx_bandwidth = 1; - VTY_DECLVAR_CONTEXT(interface, ifp); - struct if_link_params *iflp = if_link_params_get(ifp); - float bw; - - if (sscanf(argv[idx_bandwidth]->arg, "%g", &bw) != 1) { - vty_out(vty, "link_params_max_rsv_bw: fscanf: %s\n", - safe_strerror(errno)); - return CMD_WARNING_CONFIG_FAILED; - } - - /* Check that bandwidth is not greater than maximum bandwidth parameter - */ - if (iflp && bw > iflp->max_bw) { - vty_out(vty, - "Maximum Reservable Bandwidth could not be greater than Maximum Bandwidth (%g)\n", - iflp->max_bw); - return CMD_WARNING_CONFIG_FAILED; - } - - if (!iflp) - iflp = if_link_params_enable(ifp); - - /* Update Maximum Reservable Bandwidth if needed */ - link_param_cmd_set_float(ifp, &iflp->max_rsv_bw, LP_MAX_RSV_BW, bw); - - return CMD_SUCCESS; -} - -DEFUN (link_params_unrsv_bw, - link_params_unrsv_bw_cmd, - "unrsv-bw (0-7) BANDWIDTH", - "Unreserved bandwidth at each priority level\n" - "Priority\n" - "Bytes/second (IEEE floating point format)\n") -{ - int idx_number = 1; - int idx_bandwidth = 2; - VTY_DECLVAR_CONTEXT(interface, ifp); - struct if_link_params *iflp = if_link_params_get(ifp); - int priority; - float bw; - - /* We don't have to consider about range check here. */ - if (sscanf(argv[idx_number]->arg, "%d", &priority) != 1) { - vty_out(vty, "link_params_unrsv_bw: fscanf: %s\n", - safe_strerror(errno)); - return CMD_WARNING_CONFIG_FAILED; - } - - if (sscanf(argv[idx_bandwidth]->arg, "%g", &bw) != 1) { - vty_out(vty, "link_params_unrsv_bw: fscanf: %s\n", - safe_strerror(errno)); - return CMD_WARNING_CONFIG_FAILED; - } - - /* Check that bandwidth is not greater than maximum bandwidth parameter - */ - if (iflp && bw > iflp->max_bw) { - vty_out(vty, - "UnReserved Bandwidth could not be greater than Maximum Bandwidth (%g)\n", - iflp->max_bw); - return CMD_WARNING_CONFIG_FAILED; - } - - if (!iflp) - iflp = if_link_params_enable(ifp); - - /* Update Unreserved Bandwidth if needed */ - link_param_cmd_set_float(ifp, &iflp->unrsv_bw[priority], LP_UNRSV_BW, - bw); - - return CMD_SUCCESS; -} - -DEFPY_YANG(link_params_admin_grp, link_params_admin_grp_cmd, - "admin-grp BITPATTERN", - "Administrative group membership\n" - "32-bit Hexadecimal value (e.g. 0xa1)\n") -{ - char xpath[XPATH_MAXLEN]; - int idx_bitpattern = 1; - unsigned long value; - char value_str[11]; - - VTY_DECLVAR_CONTEXT(interface, ifp); - - snprintf( - xpath, sizeof(xpath), - "/frr-interface:lib/interface[name='%s']/frr-zebra:zebra/link-params/affinities", - ifp->name); - if (yang_dnode_exists(running_config->dnode, xpath)) { - vty_out(vty, - "cannot use the admin-grp command when affinity is set\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - if (sscanf(argv[idx_bitpattern]->arg, "0x%lx", &value) != 1) { - vty_out(vty, "link_params_admin_grp: fscanf: %s\n", - safe_strerror(errno)); - return CMD_WARNING_CONFIG_FAILED; - } - - if (value > 0xFFFFFFFF) { - vty_out(vty, "value must be not be superior to 0xFFFFFFFF\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - snprintf(value_str, sizeof(value_str), "%ld", value); - - nb_cli_enqueue_change( - vty, "./frr-zebra:zebra/link-params/legacy-admin-group", - NB_OP_MODIFY, value_str); - - return nb_cli_apply_changes(vty, NULL); -} - -DEFPY_YANG(no_link_params_admin_grp, no_link_params_admin_grp_cmd, - "no admin-grp", - NO_STR "Disable Administrative group membership on this interface\n") -{ - nb_cli_enqueue_change( - vty, "./frr-zebra:zebra/link-params/legacy-admin-group", - NB_OP_DESTROY, NULL); - - return nb_cli_apply_changes(vty, NULL); -} - -/* RFC5392 & RFC5316: INTER-AS */ -DEFUN (link_params_inter_as, - link_params_inter_as_cmd, - "neighbor A.B.C.D as (1-4294967295)", - "Configure remote ASBR information (Neighbor IP address and AS number)\n" - "Remote IP address in dot decimal A.B.C.D\n" - "Remote AS number\n" - "AS number in the range <1-4294967295>\n") -{ - int idx_ipv4 = 1; - int idx_number = 3; - - VTY_DECLVAR_CONTEXT(interface, ifp); - struct if_link_params *iflp = if_link_params_get(ifp); - struct in_addr addr; - uint32_t as; - - if (!inet_aton(argv[idx_ipv4]->arg, &addr)) { - vty_out(vty, "Please specify Router-Addr by A.B.C.D\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - if (!iflp) - iflp = if_link_params_enable(ifp); - - as = strtoul(argv[idx_number]->arg, NULL, 10); - - /* Update Remote IP and Remote AS fields if needed */ - if (IS_PARAM_UNSET(iflp, LP_RMT_AS) || iflp->rmt_as != as - || iflp->rmt_ip.s_addr != addr.s_addr) { - - iflp->rmt_as = as; - iflp->rmt_ip.s_addr = addr.s_addr; - SET_PARAM(iflp, LP_RMT_AS); - - /* force protocols to update LINK STATE due to parameters change - */ - if (if_is_operative(ifp)) - zebra_interface_parameters_update(ifp); - } - return CMD_SUCCESS; -} - -DEFUN (no_link_params_inter_as, - no_link_params_inter_as_cmd, - "no neighbor", - NO_STR - "Remove Neighbor IP address and AS number for Inter-AS TE\n") -{ - VTY_DECLVAR_CONTEXT(interface, ifp); - struct if_link_params *iflp = if_link_params_get(ifp); - - if (!iflp) - return CMD_SUCCESS; - - /* Reset Remote IP and AS neighbor */ - iflp->rmt_as = 0; - iflp->rmt_ip.s_addr = 0; - UNSET_PARAM(iflp, LP_RMT_AS); - - /* force protocols to update LINK STATE due to parameters change */ - if (if_is_operative(ifp)) - zebra_interface_parameters_update(ifp); - - return CMD_SUCCESS; -} - -/* RFC7471: OSPF Traffic Engineering (TE) Metric extensions & - * draft-ietf-isis-metric-extensions-07.txt */ -DEFUN (link_params_delay, - link_params_delay_cmd, - "delay (0-16777215) [min (0-16777215) max (0-16777215)]", - "Unidirectional Average Link Delay\n" - "Average delay in micro-second as decimal (0...16777215)\n" - "Minimum delay\n" - "Minimum delay in micro-second as decimal (0...16777215)\n" - "Maximum delay\n" - "Maximum delay in micro-second as decimal (0...16777215)\n") -{ - /* Get and Check new delay values */ - uint32_t delay = 0, low = 0, high = 0; - delay = strtoul(argv[1]->arg, NULL, 10); - if (argc == 6) { - low = strtoul(argv[3]->arg, NULL, 10); - high = strtoul(argv[5]->arg, NULL, 10); - } - - VTY_DECLVAR_CONTEXT(interface, ifp); - struct if_link_params *iflp = if_link_params_get(ifp); - uint8_t update = 0; - - if (argc == 2) { - /* - * Check new delay value against old Min and Max delays if set - * - * RFC 7471 Section 4.2.7: - * It is possible for min delay and max delay to be - * the same value. - * - * Therefore, it is also allowed that the average - * delay be equal to the min delay or max delay. - */ - if (iflp && IS_PARAM_SET(iflp, LP_MM_DELAY) && - (delay < iflp->min_delay || delay > iflp->max_delay)) { - vty_out(vty, - "Average delay should be in range Min (%d) - Max (%d) delay\n", - iflp->min_delay, iflp->max_delay); - return CMD_WARNING_CONFIG_FAILED; - } - - if (!iflp) - iflp = if_link_params_enable(ifp); - - /* Update delay if value is not set or change */ - if (IS_PARAM_UNSET(iflp, LP_DELAY) || iflp->av_delay != delay) { - iflp->av_delay = delay; - SET_PARAM(iflp, LP_DELAY); - update = 1; - } - /* Unset Min and Max delays if already set */ - if (IS_PARAM_SET(iflp, LP_MM_DELAY)) { - iflp->min_delay = 0; - iflp->max_delay = 0; - UNSET_PARAM(iflp, LP_MM_DELAY); - update = 1; - } - } else { - /* - * Check new delays value coherency. See above note - * regarding average delay equal to min/max allowed - */ - if (delay < low || delay > high) { - vty_out(vty, - "Average delay should be in range Min (%d) - Max (%d) delay\n", - low, high); - return CMD_WARNING_CONFIG_FAILED; - } - - if (!iflp) - iflp = if_link_params_enable(ifp); - - /* Update Delays if needed */ - if (IS_PARAM_UNSET(iflp, LP_DELAY) - || IS_PARAM_UNSET(iflp, LP_MM_DELAY) - || iflp->av_delay != delay || iflp->min_delay != low - || iflp->max_delay != high) { - iflp->av_delay = delay; - SET_PARAM(iflp, LP_DELAY); - iflp->min_delay = low; - iflp->max_delay = high; - SET_PARAM(iflp, LP_MM_DELAY); - update = 1; - } - } - - /* force protocols to update LINK STATE due to parameters change */ - if (update == 1 && if_is_operative(ifp)) - zebra_interface_parameters_update(ifp); - - return CMD_SUCCESS; -} - -DEFUN (no_link_params_delay, - no_link_params_delay_cmd, - "no delay", - NO_STR - "Disable Unidirectional Average, Min & Max Link Delay on this interface\n") -{ - VTY_DECLVAR_CONTEXT(interface, ifp); - struct if_link_params *iflp = if_link_params_get(ifp); - - if (!iflp) - return CMD_SUCCESS; - - /* Unset Delays */ - iflp->av_delay = 0; - UNSET_PARAM(iflp, LP_DELAY); - iflp->min_delay = 0; - iflp->max_delay = 0; - UNSET_PARAM(iflp, LP_MM_DELAY); - - /* force protocols to update LINK STATE due to parameters change */ - if (if_is_operative(ifp)) - zebra_interface_parameters_update(ifp); - - return CMD_SUCCESS; -} - -DEFUN (link_params_delay_var, - link_params_delay_var_cmd, - "delay-variation (0-16777215)", - "Unidirectional Link Delay Variation\n" - "delay variation in micro-second as decimal (0...16777215)\n") -{ - int idx_number = 1; - VTY_DECLVAR_CONTEXT(interface, ifp); - struct if_link_params *iflp = if_link_params_get(ifp); - uint32_t value; - - value = strtoul(argv[idx_number]->arg, NULL, 10); - - if (!iflp) - iflp = if_link_params_enable(ifp); - - /* Update Delay Variation if needed */ - link_param_cmd_set_uint32(ifp, &iflp->delay_var, LP_DELAY_VAR, value); - - return CMD_SUCCESS; -} - -DEFUN (no_link_params_delay_var, - no_link_params_delay_var_cmd, - "no delay-variation", - NO_STR - "Disable Unidirectional Delay Variation on this interface\n") -{ - VTY_DECLVAR_CONTEXT(interface, ifp); - - /* Unset Delay Variation */ - link_param_cmd_unset(ifp, LP_DELAY_VAR); - - return CMD_SUCCESS; -} - -DEFUN (link_params_pkt_loss, - link_params_pkt_loss_cmd, - "packet-loss PERCENTAGE", - "Unidirectional Link Packet Loss\n" - "percentage of total traffic by 0.000003% step and less than 50.331642%\n") -{ - int idx_percentage = 1; - VTY_DECLVAR_CONTEXT(interface, ifp); - struct if_link_params *iflp = if_link_params_get(ifp); - float fval; - - if (sscanf(argv[idx_percentage]->arg, "%g", &fval) != 1) { - vty_out(vty, "link_params_pkt_loss: fscanf: %s\n", - safe_strerror(errno)); - return CMD_WARNING_CONFIG_FAILED; - } - - if (fval > MAX_PKT_LOSS) - fval = MAX_PKT_LOSS; - - if (!iflp) - iflp = if_link_params_enable(ifp); - - /* Update Packet Loss if needed */ - link_param_cmd_set_float(ifp, &iflp->pkt_loss, LP_PKT_LOSS, fval); - - return CMD_SUCCESS; -} - -DEFUN (no_link_params_pkt_loss, - no_link_params_pkt_loss_cmd, - "no packet-loss", - NO_STR - "Disable Unidirectional Link Packet Loss on this interface\n") -{ - VTY_DECLVAR_CONTEXT(interface, ifp); - - /* Unset Packet Loss */ - link_param_cmd_unset(ifp, LP_PKT_LOSS); - - return CMD_SUCCESS; -} - -DEFUN (link_params_res_bw, - link_params_res_bw_cmd, - "res-bw BANDWIDTH", - "Unidirectional Residual Bandwidth\n" - "Bytes/second (IEEE floating point format)\n") -{ - int idx_bandwidth = 1; - VTY_DECLVAR_CONTEXT(interface, ifp); - struct if_link_params *iflp = if_link_params_get(ifp); - float bw; - - if (sscanf(argv[idx_bandwidth]->arg, "%g", &bw) != 1) { - vty_out(vty, "link_params_res_bw: fscanf: %s\n", - safe_strerror(errno)); - return CMD_WARNING_CONFIG_FAILED; - } - - /* Check that bandwidth is not greater than maximum bandwidth parameter - */ - if (iflp && bw > iflp->max_bw) { - vty_out(vty, - "Residual Bandwidth could not be greater than Maximum Bandwidth (%g)\n", - iflp->max_bw); - return CMD_WARNING_CONFIG_FAILED; - } - - if (!iflp) - iflp = if_link_params_enable(ifp); - - /* Update Residual Bandwidth if needed */ - link_param_cmd_set_float(ifp, &iflp->res_bw, LP_RES_BW, bw); - - return CMD_SUCCESS; -} - -DEFUN (no_link_params_res_bw, - no_link_params_res_bw_cmd, - "no res-bw", - NO_STR - "Disable Unidirectional Residual Bandwidth on this interface\n") -{ - VTY_DECLVAR_CONTEXT(interface, ifp); - - /* Unset Residual Bandwidth */ - link_param_cmd_unset(ifp, LP_RES_BW); - - return CMD_SUCCESS; -} - -DEFUN (link_params_ava_bw, - link_params_ava_bw_cmd, - "ava-bw BANDWIDTH", - "Unidirectional Available Bandwidth\n" - "Bytes/second (IEEE floating point format)\n") -{ - int idx_bandwidth = 1; - VTY_DECLVAR_CONTEXT(interface, ifp); - struct if_link_params *iflp = if_link_params_get(ifp); - float bw; - - if (sscanf(argv[idx_bandwidth]->arg, "%g", &bw) != 1) { - vty_out(vty, "link_params_ava_bw: fscanf: %s\n", - safe_strerror(errno)); - return CMD_WARNING_CONFIG_FAILED; - } - - /* Check that bandwidth is not greater than maximum bandwidth parameter - */ - if (iflp && bw > iflp->max_bw) { - vty_out(vty, - "Available Bandwidth could not be greater than Maximum Bandwidth (%g)\n", - iflp->max_bw); - return CMD_WARNING_CONFIG_FAILED; - } - - if (!iflp) - iflp = if_link_params_enable(ifp); - - /* Update Residual Bandwidth if needed */ - link_param_cmd_set_float(ifp, &iflp->ava_bw, LP_AVA_BW, bw); - - return CMD_SUCCESS; -} - -DEFUN (no_link_params_ava_bw, - no_link_params_ava_bw_cmd, - "no ava-bw", - NO_STR - "Disable Unidirectional Available Bandwidth on this interface\n") -{ - VTY_DECLVAR_CONTEXT(interface, ifp); - - /* Unset Available Bandwidth */ - link_param_cmd_unset(ifp, LP_AVA_BW); - - return CMD_SUCCESS; -} - -DEFUN (link_params_use_bw, - link_params_use_bw_cmd, - "use-bw BANDWIDTH", - "Unidirectional Utilised Bandwidth\n" - "Bytes/second (IEEE floating point format)\n") -{ - int idx_bandwidth = 1; - VTY_DECLVAR_CONTEXT(interface, ifp); - struct if_link_params *iflp = if_link_params_get(ifp); - float bw; - - if (sscanf(argv[idx_bandwidth]->arg, "%g", &bw) != 1) { - vty_out(vty, "link_params_use_bw: fscanf: %s\n", - safe_strerror(errno)); - return CMD_WARNING_CONFIG_FAILED; - } - - /* Check that bandwidth is not greater than maximum bandwidth parameter - */ - if (iflp && bw > iflp->max_bw) { - vty_out(vty, - "Utilised Bandwidth could not be greater than Maximum Bandwidth (%g)\n", - iflp->max_bw); - return CMD_WARNING_CONFIG_FAILED; - } - - if (!iflp) - iflp = if_link_params_enable(ifp); - - /* Update Utilized Bandwidth if needed */ - link_param_cmd_set_float(ifp, &iflp->use_bw, LP_USE_BW, bw); - - return CMD_SUCCESS; -} - -DEFUN (no_link_params_use_bw, - no_link_params_use_bw_cmd, - "no use-bw", - NO_STR - "Disable Unidirectional Utilised Bandwidth on this interface\n") -{ - VTY_DECLVAR_CONTEXT(interface, ifp); - - /* Unset Utilised Bandwidth */ - link_param_cmd_unset(ifp, LP_USE_BW); - - return CMD_SUCCESS; -} - -static int ag_change(struct vty *vty, int argc, struct cmd_token **argv, - const char *xpath, bool no, int start_idx) -{ - for (int i = start_idx; i < argc; i++) - nb_cli_enqueue_change(vty, xpath, - no ? NB_OP_DESTROY : NB_OP_CREATE, - argv[i]->arg); - return nb_cli_apply_changes(vty, NULL); -} - -/* - * XPath: - * /frr-interface:lib/interface/frr-zebra:zebra/link-params/affinities/affinity - */ -DEFPY_YANG(link_params_affinity, link_params_affinity_cmd, - "[no] affinity NAME...", - NO_STR - "Interface affinities\n" - "Affinity names\n") -{ - VTY_DECLVAR_CONTEXT(interface, ifp); - char xpath[XPATH_MAXLEN]; - - snprintf( - xpath, sizeof(xpath), - "/frr-interface:lib/interface[name='%s']/frr-zebra:zebra/link-params/legacy-admin-group", - ifp->name); - if (yang_dnode_exists(running_config->dnode, xpath)) { - vty_out(vty, - "cannot use the affinity command when admin-grp is set\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - return ag_change(vty, argc, argv, - "./frr-zebra:zebra/link-params/affinities/affinity", - no, no ? 2 : 1); -} - - -/* - * XPath: - * /frr-interface:lib/interface/frr-zebra:zebra/link-params/affinities/affinity-mode - */ -DEFPY_YANG(link_params_affinity_mode, link_params_affinity_mode_cmd, - "affinity-mode <standard|extended|both>$affmode", - "Interface affinity mode\n" - "Standard Admin-Group only RFC3630,5305,5329 (default)\n" - "Extended Admin-Group only RFC7308\n" - "Standard and extended Admin-Group format\n") -{ - const char *xpath = "./frr-zebra:zebra/link-params/affinity-mode"; - - nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, affmode); - - return nb_cli_apply_changes(vty, NULL); -} - -DEFPY_YANG(no_link_params_affinity_mode, no_link_params_affinity_mode_cmd, - "no affinity-mode [<standard|extended|both>]", - NO_STR - "Interface affinity mode\n" - "Standard Admin-Group only RFC3630,5305,5329 (default)\n" - "Extended Admin-Group only RFC7308\n" - "Standard and extended Admin-Group format\n") -{ - const char *xpath = "./frr-zebra:zebra/link-params/affinity-mode"; - - nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, "standard"); - - return nb_cli_apply_changes(vty, NULL); -} - -static int ag_iter_cb(const struct lyd_node *dnode, void *arg) -{ - struct vty *vty = (struct vty *)arg; - - vty_out(vty, " %s", yang_dnode_get_string(dnode, ".")); - return YANG_ITER_CONTINUE; -} - -void cli_show_legacy_admin_group(struct vty *vty, const struct lyd_node *dnode, - bool show_defaults) -{ - if (!yang_dnode_exists(dnode, "./legacy-admin-group")) - return; - - vty_out(vty, " admin-group 0x%x\n", - yang_dnode_get_uint32(dnode, "./legacy-admin-group")); -} - -void cli_show_affinity_mode(struct vty *vty, const struct lyd_node *dnode, - bool show_defaults) -{ - enum affinity_mode affinity_mode = yang_dnode_get_enum(dnode, "."); - - if (affinity_mode == AFFINITY_MODE_STANDARD) - vty_out(vty, " affinity-mode standard\n"); - else if (affinity_mode == AFFINITY_MODE_BOTH) - vty_out(vty, " affinity-mode both\n"); -} - -void cli_show_affinity(struct vty *vty, const struct lyd_node *dnode, - bool show_defaults) -{ - if (!yang_dnode_exists(dnode, "./affinity")) - return; - - vty_out(vty, " affinity"); - yang_dnode_iterate(ag_iter_cb, vty, dnode, "./affinity"); - vty_out(vty, "\n"); -} - -int if_ip_address_install(struct interface *ifp, struct prefix *prefix, - const char *label, struct prefix *pp) +void if_ip_address_install(struct interface *ifp, struct prefix *prefix, + const char *label, struct prefix *pp) { struct zebra_if *if_data; - struct prefix_ipv4 lp; - struct prefix_ipv4 *p; struct connected *ifc; - enum zebra_dplane_result dplane_res; if_data = ifp->info; - lp.family = prefix->family; - lp.prefix = prefix->u.prefix4; - lp.prefixlen = prefix->prefixlen; - apply_mask_ipv4(&lp); - - ifc = connected_check_ptp(ifp, &lp, pp ? pp : NULL); + ifc = connected_check_ptp(ifp, prefix, pp); if (!ifc) { ifc = connected_new(); ifc->ifp = ifp; /* Address. */ - p = prefix_ipv4_new(); - *p = lp; - ifc->address = (struct prefix *)p; + ifc->address = prefix_new(); + prefix_copy(ifc->address, prefix); if (pp) { SET_FLAG(ifc->flags, ZEBRA_IFA_PEER); - p = prefix_ipv4_new(); - *p = *(struct prefix_ipv4 *)pp; - ifc->destination = (struct prefix *)p; + ifc->destination = prefix_new(); + prefix_copy(ifc->destination, pp); } /* Label. */ @@ -4159,7 +3805,7 @@ int if_ip_address_install(struct interface *ifp, struct prefix *prefix, ifc->label = XSTRDUP(MTYPE_CONNECTED_LABEL, label); /* Add to linked list. */ - listnode_add(ifp->connected, ifc); + if_connected_add_tail(ifp->connected, ifc); } /* This address is configured from zebra. */ @@ -4176,13 +3822,7 @@ int if_ip_address_install(struct interface *ifp, struct prefix *prefix, if_refresh(ifp); } - dplane_res = dplane_intf_addr_set(ifp, ifc); - if (dplane_res == ZEBRA_DPLANE_REQUEST_FAILURE) { - zlog_debug( - "dplane can't set interface IP address: %s.", - dplane_res2str(dplane_res)); - return NB_ERR; - } + dplane_intf_addr_set(ifp, ifc); SET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED); /* The address will be advertised to zebra clients when the @@ -4190,407 +3830,50 @@ int if_ip_address_install(struct interface *ifp, struct prefix *prefix, * from the kernel has been received. * It will also be added to the subnet chain list, then. */ } - - return 0; } -static int ip_address_install(struct vty *vty, struct interface *ifp, - const char *addr_str, const char *peer_str, - const char *label) +void if_ip_address_uninstall(struct interface *ifp, struct prefix *prefix, + struct prefix *pp) { - struct zebra_if *if_data; - struct prefix_ipv4 lp, pp; struct connected *ifc; - struct prefix_ipv4 *p; - int ret; - enum zebra_dplane_result dplane_res; - - if_data = ifp->info; - - ret = str2prefix_ipv4(addr_str, &lp); - if (ret <= 0) { - vty_out(vty, "%% Malformed address \n"); - return CMD_WARNING_CONFIG_FAILED; - } - - if (ipv4_martian(&lp.prefix)) { - vty_out(vty, "%% Invalid address\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - if (peer_str) { - if (lp.prefixlen != IPV4_MAX_BITLEN) { - vty_out(vty, - "%% Local prefix length for P-t-P address must be /32\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - ret = str2prefix_ipv4(peer_str, &pp); - if (ret <= 0) { - vty_out(vty, "%% Malformed peer address\n"); - return CMD_WARNING_CONFIG_FAILED; - } - } - - ifc = connected_check_ptp(ifp, &lp, peer_str ? &pp : NULL); - if (!ifc) { - ifc = connected_new(); - ifc->ifp = ifp; - - /* Address. */ - p = prefix_ipv4_new(); - *p = lp; - ifc->address = (struct prefix *)p; - - if (peer_str) { - SET_FLAG(ifc->flags, ZEBRA_IFA_PEER); - p = prefix_ipv4_new(); - *p = pp; - ifc->destination = (struct prefix *)p; - } - - /* Label. */ - if (label) - ifc->label = XSTRDUP(MTYPE_CONNECTED_LABEL, label); - - /* Add to linked list. */ - listnode_add(ifp->connected, ifc); - } - - /* This address is configured from zebra. */ - if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED)) - SET_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED); - - /* In case of this route need to install kernel. */ - if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_QUEUED) && - CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE) && - !(if_data && if_data->shutdown == IF_ZEBRA_DATA_ON)) { - /* Some system need to up the interface to set IP address. */ - if (!if_is_up(ifp)) { - if_set_flags(ifp, IFF_UP | IFF_RUNNING); - if_refresh(ifp); - } - - dplane_res = dplane_intf_addr_set(ifp, ifc); - if (dplane_res == ZEBRA_DPLANE_REQUEST_FAILURE) { - vty_out(vty, "%% Can't set interface IP address: %s.\n", - dplane_res2str(dplane_res)); - return CMD_WARNING_CONFIG_FAILED; - } - - SET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED); - /* The address will be advertised to zebra clients when the - * notification - * from the kernel has been received. - * It will also be added to the subnet chain list, then. */ - } - - return CMD_SUCCESS; -} - -int if_ip_address_uinstall(struct interface *ifp, struct prefix *prefix) -{ - struct connected *ifc = NULL; - enum zebra_dplane_result dplane_res; - - if (prefix->family == AF_INET) { - /* Check current interface address. */ - ifc = connected_check_ptp(ifp, prefix, NULL); - if (!ifc) { - zlog_debug("interface %s Can't find address", - ifp->name); - return -1; - } - } else if (prefix->family == AF_INET6) { - /* Check current interface address. */ - ifc = connected_check(ifp, prefix); - } + ifc = connected_check_ptp(ifp, prefix, pp); + assert(ifc); - if (!ifc) { - zlog_debug("interface %s Can't find address", ifp->name); - return -1; - } UNSET_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED); /* This is not real address or interface is not active. */ if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_QUEUED) || !CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE)) { - listnode_delete(ifp->connected, ifc); + if_connected_del(ifp->connected, ifc); connected_free(&ifc); - return CMD_WARNING_CONFIG_FAILED; + return; } /* This is real route. */ - dplane_res = dplane_intf_addr_unset(ifp, ifc); - if (dplane_res == ZEBRA_DPLANE_REQUEST_FAILURE) { - zlog_debug("Can't unset interface IP address: %s.", - dplane_res2str(dplane_res)); - return -1; - } - UNSET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED); - - return 0; -} - -static int ip_address_uninstall(struct vty *vty, struct interface *ifp, - const char *addr_str, const char *peer_str, - const char *label) -{ - struct prefix_ipv4 lp, pp; - struct connected *ifc; - int ret; - enum zebra_dplane_result dplane_res; - - /* Convert to prefix structure. */ - ret = str2prefix_ipv4(addr_str, &lp); - if (ret <= 0) { - vty_out(vty, "%% Malformed address \n"); - return CMD_WARNING_CONFIG_FAILED; - } - - if (peer_str) { - if (lp.prefixlen != IPV4_MAX_BITLEN) { - vty_out(vty, - "%% Local prefix length for P-t-P address must be /32\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - ret = str2prefix_ipv4(peer_str, &pp); - if (ret <= 0) { - vty_out(vty, "%% Malformed peer address\n"); - return CMD_WARNING_CONFIG_FAILED; - } - } - - /* Check current interface address. */ - ifc = connected_check_ptp(ifp, &lp, peer_str ? &pp : NULL); - if (!ifc) { - vty_out(vty, "%% Can't find address\n"); - return CMD_WARNING_CONFIG_FAILED; - } + dplane_intf_addr_unset(ifp, ifc); - /* This is not configured address. */ - if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED)) - return CMD_WARNING_CONFIG_FAILED; - - UNSET_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED); - - /* This is not real address or interface is not active. */ - if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_QUEUED) - || !CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE)) { - listnode_delete(ifp->connected, ifc); - connected_free(&ifc); - return CMD_WARNING_CONFIG_FAILED; - } - - /* This is real route. */ - dplane_res = dplane_intf_addr_unset(ifp, ifc); - if (dplane_res == ZEBRA_DPLANE_REQUEST_FAILURE) { - vty_out(vty, "%% Can't unset interface IP address: %s.\n", - dplane_res2str(dplane_res)); - return CMD_WARNING_CONFIG_FAILED; - } UNSET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED); - /* we will receive a kernel notification about this route being removed. - * this will trigger its removal from the connected list. */ - return CMD_SUCCESS; -} - -DEFUN (ip_address, - ip_address_cmd, - "ip address A.B.C.D/M", - "Interface Internet Protocol config commands\n" - "Set the IP address of an interface\n" - "IP address (e.g. 10.0.0.1/8)\n") -{ - int idx_ipv4_prefixlen = 2; - VTY_DECLVAR_CONTEXT(interface, ifp); - return ip_address_install(vty, ifp, argv[idx_ipv4_prefixlen]->arg, NULL, - NULL); -} - -DEFUN (no_ip_address, - no_ip_address_cmd, - "no ip address A.B.C.D/M", - NO_STR - "Interface Internet Protocol config commands\n" - "Set the IP address of an interface\n" - "IP Address (e.g. 10.0.0.1/8)\n") -{ - int idx_ipv4_prefixlen = 3; - VTY_DECLVAR_CONTEXT(interface, ifp); - return ip_address_uninstall(vty, ifp, argv[idx_ipv4_prefixlen]->arg, - NULL, NULL); -} - -DEFUN(ip_address_peer, - ip_address_peer_cmd, - "ip address A.B.C.D peer A.B.C.D/M", - "Interface Internet Protocol config commands\n" - "Set the IP address of an interface\n" - "Local IP (e.g. 10.0.0.1) for P-t-P address\n" - "Specify P-t-P address\n" - "Peer IP address (e.g. 10.0.0.1/8)\n") -{ - VTY_DECLVAR_CONTEXT(interface, ifp); - return ip_address_install(vty, ifp, argv[2]->arg, argv[4]->arg, NULL); -} - -DEFUN(no_ip_address_peer, - no_ip_address_peer_cmd, - "no ip address A.B.C.D peer A.B.C.D/M", - NO_STR - "Interface Internet Protocol config commands\n" - "Set the IP address of an interface\n" - "Local IP (e.g. 10.0.0.1) for P-t-P address\n" - "Specify P-t-P address\n" - "Peer IP address (e.g. 10.0.0.1/8)\n") -{ - VTY_DECLVAR_CONTEXT(interface, ifp); - return ip_address_uninstall(vty, ifp, argv[3]->arg, argv[5]->arg, NULL); -} - -#ifdef HAVE_NETLINK -DEFUN (ip_address_label, - ip_address_label_cmd, - "ip address A.B.C.D/M label LINE", - "Interface Internet Protocol config commands\n" - "Set the IP address of an interface\n" - "IP address (e.g. 10.0.0.1/8)\n" - "Label of this address\n" - "Label\n") -{ - int idx_ipv4_prefixlen = 2; - int idx_line = 4; - VTY_DECLVAR_CONTEXT(interface, ifp); - return ip_address_install(vty, ifp, argv[idx_ipv4_prefixlen]->arg, NULL, - argv[idx_line]->arg); -} - -DEFUN (no_ip_address_label, - no_ip_address_label_cmd, - "no ip address A.B.C.D/M label LINE", - NO_STR - "Interface Internet Protocol config commands\n" - "Set the IP address of an interface\n" - "IP address (e.g. 10.0.0.1/8)\n" - "Label of this address\n" - "Label\n") -{ - int idx_ipv4_prefixlen = 3; - int idx_line = 5; - VTY_DECLVAR_CONTEXT(interface, ifp); - return ip_address_uninstall(vty, ifp, argv[idx_ipv4_prefixlen]->arg, - NULL, argv[idx_line]->arg); } -#endif /* HAVE_NETLINK */ -int if_ipv6_address_install(struct interface *ifp, struct prefix *prefix, - const char *label) +void if_ipv6_address_install(struct interface *ifp, struct prefix *prefix) { struct zebra_if *if_data; - struct prefix_ipv6 cp; struct connected *ifc; - struct prefix_ipv6 *p; - enum zebra_dplane_result dplane_res; - - if_data = ifp->info; - - cp.family = prefix->family; - cp.prefixlen = prefix->prefixlen; - cp.prefix = prefix->u.prefix6; - apply_mask_ipv6(&cp); - - ifc = connected_check(ifp, (struct prefix *)&cp); - if (!ifc) { - ifc = connected_new(); - ifc->ifp = ifp; - - /* Address. */ - p = prefix_ipv6_new(); - *p = cp; - ifc->address = (struct prefix *)p; - - /* Label. */ - if (label) - ifc->label = XSTRDUP(MTYPE_CONNECTED_LABEL, label); - - /* Add to linked list. */ - listnode_add(ifp->connected, ifc); - } - - /* This address is configured from zebra. */ - if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED)) - SET_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED); - - /* In case of this route need to install kernel. */ - if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_QUEUED) && - CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE) && - !(if_data && if_data->shutdown == IF_ZEBRA_DATA_ON)) { - /* Some system need to up the interface to set IP address. */ - if (!if_is_up(ifp)) { - if_set_flags(ifp, IFF_UP | IFF_RUNNING); - if_refresh(ifp); - } - - dplane_res = dplane_intf_addr_set(ifp, ifc); - if (dplane_res == ZEBRA_DPLANE_REQUEST_FAILURE) { - zlog_debug( - "dplane can't set interface IP address: %s.", - dplane_res2str(dplane_res)); - return NB_ERR; - } - - SET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED); - /* The address will be advertised to zebra clients when the - * notification - * from the kernel has been received. */ - } - - return 0; -} - -static int ipv6_address_install(struct vty *vty, struct interface *ifp, - const char *addr_str, const char *peer_str, - const char *label) -{ - struct zebra_if *if_data; - struct prefix_ipv6 cp; - struct connected *ifc; - struct prefix_ipv6 *p; - int ret; - enum zebra_dplane_result dplane_res; if_data = ifp->info; - ret = str2prefix_ipv6(addr_str, &cp); - if (ret <= 0) { - vty_out(vty, "%% Malformed address \n"); - return CMD_WARNING_CONFIG_FAILED; - } - - if (ipv6_martian(&cp.prefix)) { - vty_out(vty, "%% Invalid address\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - ifc = connected_check(ifp, (struct prefix *)&cp); + ifc = connected_check(ifp, prefix); if (!ifc) { ifc = connected_new(); ifc->ifp = ifp; /* Address. */ - p = prefix_ipv6_new(); - *p = cp; - ifc->address = (struct prefix *)p; - - /* Label. */ - if (label) - ifc->label = XSTRDUP(MTYPE_CONNECTED_LABEL, label); + ifc->address = prefix_new(); + prefix_copy(ifc->address, prefix); /* Add to linked list. */ - listnode_add(ifp->connected, ifc); + if_connected_add_tail(ifp->connected, ifc); } /* This address is configured from zebra. */ @@ -4607,261 +3890,36 @@ static int ipv6_address_install(struct vty *vty, struct interface *ifp, if_refresh(ifp); } - dplane_res = dplane_intf_addr_set(ifp, ifc); - if (dplane_res == ZEBRA_DPLANE_REQUEST_FAILURE) { - vty_out(vty, "%% Can't set interface IP address: %s.\n", - dplane_res2str(dplane_res)); - return CMD_WARNING_CONFIG_FAILED; - } + dplane_intf_addr_set(ifp, ifc); SET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED); /* The address will be advertised to zebra clients when the * notification * from the kernel has been received. */ } - - return CMD_SUCCESS; -} - -/* Return true if an ipv6 address is configured on ifp */ -int ipv6_address_configured(struct interface *ifp) -{ - struct connected *connected; - struct listnode *node; - - for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, connected)) - if (CHECK_FLAG(connected->conf, ZEBRA_IFC_REAL) - && (connected->address->family == AF_INET6)) - return 1; - - return 0; } -static int ipv6_address_uninstall(struct vty *vty, struct interface *ifp, - const char *addr_str, const char *peer_str, - const char *label) +void if_ipv6_address_uninstall(struct interface *ifp, struct prefix *prefix) { - struct prefix_ipv6 cp; struct connected *ifc; - int ret; - enum zebra_dplane_result dplane_res; - - /* Convert to prefix structure. */ - ret = str2prefix_ipv6(addr_str, &cp); - if (ret <= 0) { - vty_out(vty, "%% Malformed address \n"); - return CMD_WARNING_CONFIG_FAILED; - } - /* Check current interface address. */ - ifc = connected_check(ifp, (struct prefix *)&cp); - if (!ifc) { - vty_out(vty, "%% Can't find address\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - /* This is not configured address. */ - if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED)) - return CMD_WARNING_CONFIG_FAILED; + ifc = connected_check(ifp, prefix); + assert(ifc); UNSET_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED); /* This is not real address or interface is not active. */ if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_QUEUED) || !CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE)) { - listnode_delete(ifp->connected, ifc); + if_connected_del(ifp->connected, ifc); connected_free(&ifc); - return CMD_WARNING_CONFIG_FAILED; + return; } /* This is real route. */ - dplane_res = dplane_intf_addr_unset(ifp, ifc); - if (dplane_res == ZEBRA_DPLANE_REQUEST_FAILURE) { - vty_out(vty, "%% Can't unset interface IP address: %s.\n", - dplane_res2str(dplane_res)); - return CMD_WARNING_CONFIG_FAILED; - } + dplane_intf_addr_unset(ifp, ifc); UNSET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED); - /* This information will be propagated to the zclients when the - * kernel notification is received. */ - return CMD_SUCCESS; -} - -DEFUN (ipv6_address, - ipv6_address_cmd, - "ipv6 address X:X::X:X/M", - "Interface IPv6 config commands\n" - "Set the IP address of an interface\n" - "IPv6 address (e.g. 3ffe:506::1/48)\n") -{ - int idx_ipv6_prefixlen = 2; - VTY_DECLVAR_CONTEXT(interface, ifp); - return ipv6_address_install(vty, ifp, argv[idx_ipv6_prefixlen]->arg, - NULL, NULL); -} - -DEFUN (no_ipv6_address, - no_ipv6_address_cmd, - "no ipv6 address X:X::X:X/M", - NO_STR - "Interface IPv6 config commands\n" - "Set the IP address of an interface\n" - "IPv6 address (e.g. 3ffe:506::1/48)\n") -{ - int idx_ipv6_prefixlen = 3; - VTY_DECLVAR_CONTEXT(interface, ifp); - return ipv6_address_uninstall(vty, ifp, argv[idx_ipv6_prefixlen]->arg, - NULL, NULL); -} - -static int link_params_config_write(struct vty *vty, struct interface *ifp) -{ - const struct lyd_node *dnode; - char xpath[XPATH_MAXLEN]; - int i; - - if ((ifp == NULL) || !HAS_LINK_PARAMS(ifp)) - return -1; - - struct if_link_params *iflp = ifp->link_params; - - vty_out(vty, " link-params\n"); - vty_out(vty, " enable\n"); - if (IS_PARAM_SET(iflp, LP_TE_METRIC) && iflp->te_metric != ifp->metric) - vty_out(vty, " metric %u\n", iflp->te_metric); - if (IS_PARAM_SET(iflp, LP_MAX_BW) && iflp->max_bw != iflp->default_bw) - vty_out(vty, " max-bw %g\n", iflp->max_bw); - if (IS_PARAM_SET(iflp, LP_MAX_RSV_BW) - && iflp->max_rsv_bw != iflp->default_bw) - vty_out(vty, " max-rsv-bw %g\n", iflp->max_rsv_bw); - if (IS_PARAM_SET(iflp, LP_UNRSV_BW)) { - for (i = 0; i < 8; i++) - if (iflp->unrsv_bw[i] != iflp->default_bw) - vty_out(vty, " unrsv-bw %d %g\n", i, - iflp->unrsv_bw[i]); - } - - snprintf( - xpath, sizeof(xpath), - "/frr-interface:lib/interface[name='%s']/frr-zebra:zebra/link-params", - ifp->name); - dnode = yang_dnode_get(running_config->dnode, xpath); - if (dnode) - nb_cli_show_dnode_cmds(vty, dnode, false); - - if (IS_PARAM_SET(iflp, LP_DELAY)) { - vty_out(vty, " delay %u", iflp->av_delay); - if (IS_PARAM_SET(iflp, LP_MM_DELAY)) { - vty_out(vty, " min %u", iflp->min_delay); - vty_out(vty, " max %u", iflp->max_delay); - } - vty_out(vty, "\n"); - } - if (IS_PARAM_SET(iflp, LP_DELAY_VAR)) - vty_out(vty, " delay-variation %u\n", iflp->delay_var); - if (IS_PARAM_SET(iflp, LP_PKT_LOSS)) - vty_out(vty, " packet-loss %g\n", iflp->pkt_loss); - if (IS_PARAM_SET(iflp, LP_AVA_BW)) - vty_out(vty, " ava-bw %g\n", iflp->ava_bw); - if (IS_PARAM_SET(iflp, LP_RES_BW)) - vty_out(vty, " res-bw %g\n", iflp->res_bw); - if (IS_PARAM_SET(iflp, LP_USE_BW)) - vty_out(vty, " use-bw %g\n", iflp->use_bw); - if (IS_PARAM_SET(iflp, LP_RMT_AS)) - vty_out(vty, " neighbor %pI4 as %u\n", &iflp->rmt_ip, - iflp->rmt_as); - - vty_out(vty, " exit-link-params\n"); - return 0; -} - -static int if_config_write(struct vty *vty) -{ - struct vrf *vrf; - struct interface *ifp; - - zebra_ptm_write(vty); - - RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) - FOR_ALL_INTERFACES (vrf, ifp) { - struct zebra_if *if_data; - struct listnode *addrnode; - struct connected *ifc; - struct prefix *p; - - if_data = ifp->info; - - if_vty_config_start(vty, ifp); - - if (if_data) { - if (if_data->shutdown == IF_ZEBRA_DATA_ON) - vty_out(vty, " shutdown\n"); - - zebra_ptm_if_write(vty, if_data); - } - - if (ifp->desc) - vty_out(vty, " description %s\n", ifp->desc); - - /* Assign bandwidth here to avoid unnecessary interface - flap - while processing config script */ - if (ifp->bandwidth != 0) - vty_out(vty, " bandwidth %u\n", ifp->bandwidth); - - if (!CHECK_FLAG(ifp->status, - ZEBRA_INTERFACE_LINKDETECTION)) - vty_out(vty, " no link-detect\n"); - - for (ALL_LIST_ELEMENTS_RO(ifp->connected, addrnode, - ifc)) { - if (CHECK_FLAG(ifc->conf, - ZEBRA_IFC_CONFIGURED)) { - char buf[INET6_ADDRSTRLEN]; - p = ifc->address; - vty_out(vty, " ip%s address %s", - p->family == AF_INET ? "" - : "v6", - inet_ntop(p->family, - &p->u.prefix, buf, - sizeof(buf))); - if (CONNECTED_PEER(ifc)) { - p = ifc->destination; - vty_out(vty, " peer %s", - inet_ntop(p->family, - &p->u.prefix, - buf, - sizeof(buf))); - } - vty_out(vty, "/%d", p->prefixlen); - - if (ifc->label) - vty_out(vty, " label %s", - ifc->label); - - vty_out(vty, "\n"); - } - } - - if (if_data) { - if (if_data->multicast != IF_ZEBRA_DATA_UNSPEC) - vty_out(vty, " %smulticast\n", - if_data->multicast == - IF_ZEBRA_DATA_ON - ? "" - : "no "); - if (if_data->mpls == IF_ZEBRA_DATA_ON) - vty_out(vty, " mpls enable\n"); - } - - hook_call(zebra_if_config_wr, vty, ifp); - zebra_evpn_mh_if_write(vty, ifp); - link_params_config_write(vty, ifp); - - if_vty_config_end(vty); - } - return 0; } /* Allocate and initialize interface vector. */ @@ -4871,15 +3929,6 @@ void zebra_if_init(void) hook_register_prio(if_add, 0, if_zebra_new_hook); hook_register_prio(if_del, 0, if_zebra_delete_hook); - /* Install configuration write function. */ - if_cmd_init(if_config_write); - install_node(&link_params_node); - /* - * This is *intentionally* setting this to NULL, signaling - * that interface creation for zebra acts differently - */ - if_zapi_callbacks(NULL, NULL, NULL, NULL); - install_element(VIEW_NODE, &show_interface_cmd); install_element(VIEW_NODE, &show_interface_vrf_all_cmd); install_element(VIEW_NODE, &show_interface_name_vrf_cmd); @@ -4887,55 +3936,4 @@ void zebra_if_init(void) install_element(ENABLE_NODE, &show_interface_desc_cmd); install_element(ENABLE_NODE, &show_interface_desc_vrf_all_cmd); - install_element(INTERFACE_NODE, &multicast_cmd); - install_element(INTERFACE_NODE, &no_multicast_cmd); - install_element(INTERFACE_NODE, &mpls_cmd); - install_element(INTERFACE_NODE, &linkdetect_cmd); - install_element(INTERFACE_NODE, &no_linkdetect_cmd); - install_element(INTERFACE_NODE, &shutdown_if_cmd); - install_element(INTERFACE_NODE, &no_shutdown_if_cmd); - install_element(INTERFACE_NODE, &bandwidth_if_cmd); - install_element(INTERFACE_NODE, &no_bandwidth_if_cmd); - install_element(INTERFACE_NODE, &ip_address_cmd); - install_element(INTERFACE_NODE, &no_ip_address_cmd); - install_element(INTERFACE_NODE, &ip_address_peer_cmd); - install_element(INTERFACE_NODE, &no_ip_address_peer_cmd); - install_element(INTERFACE_NODE, &ipv6_address_cmd); - install_element(INTERFACE_NODE, &no_ipv6_address_cmd); -#ifdef HAVE_NETLINK - install_element(INTERFACE_NODE, &ip_address_label_cmd); - install_element(INTERFACE_NODE, &no_ip_address_label_cmd); -#endif /* HAVE_NETLINK */ - install_element(INTERFACE_NODE, &link_params_cmd); - install_default(LINK_PARAMS_NODE); - install_element(LINK_PARAMS_NODE, &link_params_enable_cmd); - install_element(LINK_PARAMS_NODE, &no_link_params_enable_cmd); - install_element(LINK_PARAMS_NODE, &link_params_metric_cmd); - install_element(LINK_PARAMS_NODE, &no_link_params_metric_cmd); - install_element(LINK_PARAMS_NODE, &link_params_maxbw_cmd); - install_element(LINK_PARAMS_NODE, &link_params_max_rsv_bw_cmd); - install_element(LINK_PARAMS_NODE, &link_params_unrsv_bw_cmd); - install_element(LINK_PARAMS_NODE, &link_params_admin_grp_cmd); - install_element(LINK_PARAMS_NODE, &no_link_params_admin_grp_cmd); - install_element(LINK_PARAMS_NODE, &link_params_inter_as_cmd); - install_element(LINK_PARAMS_NODE, &no_link_params_inter_as_cmd); - install_element(LINK_PARAMS_NODE, &link_params_delay_cmd); - install_element(LINK_PARAMS_NODE, &no_link_params_delay_cmd); - install_element(LINK_PARAMS_NODE, &link_params_delay_var_cmd); - install_element(LINK_PARAMS_NODE, &no_link_params_delay_var_cmd); - install_element(LINK_PARAMS_NODE, &link_params_pkt_loss_cmd); - install_element(LINK_PARAMS_NODE, &no_link_params_pkt_loss_cmd); - install_element(LINK_PARAMS_NODE, &link_params_ava_bw_cmd); - install_element(LINK_PARAMS_NODE, &no_link_params_ava_bw_cmd); - install_element(LINK_PARAMS_NODE, &link_params_res_bw_cmd); - install_element(LINK_PARAMS_NODE, &no_link_params_res_bw_cmd); - install_element(LINK_PARAMS_NODE, &link_params_use_bw_cmd); - install_element(LINK_PARAMS_NODE, &no_link_params_use_bw_cmd); - install_element(LINK_PARAMS_NODE, &link_params_affinity_cmd); - install_element(LINK_PARAMS_NODE, &link_params_affinity_mode_cmd); - install_element(LINK_PARAMS_NODE, &no_link_params_affinity_mode_cmd); - install_element(LINK_PARAMS_NODE, &exit_link_params_cmd); - - /* setup EVPN MH elements */ - zebra_evpn_interface_init(); } |
