diff options
52 files changed, 869 insertions, 425 deletions
diff --git a/bgpd/bgp_nexthop.h b/bgpd/bgp_nexthop.h index 49cbbaf885..90e0074e35 100644 --- a/bgpd/bgp_nexthop.h +++ b/bgpd/bgp_nexthop.h @@ -26,6 +26,8 @@ PREDECL_RBTREE_UNIQ(bgp_nexthop_cache); /* BGP nexthop cache value structure. */ struct bgp_nexthop_cache { + afi_t afi; + /* The ifindex of the outgoing interface *if* it's a v6 LL */ ifindex_t ifindex_ipv6_ll; diff --git a/bgpd/bgp_nht.c b/bgpd/bgp_nht.c index 9a2166c86b..10c0382f6f 100644 --- a/bgpd/bgp_nht.c +++ b/bgpd/bgp_nht.c @@ -386,6 +386,7 @@ int bgp_find_or_add_nexthop(struct bgp *bgp_route, struct bgp *bgp_nexthop, bnc = bnc_find(tree, &p, srte_color, ifindex); if (!bnc) { bnc = bnc_new(tree, &p, srte_color, ifindex); + bnc->afi = afi; bnc->bgp = bgp_nexthop; if (BGP_DEBUG(nht, NHT)) zlog_debug("Allocated bnc %pFX(%d)(%u)(%s) peer %p", @@ -1162,6 +1163,11 @@ static void register_zebra_rnh(struct bgp_nexthop_cache *bnc) */ static void unregister_zebra_rnh(struct bgp_nexthop_cache *bnc) { + struct bgp_nexthop_cache *import; + struct bgp_nexthop_cache *nexthop; + + struct bgp *bgp = bnc->bgp; + /* Check if we have already registered */ if (!CHECK_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED)) return; @@ -1171,6 +1177,19 @@ static void unregister_zebra_rnh(struct bgp_nexthop_cache *bnc) return; } + import = bnc_find(&bgp->import_check_table[bnc->afi], &bnc->prefix, 0, + 0); + nexthop = bnc_find(&bgp->nexthop_cache_table[bnc->afi], &bnc->prefix, 0, + 0); + + /* + * If this entry has both a import and a nexthop entry + * then let's not send the unregister quite as of yet + * wait until we only have 1 left + */ + if (import && nexthop) + return; + sendmsg_zebra_rnh(bnc, ZEBRA_NEXTHOP_UNREGISTER); } diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index 9283055d9d..125a39d807 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -7595,7 +7595,6 @@ bool bgp_aggregate_route(struct bgp *bgp, const struct prefix *p, afi_t afi, */ aggregate->count = 0; aggregate->incomplete_origin_count = 0; - aggregate->incomplete_origin_count = 0; aggregate->egp_origin_count = 0; /* ORIGIN attribute: If at least one route among routes that are diff --git a/bgpd/bgp_snmp_bgp4v2.c b/bgpd/bgp_snmp_bgp4v2.c index 3b499271c8..48db73a343 100644 --- a/bgpd/bgp_snmp_bgp4v2.c +++ b/bgpd/bgp_snmp_bgp4v2.c @@ -446,6 +446,8 @@ bgp4v2PathAttrLookup(struct variable *v, oid name[], size_t *length, size_t afi_len; long prefix_type = 0; long peer_addr_type = 0; + long nrli_index = 1; + long cur_index = 0; /* Bgp4V2AddressFamilyIdentifierTC limited to IPv6 */ if (name[namelen - 1] > IANA_AFI_IPV6) @@ -455,12 +457,17 @@ bgp4v2PathAttrLookup(struct variable *v, oid name[], size_t *length, assert(IS_VALID_AFI(afi)); #define BGP_NLRI_ENTRY_OFFSET namelen +#define BGP4V2_NLRI_V4_V4_OFFSET IN_ADDR_SIZE + IN_ADDR_SIZE + 5 +#define BGP4V2_NLRI_V4_V6_OFFSET IN_ADDR_SIZE + IN6_ADDR_SIZE + 5 +#define BGP4V2_NLRI_V6_V6_OFFSET IN6_ADDR_SIZE + IN6_ADDR_SIZE + 5 sockunion_init(&su); if (exact) { - if (*length - namelen != BGP_NLRI_ENTRY_OFFSET) + if (*length - namelen != BGP4V2_NLRI_V4_V4_OFFSET && + *length - namelen != BGP4V2_NLRI_V4_V6_OFFSET && + *length - namelen != BGP4V2_NLRI_V6_V6_OFFSET) return NULL; /* Set OID offset for prefix type */ @@ -504,12 +511,17 @@ bgp4v2PathAttrLookup(struct variable *v, oid name[], size_t *length, su.sin.sin_family = family; /* get bgp4V2PeerRemoteAddr*/ - if (family == AF_INET) + if (family == AF_INET) { oid2in_addr(offset, IN_ADDR_SIZE, &su.sin.sin_addr); - else + offset += IN_ADDR_SIZE; + } else { oid2in6_addr(offset, &su.sin6.sin6_addr); + offset += IN6_ADDR_SIZE; + } - /* bgp4V2NlriIndex currently ignored */ + /* bgp4V2NlriIndex */ + nrli_index = *offset; + offset++; /* Lookup node */ dest = bgp_node_lookup(bgp->rib[afi][safi], addr); @@ -517,8 +529,11 @@ bgp4v2PathAttrLookup(struct variable *v, oid name[], size_t *length, for (path = bgp_dest_get_bgp_path_info(dest); path; path = path->next) if (sockunion_same(&path->peer->connection->su, - &su)) - return path; + &su)) { + cur_index++; + if (cur_index == nrli_index) + return path; + } bgp_dest_unlock_node(dest); } @@ -573,7 +588,7 @@ bgp4v2PathAttrLookup(struct variable *v, oid name[], size_t *length, offsetlen--; /* get node */ - dest = bgp_node_get(bgp->rib[afi][safi], addr); + dest = bgp_node_lookup(bgp->rib[afi][safi], addr); } if (!dest) @@ -593,10 +608,17 @@ bgp4v2PathAttrLookup(struct variable *v, oid name[], size_t *length, family = AF_INET6; offset++; - if (family == AF_INET) + if (family == AF_INET) { oid2in_addr(offset, IN_ADDR_SIZE, &paddr.ip._v4_addr); - else + offset += IN_ADDR_SIZE; + } else { oid2in6_addr(offset, &paddr.ip._v6_addr); + offset += IN6_ADDR_SIZE; + } + /* get bgp4V2NlriIndex */ + nrli_index = *offset; + offset++; + } else { /* default case start with ipv4*/ if (afi == AFI_IP) @@ -604,11 +626,13 @@ bgp4v2PathAttrLookup(struct variable *v, oid name[], size_t *length, else family = AF_INET6; memset(&paddr.ip, 0, sizeof(paddr.ip)); + nrli_index = 1; } do { min = NULL; min_family = 0; + cur_index = 0; for (path = bgp_dest_get_bgp_path_info(dest); path; path = path->next) { @@ -618,19 +642,44 @@ bgp4v2PathAttrLookup(struct variable *v, oid name[], size_t *length, if (path_family < family) continue; - if (family == AF_INET - && IPV4_ADDR_CMP(&paddr.ip._v4_addr, - &path->peer->connection->su.sin.sin_addr) - >= 0) + if (family == AF_INET && + IPV4_ADDR_CMP(&paddr.ip._v4_addr, + &path->peer->connection->su.sin + .sin_addr) > 0) continue; - else if (family == AF_INET6 - && IPV6_ADDR_CMP( - &paddr.ip._v6_addr, - &path->peer->connection->su.sin6.sin6_addr) - >= 0) + else if (family == AF_INET6 && + IPV6_ADDR_CMP(&paddr.ip._v6_addr, + &path->peer->connection->su.sin6 + .sin6_addr) > 0) continue; - /* first valid path its the min*/ + if (family == AF_INET && + IPV4_ADDR_CMP(&paddr.ip._v4_addr, + &path->peer->connection->su.sin + .sin_addr) == 0) { + if (cur_index == nrli_index) { + min = path; + min_family = family; + nrli_index++; + break; + } + cur_index++; + continue; + } else if (family == AF_INET6 && + IPV6_ADDR_CMP(&paddr.ip._v6_addr, + &path->peer->connection->su + .sin6.sin6_addr) == 0) { + if (cur_index == nrli_index) { + min = path; + min_family = family; + nrli_index++; + break; + } + cur_index++; + continue; + } + + /* first valid path its the min peer addr*/ if (!min) { min = path; min_family = path_family; @@ -706,7 +755,7 @@ bgp4v2PathAttrLookup(struct variable *v, oid name[], size_t *length, /* Encode bgp4V2NlriIndex*/ - *offset = 1; + *offset = nrli_index; offset++; *length = offset - name; @@ -720,6 +769,7 @@ bgp4v2PathAttrLookup(struct variable *v, oid name[], size_t *length, } memset(&paddr.ip, 0, sizeof(paddr.ip)); + nrli_index = 1; } while ((dest = bgp_route_next(dest))); diff --git a/docker/ubuntu-ci/Dockerfile b/docker/ubuntu-ci/Dockerfile index 939a43e4ea..1b3deb2750 100644 --- a/docker/ubuntu-ci/Dockerfile +++ b/docker/ubuntu-ci/Dockerfile @@ -45,6 +45,7 @@ RUN apt update && apt upgrade -y && \ apt-get install -y \ curl \ gdb \ + kmod \ iproute2 \ iputils-ping \ liblua5.3-dev \ @@ -434,6 +434,8 @@ struct connected { #define ZEBRA_IFA_SECONDARY (1 << 0) #define ZEBRA_IFA_PEER (1 << 1) #define ZEBRA_IFA_UNNUMBERED (1 << 2) +#define ZEBRA_IFA_NOPREFIXROUTE (1 << 3) + /* N.B. the ZEBRA_IFA_PEER flag should be set if and only if a peer address has been configured. If this flag is set, the destination field must contain the peer address. diff --git a/lib/mgmt_be_client.c b/lib/mgmt_be_client.c index ef77be1f18..51eaeb92de 100644 --- a/lib/mgmt_be_client.c +++ b/lib/mgmt_be_client.c @@ -112,7 +112,11 @@ struct mgmt_be_client { #define FOREACH_BE_TXN_IN_LIST(client_ctx, txn) \ frr_each_safe (mgmt_be_txns, &(client_ctx)->txn_head, (txn)) -struct debug mgmt_dbg_be_client = {0, "Management backend client operations"}; +struct debug mgmt_dbg_be_client = { + .desc = "Management backend client operations" +}; + +struct mgmt_be_client *mgmt_be_client; static int mgmt_be_client_send_msg(struct mgmt_be_client *client_ctx, Mgmtd__BeMessage *be_msg) @@ -820,24 +824,28 @@ static int mgmt_be_client_notify_disconenct(struct msg_conn *conn) * Debug Flags */ +static void mgmt_debug_client_be_set(uint32_t flags, bool set) +{ + DEBUG_FLAGS_SET(&mgmt_dbg_be_client, flags, set); + + if (!mgmt_be_client) + return; + + mgmt_be_client->client.conn.debug = + DEBUG_MODE_CHECK(&mgmt_dbg_be_client, DEBUG_MODE_ALL); +} + DEFPY(debug_mgmt_client_be, debug_mgmt_client_be_cmd, "[no] debug mgmt client backend", NO_STR DEBUG_STR MGMTD_STR "client\n" "backend\n") { - uint32_t mode = DEBUG_NODE2MODE(vty->node); - - DEBUG_MODE_SET(&mgmt_dbg_be_client, mode, !no); + mgmt_debug_client_be_set(DEBUG_NODE2MODE(vty->node), !no); return CMD_SUCCESS; } -static void mgmt_debug_client_be_set_all(uint32_t flags, bool set) -{ - DEBUG_FLAGS_SET(&mgmt_dbg_be_client, flags, set); -} - static int mgmt_debug_be_client_config_write(struct vty *vty) { if (DEBUG_MODE_CHECK(&mgmt_dbg_be_client, DEBUG_MODE_CONF)) @@ -853,7 +861,8 @@ void mgmt_debug_be_client_show_debug(struct vty *vty) } static struct debug_callbacks mgmt_dbg_be_client_cbs = { - .debug_set_all = mgmt_debug_client_be_set_all}; + .debug_set_all = mgmt_debug_client_be_set +}; static struct cmd_node mgmt_dbg_node = { .name = "debug mgmt client backend", @@ -867,8 +876,13 @@ struct mgmt_be_client *mgmt_be_client_create(const char *client_name, uintptr_t user_data, struct event_loop *event_loop) { - struct mgmt_be_client *client = - XCALLOC(MTYPE_MGMTD_BE_CLIENT, sizeof(*client)); + struct mgmt_be_client *client; + + if (mgmt_be_client) + return NULL; + + client = XCALLOC(MTYPE_MGMTD_BE_CLIENT, sizeof(*client)); + mgmt_be_client = client; /* Only call after frr_init() */ assert(running_config); @@ -902,6 +916,8 @@ void mgmt_be_client_lib_vty_init(void) void mgmt_be_client_destroy(struct mgmt_be_client *client) { + assert(client == mgmt_be_client); + MGMTD_BE_CLIENT_DBG("Destroying MGMTD Backend Client '%s'", client->name); @@ -912,4 +928,6 @@ void mgmt_be_client_destroy(struct mgmt_be_client *client) XFREE(MTYPE_MGMTD_BE_CLIENT_NAME, client->name); XFREE(MTYPE_MGMTD_BE_CLIENT, client); + + mgmt_be_client = NULL; } diff --git a/lib/mgmt_fe_client.c b/lib/mgmt_fe_client.c index aab553049d..e99826761e 100644 --- a/lib/mgmt_fe_client.c +++ b/lib/mgmt_fe_client.c @@ -47,8 +47,11 @@ struct mgmt_fe_client { #define FOREACH_SESSION_IN_LIST(client, session) \ frr_each_safe (mgmt_sessions, &(client)->sessions, (session)) -struct debug mgmt_dbg_fe_client = {0, "Management frontend client operations"}; +struct debug mgmt_dbg_fe_client = { + .desc = "Management frontend client operations" +}; +struct mgmt_fe_client *mgmt_fe_client; static inline const char *dsid2name(Mgmtd__DatastoreId id) { @@ -543,6 +546,16 @@ static int mgmt_fe_client_notify_disconnect(struct msg_conn *conn) return _notify_connect_disconnect(client, false); } +static void mgmt_debug_client_fe_set(uint32_t mode, bool set) +{ + DEBUG_FLAGS_SET(&mgmt_dbg_fe_client, mode, set); + + if (!mgmt_fe_client) + return; + + mgmt_fe_client->client.conn.debug = + DEBUG_MODE_CHECK(&mgmt_dbg_fe_client, DEBUG_MODE_ALL); +} DEFPY(debug_mgmt_client_fe, debug_mgmt_client_fe_cmd, "[no] debug mgmt client frontend", @@ -550,18 +563,11 @@ DEFPY(debug_mgmt_client_fe, debug_mgmt_client_fe_cmd, "client\n" "frontend\n") { - uint32_t mode = DEBUG_NODE2MODE(vty->node); - - DEBUG_MODE_SET(&mgmt_dbg_fe_client, mode, !no); + mgmt_debug_client_fe_set(DEBUG_NODE2MODE(vty->node), !no); return CMD_SUCCESS; } -static void mgmt_debug_client_fe_set_all(uint32_t flags, bool set) -{ - DEBUG_FLAGS_SET(&mgmt_dbg_fe_client, flags, set); -} - static int mgmt_debug_fe_client_config_write(struct vty *vty) { if (DEBUG_MODE_CHECK(&mgmt_dbg_fe_client, DEBUG_MODE_CONF)) @@ -577,7 +583,8 @@ void mgmt_debug_fe_client_show_debug(struct vty *vty) } static struct debug_callbacks mgmt_dbg_fe_client_cbs = { - .debug_set_all = mgmt_debug_client_fe_set_all}; + .debug_set_all = mgmt_debug_client_fe_set +}; static struct cmd_node mgmt_dbg_node = { .name = "debug mgmt client frontend", @@ -594,8 +601,13 @@ struct mgmt_fe_client *mgmt_fe_client_create(const char *client_name, uintptr_t user_data, struct event_loop *event_loop) { - struct mgmt_fe_client *client = - XCALLOC(MTYPE_MGMTD_FE_CLIENT, sizeof(*client)); + struct mgmt_fe_client *client; + + if (mgmt_fe_client) + return NULL; + + client = XCALLOC(MTYPE_MGMTD_FE_CLIENT, sizeof(*client)); + mgmt_fe_client = client; client->name = XSTRDUP(MTYPE_MGMTD_FE_CLIENT_NAME, client_name); client->user_data = user_data; @@ -692,6 +704,8 @@ void mgmt_fe_client_destroy(struct mgmt_fe_client *client) { struct mgmt_fe_client_session *session; + assert(client == mgmt_fe_client); + MGMTD_FE_CLIENT_DBG("Destroying MGMTD Frontend Client '%s'", client->name); @@ -702,4 +716,6 @@ void mgmt_fe_client_destroy(struct mgmt_fe_client *client) XFREE(MTYPE_MGMTD_FE_CLIENT_NAME, client->name); XFREE(MTYPE_MGMTD_FE_CLIENT, client); + + mgmt_fe_client = NULL; } diff --git a/mgmtd/mgmt_be_adapter.c b/mgmtd/mgmt_be_adapter.c index 0043c9d8e0..ed93244b83 100644 --- a/mgmtd/mgmt_be_adapter.c +++ b/mgmtd/mgmt_be_adapter.c @@ -668,6 +668,8 @@ struct msg_conn *mgmt_be_create_adapter(int conn_fd, union sockunion *from) MGMTD_BE_MAX_NUM_MSG_WRITE, MGMTD_BE_MSG_MAX_LEN, adapter, "BE-adapter"); + adapter->conn->debug = DEBUG_MODE_CHECK(&mgmt_debug_be, DEBUG_MODE_ALL); + MGMTD_BE_ADAPTER_DBG("Added new MGMTD Backend adapter '%s'", adapter->name); @@ -677,8 +679,7 @@ struct msg_conn *mgmt_be_create_adapter(int conn_fd, union sockunion *from) struct mgmt_be_client_adapter * mgmt_be_get_adapter_by_id(enum mgmt_be_client_id id) { - return (id < MGMTD_BE_CLIENT_ID_MAX ? mgmt_be_adapters_by_id[id] - : NULL); + return (id < MGMTD_BE_CLIENT_ID_MAX ? mgmt_be_adapters_by_id[id] : NULL); } struct mgmt_be_client_adapter * @@ -687,6 +688,14 @@ mgmt_be_get_adapter_by_name(const char *name) return mgmt_be_find_adapter_by_name(name); } +void mgmt_be_adapter_toggle_client_debug(bool set) +{ + struct mgmt_be_client_adapter *adapter; + + FOREACH_ADAPTER_IN_LIST (adapter) + adapter->conn->debug = set; +} + /* * Get a full set of changes for all the config that an adapter is subscribed to * receive. diff --git a/mgmtd/mgmt_be_adapter.h b/mgmtd/mgmt_be_adapter.h index a818d658a9..e06ee115f0 100644 --- a/mgmtd/mgmt_be_adapter.h +++ b/mgmtd/mgmt_be_adapter.h @@ -149,6 +149,9 @@ mgmt_be_get_adapter_by_name(const char *name); extern struct mgmt_be_client_adapter * mgmt_be_get_adapter_by_id(enum mgmt_be_client_id id); +/* Toggle debug on or off for connected clients. */ +extern void mgmt_be_adapter_toggle_client_debug(bool set); + /* Fetch backend adapter config. */ extern int mgmt_be_get_adapter_config(struct mgmt_be_client_adapter *adapter, struct nb_config_cbs **cfg_chgs); diff --git a/mgmtd/mgmt_fe_adapter.c b/mgmtd/mgmt_fe_adapter.c index 2b2471c901..d613b7467a 100644 --- a/mgmtd/mgmt_fe_adapter.c +++ b/mgmtd/mgmt_fe_adapter.c @@ -246,6 +246,14 @@ mgmt_session_id2ctx(uint64_t session_id) return session; } +void mgmt_fe_adapter_toggle_client_debug(bool set) +{ + struct mgmt_fe_client_adapter *adapter; + + FOREACH_ADAPTER_IN_LIST (adapter) + adapter->conn->debug = set; +} + static struct mgmt_fe_session_ctx * mgmt_fe_create_session(struct mgmt_fe_client_adapter *adapter, uint64_t client_id) @@ -1132,6 +1140,9 @@ struct msg_conn *mgmt_fe_create_adapter(int conn_fd, union sockunion *from) MGMTD_FE_MAX_NUM_MSG_WRITE, MGMTD_FE_MSG_MAX_LEN, adapter, "FE-adapter"); + adapter->conn->debug = DEBUG_MODE_CHECK(&mgmt_debug_fe, + DEBUG_MODE_ALL); + adapter->setcfg_stats.min_tm = ULONG_MAX; adapter->cmt_stats.min_tm = ULONG_MAX; MGMTD_FE_ADAPTER_DBG("Added new MGMTD Frontend adapter '%s'", diff --git a/mgmtd/mgmt_fe_adapter.h b/mgmtd/mgmt_fe_adapter.h index 1560916c85..1172262a45 100644 --- a/mgmtd/mgmt_fe_adapter.h +++ b/mgmtd/mgmt_fe_adapter.h @@ -149,4 +149,8 @@ mgmt_fe_get_session_commit_stats(uint64_t session_id); extern void mgmt_fe_adapter_status_write(struct vty *vty, bool detail); extern void mgmt_fe_adapter_perf_measurement(struct vty *vty, bool config); extern void mgmt_fe_adapter_reset_perf_stats(struct vty *vty); + +/* Toggle debug on or off for connected clients. */ +extern void mgmt_fe_adapter_toggle_client_debug(bool set); + #endif /* _FRR_MGMTD_FE_ADAPTER_H_ */ diff --git a/mgmtd/mgmt_vty.c b/mgmtd/mgmt_vty.c index 0f6df9f129..3116ccbaf7 100644 --- a/mgmtd/mgmt_vty.c +++ b/mgmtd/mgmt_vty.c @@ -438,12 +438,18 @@ DEFPY(debug_mgmt, debug_mgmt_cmd, { uint32_t mode = DEBUG_NODE2MODE(vty->node); - if (be) + if (be) { DEBUG_MODE_SET(&mgmt_debug_be, mode, !no); + mgmt_be_adapter_toggle_client_debug( + DEBUG_MODE_CHECK(&mgmt_debug_be, DEBUG_MODE_ALL)); + } if (ds) DEBUG_MODE_SET(&mgmt_debug_ds, mode, !no); - if (fe) + if (fe) { DEBUG_MODE_SET(&mgmt_debug_fe, mode, !no); + mgmt_fe_adapter_toggle_client_debug( + DEBUG_MODE_CHECK(&mgmt_debug_fe, DEBUG_MODE_ALL)); + } if (txn) DEBUG_MODE_SET(&mgmt_debug_txn, mode, !no); diff --git a/ospf6d/ospf6_top.c b/ospf6d/ospf6_top.c index ef312cbe3a..63672a96e7 100644 --- a/ospf6d/ospf6_top.c +++ b/ospf6d/ospf6_top.c @@ -1070,148 +1070,6 @@ DEFUN (no_ospf6_distance_ospf6, return CMD_SUCCESS; } -DEFUN_HIDDEN (ospf6_interface_area, - ospf6_interface_area_cmd, - "interface IFNAME area <A.B.C.D|(0-4294967295)>", - "Enable routing on an IPv6 interface\n" - IFNAME_STR - "Specify the OSPF6 area ID\n" - "OSPF6 area ID in IPv4 address notation\n" - "OSPF6 area ID in decimal notation\n" - ) -{ - VTY_DECLVAR_CONTEXT(ospf6, ospf6); - int idx_ifname = 1; - int idx_ipv4 = 3; - struct ospf6_area *oa; - struct ospf6_interface *oi; - struct interface *ifp; - uint32_t area_id; - int format; - - vty_out(vty, - "This command is deprecated, because it is not VRF-aware.\n"); - vty_out(vty, - "Please, use \"ipv6 ospf6 area\" on an interface instead.\n"); - - /* find/create ospf6 interface */ - ifp = if_get_by_name(argv[idx_ifname]->arg, ospf6->vrf_id, ospf6->name); - oi = (struct ospf6_interface *)ifp->info; - if (oi == NULL) - oi = ospf6_interface_create(ifp); - if (oi->area) { - vty_out(vty, "%s already attached to Area %s\n", - oi->interface->name, oi->area->name); - return CMD_SUCCESS; - } - - if (str2area_id(argv[idx_ipv4]->arg, &area_id, &format)) { - vty_out(vty, "Malformed Area-ID: %s\n", argv[idx_ipv4]->arg); - return CMD_WARNING_CONFIG_FAILED; - } - - oi->area_id = area_id; - oi->area_id_format = format; - - oa = ospf6_area_lookup(area_id, ospf6); - if (oa == NULL) - oa = ospf6_area_create(area_id, ospf6, format); - - /* attach interface to area */ - listnode_add(oa->if_list, oi); /* sort ?? */ - oi->area = oa; - - SET_FLAG(oa->flag, OSPF6_AREA_ENABLE); - - /* ospf6 process is currently disabled, not much more to do */ - if (CHECK_FLAG(ospf6->flag, OSPF6_DISABLED)) - return CMD_SUCCESS; - - /* start up */ - ospf6_interface_enable(oi); - - /* If the router is ABR, originate summary routes */ - if (ospf6_check_and_set_router_abr(ospf6)) { - ospf6_abr_enable_area(oa); - ospf6_schedule_abr_task(oa->ospf6); - } - - return CMD_SUCCESS; -} - -DEFUN_HIDDEN (no_ospf6_interface_area, - no_ospf6_interface_area_cmd, - "no interface IFNAME area <A.B.C.D|(0-4294967295)>", - NO_STR - "Disable routing on an IPv6 interface\n" - IFNAME_STR - "Specify the OSPF6 area ID\n" - "OSPF6 area ID in IPv4 address notation\n" - "OSPF6 area ID in decimal notation\n" - ) -{ - VTY_DECLVAR_CONTEXT(ospf6, ospf6); - int idx_ifname = 2; - int idx_ipv4 = 4; - struct ospf6_interface *oi; - struct ospf6_area *oa; - struct interface *ifp; - uint32_t area_id; - - vty_out(vty, - "This command is deprecated, because it is not VRF-aware.\n"); - vty_out(vty, - "Please, use \"no ipv6 ospf6 area\" on an interface instead.\n"); - - /* find/create ospf6 interface */ - ifp = if_get_by_name(argv[idx_ifname]->arg, ospf6->vrf_id, ospf6->name); - - if (ifp == NULL) { - vty_out(vty, "No such interface %s\n", argv[idx_ifname]->arg); - return CMD_SUCCESS; - } - - oi = (struct ospf6_interface *)ifp->info; - if (oi == NULL) { - vty_out(vty, "Interface %s not enabled\n", ifp->name); - return CMD_SUCCESS; - } - - /* parse Area-ID */ - if (inet_pton(AF_INET, argv[idx_ipv4]->arg, &area_id) != 1) - area_id = htonl(strtoul(argv[idx_ipv4]->arg, NULL, 10)); - - /* Verify Area */ - if (oi->area == NULL) { - vty_out(vty, "%s not attached to area %s\n", - oi->interface->name, argv[idx_ipv4]->arg); - return CMD_SUCCESS; - } - - if (oi->area->area_id != area_id) { - vty_out(vty, "Wrong Area-ID: %s is attached to area %s\n", - oi->interface->name, oi->area->name); - return CMD_SUCCESS; - } - - ospf6_interface_disable(oi); - - oa = oi->area; - listnode_delete(oi->area->if_list, oi); - oi->area = (struct ospf6_area *)NULL; - - /* Withdraw inter-area routes from this area, if necessary */ - if (oa->if_list->count == 0) { - UNSET_FLAG(oa->flag, OSPF6_AREA_ENABLE); - ospf6_abr_disable_area(oa); - } - - oi->area_id = 0; - oi->area_id_format = OSPF6_AREA_FMT_UNSET; - - return CMD_SUCCESS; -} - DEFUN (ospf6_stub_router_admin, ospf6_stub_router_admin_cmd, "stub-router administrative", @@ -2360,8 +2218,6 @@ void ospf6_top_init(void) install_element(OSPF6_NODE, &ospf6_timers_lsa_cmd); install_element(OSPF6_NODE, &no_ospf6_timers_lsa_cmd); - install_element(OSPF6_NODE, &ospf6_interface_area_cmd); - install_element(OSPF6_NODE, &no_ospf6_interface_area_cmd); install_element(OSPF6_NODE, &ospf6_stub_router_admin_cmd); install_element(OSPF6_NODE, &no_ospf6_stub_router_admin_cmd); diff --git a/tests/topotests/all_protocol_startup/r1/ospf6d.conf b/tests/topotests/all_protocol_startup/r1/ospf6d.conf index 33c26501ba..31c904b415 100644 --- a/tests/topotests/all_protocol_startup/r1/ospf6d.conf +++ b/tests/topotests/all_protocol_startup/r1/ospf6d.conf @@ -6,12 +6,12 @@ log file ospf6d.log ! debug ospf6 neighbor ! interface r1-eth4 - ipv6 ospf6 hello-interval 1 + ipv6 ospf6 area 0.0.0.0 + ipv6 ospf6 hello-interval 1 ! router ospf6 ospf6 router-id 192.168.0.1 log-adjacency-changes - interface r1-eth4 area 0.0.0.0 ! line vty ! diff --git a/tests/topotests/bfd_ospf_topo1/rt1/ospf6d.conf b/tests/topotests/bfd_ospf_topo1/rt1/ospf6d.conf index 98da8c2619..a8ce562da2 100644 --- a/tests/topotests/bfd_ospf_topo1/rt1/ospf6d.conf +++ b/tests/topotests/bfd_ospf_topo1/rt1/ospf6d.conf @@ -6,12 +6,14 @@ hostname rt1 password 1 ! interface eth-rt2 + ipv6 ospf6 area 0.0.0.0 ipv6 ospf6 hello-interval 2 ipv6 ospf6 dead-interval 8 ipv6 ospf6 network broadcast ipv6 ospf6 bfd ! interface eth-rt3 + ipv6 ospf6 area 0.0.0.0 ipv6 ospf6 hello-interval 2 ipv6 ospf6 dead-interval 8 ipv6 ospf6 network broadcast @@ -19,7 +21,5 @@ interface eth-rt3 ! router ospf6 ospf6 router-id 1.1.1.1 - interface eth-rt2 area 0.0.0.0 - interface eth-rt3 area 0.0.0.0 redistribute connected ! diff --git a/tests/topotests/bfd_ospf_topo1/rt2/ospf6d.conf b/tests/topotests/bfd_ospf_topo1/rt2/ospf6d.conf index 34b0902094..f04d017681 100644 --- a/tests/topotests/bfd_ospf_topo1/rt2/ospf6d.conf +++ b/tests/topotests/bfd_ospf_topo1/rt2/ospf6d.conf @@ -5,19 +5,19 @@ hostname rt2 password 1 ! interface eth-rt1 + ipv6 ospf6 area 0.0.0.0 ipv6 ospf6 hello-interval 2 ipv6 ospf6 dead-interval 8 ipv6 ospf6 network broadcast ipv6 ospf6 bfd ! interface eth-rt5 + ipv6 ospf6 area 0.0.0.0 ipv6 ospf6 hello-interval 2 ipv6 ospf6 dead-interval 8 ipv6 ospf6 network broadcast ! router ospf6 ospf6 router-id 2.2.2.2 - interface eth-rt1 area 0.0.0.0 - interface eth-rt5 area 0.0.0.0 redistribute connected ! diff --git a/tests/topotests/bfd_ospf_topo1/rt3/ospf6d.conf b/tests/topotests/bfd_ospf_topo1/rt3/ospf6d.conf index 8ab4eee1d3..faf975497d 100644 --- a/tests/topotests/bfd_ospf_topo1/rt3/ospf6d.conf +++ b/tests/topotests/bfd_ospf_topo1/rt3/ospf6d.conf @@ -5,19 +5,19 @@ hostname rt3 password 1 ! interface eth-rt1 + ipv6 ospf6 area 0.0.0.0 ipv6 ospf6 hello-interval 2 ipv6 ospf6 dead-interval 8 ipv6 ospf6 network broadcast ipv6 ospf6 bfd ! interface eth-rt4 + ipv6 ospf6 area 0.0.0.0 ipv6 ospf6 hello-interval 2 ipv6 ospf6 dead-interval 8 ipv6 ospf6 network broadcast ! router ospf6 ospf6 router-id 3.3.3.3 - interface eth-rt1 area 0.0.0.0 - interface eth-rt4 area 0.0.0.0 redistribute connected ! diff --git a/tests/topotests/bfd_ospf_topo1/rt4/ospf6d.conf b/tests/topotests/bfd_ospf_topo1/rt4/ospf6d.conf index 138b688140..c96093b98a 100644 --- a/tests/topotests/bfd_ospf_topo1/rt4/ospf6d.conf +++ b/tests/topotests/bfd_ospf_topo1/rt4/ospf6d.conf @@ -5,18 +5,18 @@ hostname rt4 password 1 ! interface eth-rt3 + ipv6 ospf6 area 0.0.0.0 ipv6 ospf6 hello-interval 2 ipv6 ospf6 dead-interval 8 ipv6 ospf6 network broadcast ! interface eth-rt5 + ipv6 ospf6 area 0.0.0.0 ipv6 ospf6 hello-interval 2 ipv6 ospf6 dead-interval 8 ipv6 ospf6 network broadcast ! router ospf6 ospf6 router-id 4.4.4.4 - interface eth-rt3 area 0.0.0.0 - interface eth-rt5 area 0.0.0.0 redistribute connected ! diff --git a/tests/topotests/bfd_ospf_topo1/rt5/ospf6d.conf b/tests/topotests/bfd_ospf_topo1/rt5/ospf6d.conf index 6eb4fe59a8..6d40d17d50 100644 --- a/tests/topotests/bfd_ospf_topo1/rt5/ospf6d.conf +++ b/tests/topotests/bfd_ospf_topo1/rt5/ospf6d.conf @@ -5,18 +5,18 @@ hostname rt5 password 1 ! interface eth-rt2 + ipv6 ospf6 area 0.0.0.0 ipv6 ospf6 network broadcast ipv6 ospf6 hello-interval 2 ipv6 ospf6 dead-interval 8 ! interface eth-rt4 + ipv6 ospf6 area 0.0.0.0 ipv6 ospf6 network broadcast ipv6 ospf6 hello-interval 2 ipv6 ospf6 dead-interval 8 ! router ospf6 ospf6 router-id 5.5.5.5 - interface eth-rt2 area 0.0.0.0 - interface eth-rt4 area 0.0.0.0 redistribute connected ! diff --git a/tests/topotests/bfd_profiles_topo1/r4/ospf6d.conf b/tests/topotests/bfd_profiles_topo1/r4/ospf6d.conf index 4ef28c39ca..948874c0e5 100644 --- a/tests/topotests/bfd_profiles_topo1/r4/ospf6d.conf +++ b/tests/topotests/bfd_profiles_topo1/r4/ospf6d.conf @@ -1,4 +1,5 @@ interface r4-eth1 + ipv6 ospf6 area 0.0.0.0 ipv6 ospf6 bfd profile fast-tx ipv6 ospf6 hello-interval 2 ipv6 ospf6 dead-interval 10 @@ -6,5 +7,4 @@ interface r4-eth1 router ospf6 ospf6 router-id 10.254.254.4 redistribute connected - interface r4-eth1 area 0.0.0.0 ! diff --git a/tests/topotests/bfd_profiles_topo1/r5/ospf6d.conf b/tests/topotests/bfd_profiles_topo1/r5/ospf6d.conf index 20b53cfc55..f6e8dc3b67 100644 --- a/tests/topotests/bfd_profiles_topo1/r5/ospf6d.conf +++ b/tests/topotests/bfd_profiles_topo1/r5/ospf6d.conf @@ -1,4 +1,5 @@ interface r5-eth0 + ipv6 ospf6 area 0.0.0.0 ipv6 ospf6 bfd ipv6 ospf6 hello-interval 2 ipv6 ospf6 dead-interval 10 @@ -6,5 +7,4 @@ interface r5-eth0 router ospf6 ospf6 router-id 10.254.254.5 redistribute connected - interface r5-eth0 area 0.0.0.0 ! diff --git a/tests/topotests/bgp_features/r1/ospf6d.conf b/tests/topotests/bgp_features/r1/ospf6d.conf index 9afc6f4919..3e6196ecaf 100644 --- a/tests/topotests/bgp_features/r1/ospf6d.conf +++ b/tests/topotests/bgp_features/r1/ospf6d.conf @@ -3,19 +3,19 @@ log file ospf6d.log ! debug ospf6 neighbor ! interface r1-lo + ipv6 ospf6 area 0.0.0.0 ! interface r1-eth1 + ipv6 ospf6 area 0.0.0.0 ipv6 ospf6 priority 10 ! interface r1-eth2 + ipv6 ospf6 area 0.0.0.0 ipv6 ospf6 priority 10 ! router ospf6 ospf6 router-id 192.168.0.1 log-adjacency-changes - interface r1-lo area 0.0.0.0 - interface r1-eth1 area 0.0.0.0 - interface r1-eth2 area 0.0.0.0 ! line vty ! diff --git a/tests/topotests/bgp_features/r2/ospf6d.conf b/tests/topotests/bgp_features/r2/ospf6d.conf index 7fe535651e..56aecd006c 100644 --- a/tests/topotests/bgp_features/r2/ospf6d.conf +++ b/tests/topotests/bgp_features/r2/ospf6d.conf @@ -3,19 +3,19 @@ log file ospf6d.log ! debug ospf6 neighbor ! interface r2-lo + ipv6 ospf6 area 0.0.0.0 ! interface r2-eth1 + ipv6 ospf6 area 0.0.0.0 ipv6 ospf6 priority 5 ! interface r2-eth2 + ipv6 ospf6 area 0.0.0.0 ipv6 ospf6 priority 10 ! router ospf6 ospf6 router-id 192.168.0.2 log-adjacency-changes - interface r2-lo area 0.0.0.0 - interface r2-eth1 area 0.0.0.0 - interface r2-eth2 area 0.0.0.0 ! line vty ! diff --git a/tests/topotests/bgp_features/r3/ospf6d.conf b/tests/topotests/bgp_features/r3/ospf6d.conf index 07325b69b0..f15b9d9ea5 100644 --- a/tests/topotests/bgp_features/r3/ospf6d.conf +++ b/tests/topotests/bgp_features/r3/ospf6d.conf @@ -3,19 +3,19 @@ log file ospf6d.log ! debug ospf6 neighbor ! interface r3-lo + ipv6 ospf6 area 0.0.0.0 ! interface r3-eth1 + ipv6 ospf6 area 0.0.0.0 ipv6 ospf6 priority 5 ! interface r3-eth2 + ipv6 ospf6 area 0.0.0.0 ipv6 ospf6 priority 5 ! router ospf6 ospf6 router-id 192.168.0.3 log-adjacency-changes - interface r3-lo area 0.0.0.0 - interface r3-eth1 area 0.0.0.0 - interface r3-eth2 area 0.0.0.0 ! line vty ! diff --git a/tests/topotests/bgp_snmp_bgp4v2mib/r1/bgpd.conf b/tests/topotests/bgp_snmp_bgp4v2mib/r1/bgpd.conf index d82a21e1f9..144466e418 100644 --- a/tests/topotests/bgp_snmp_bgp4v2mib/r1/bgpd.conf +++ b/tests/topotests/bgp_snmp_bgp4v2mib/r1/bgpd.conf @@ -1,24 +1,28 @@ ! +!debug bgp updates +! router bgp 65001 no bgp ebgp-requires-policy no bgp network import-check no bgp default ipv4-unicast - neighbor 192.168.12.2 remote-as external - neighbor 192.168.12.2 timers 1 3 - neighbor 192.168.12.2 timers connect 1 - neighbor 2001:db8::12:2 remote-as external - neighbor 2001:db8::12:2 timers 1 3 - neighbor 2001:db8::12:2 timers connect 1 + neighbor 192.168.12.4 remote-as external + neighbor 192.168.12.4 timers 1 3 + neighbor 192.168.12.4 timers connect 1 + neighbor 2001:db8::12:4 remote-as external + neighbor 2001:db8::12:4 timers 1 3 + neighbor 2001:db8::12:4 timers connect 1 ! address-family ipv4 unicast network 10.0.0.0/31 route-map p1 network 10.0.0.2/32 route-map p2 - neighbor 192.168.12.2 activate + neighbor 192.168.12.4 activate + neighbor 192.168.12.4 addpath-tx-all-paths + network 10.10.10.10/32 exit-address-family address-family ipv6 unicast network 2001:db8::1/128 route-map p1 network 2001:db8:1::/56 route-map p2 - neighbor 2001:db8::12:2 activate + neighbor 2001:db8::12:4 activate exit-address-family ! route-map p1 permit 10 @@ -28,4 +32,3 @@ route-map p2 permit 10 set metric 2 set origin incomplete exit -! diff --git a/tests/topotests/bgp_snmp_bgp4v2mib/r2/bgpd.conf b/tests/topotests/bgp_snmp_bgp4v2mib/r2/bgpd.conf index cf0013e1b7..55686f407a 100644 --- a/tests/topotests/bgp_snmp_bgp4v2mib/r2/bgpd.conf +++ b/tests/topotests/bgp_snmp_bgp4v2mib/r2/bgpd.conf @@ -5,18 +5,20 @@ router bgp 65002 no bgp ebgp-requires-policy no bgp network import-check no bgp default ipv4-unicast - neighbor 192.168.12.1 remote-as external - neighbor 192.168.12.1 timers 1 3 - neighbor 192.168.12.1 timers connect 1 - neighbor 2001:db8::12:1 remote-as external - neighbor 2001:db8::12:1 timers 1 3 - neighbor 2001:db8::12:1 timers connect 1 + neighbor 192.168.12.4 remote-as external + neighbor 192.168.12.4 timers 1 3 + neighbor 192.168.12.4 timers connect 1 + neighbor 2001:db8::12:4 remote-as external + neighbor 2001:db8::12:4 timers 1 3 + neighbor 2001:db8::12:4 timers connect 1 ! address-family ipv4 unicast - neighbor 192.168.12.1 activate + neighbor 192.168.12.4 activate + neighbor 192.168.12.4 addpath-tx-all-paths + exit-address-family address-family ipv6 unicast - neighbor 2001:db8::12:1 activate + neighbor 2001:db8::12:4 activate exit-address-family ! agentx diff --git a/tests/topotests/bgp_snmp_bgp4v2mib/r3/bgpd.conf b/tests/topotests/bgp_snmp_bgp4v2mib/r3/bgpd.conf new file mode 100644 index 0000000000..71dbda0bc1 --- /dev/null +++ b/tests/topotests/bgp_snmp_bgp4v2mib/r3/bgpd.conf @@ -0,0 +1,25 @@ +! +!debug bgp updates +! +router bgp 65003 + no bgp ebgp-requires-policy + no bgp network import-check + no bgp default ipv4-unicast + neighbor 192.168.12.4 remote-as external + neighbor 192.168.12.4 timers 1 3 + neighbor 192.168.12.4 timers connect 1 + neighbor 2001:db8::12:4 remote-as external + neighbor 2001:db8::12:4 timers 1 3 + neighbor 2001:db8::12:4 timers connect 1 + ! + address-family ipv4 unicast + neighbor 192.168.12.4 activate + neighbor 192.168.12.4 addpath-tx-all-paths + network 10.10.10.10/32 + exit-address-family + address-family ipv6 unicast + neighbor 2001:db8::12:4 activate + exit-address-family +! +agentx +! diff --git a/tests/topotests/bgp_snmp_bgp4v2mib/r3/zebra.conf b/tests/topotests/bgp_snmp_bgp4v2mib/r3/zebra.conf new file mode 100644 index 0000000000..398af65ffe --- /dev/null +++ b/tests/topotests/bgp_snmp_bgp4v2mib/r3/zebra.conf @@ -0,0 +1,5 @@ +! +interface r3-eth0 + ip address 192.168.12.3/24 + ipv6 address 2001:db8::12:3/64 +! diff --git a/tests/topotests/bgp_snmp_bgp4v2mib/rr/bgpd.conf b/tests/topotests/bgp_snmp_bgp4v2mib/rr/bgpd.conf new file mode 100644 index 0000000000..5ebbde6703 --- /dev/null +++ b/tests/topotests/bgp_snmp_bgp4v2mib/rr/bgpd.conf @@ -0,0 +1,67 @@ +! +! debug bgp updates +! +router bgp 65004 + no bgp ebgp-requires-policy + no bgp network import-check + no bgp default ipv4-unicast + neighbor 192.168.12.1 remote-as external + neighbor 192.168.12.1 timers 1 3 + neighbor 192.168.12.1 timers connect 1 + neighbor 192.168.12.2 remote-as external + neighbor 192.168.12.2 timers 1 3 + neighbor 192.168.12.2 timers connect 1 + neighbor 192.168.12.3 remote-as external + neighbor 192.168.12.3 timers 1 3 + neighbor 192.168.12.3 timers connect 1 + neighbor 2001:db8::12:1 remote-as external + neighbor 2001:db8::12:1 timers 1 3 + neighbor 2001:db8::12:1 timers connect 1 + neighbor 2001:db8::12:2 remote-as external + neighbor 2001:db8::12:2 timers 1 3 + neighbor 2001:db8::12:2 timers connect 1 + neighbor 2001:db8::12:3 remote-as external + neighbor 2001:db8::12:3 timers 1 3 + neighbor 2001:db8::12:3 timers connect 1 + ! + address-family ipv4 unicast + network 10.0.0.0/31 route-map p1 + network 10.0.0.2/32 route-map p2 + neighbor 192.168.12.1 activate + neighbor 192.168.12.2 activate + neighbor 192.168.12.2 addpath-tx-all-paths + neighbor 192.168.12.2 route-map r2-import in + neighbor 192.168.12.2 route-map r2-export out +! neighbor 192.168.12.2 soft-reconfiguration inbound + neighbor 192.168.12.3 activate + exit-address-family + address-family ipv6 unicast + network 2001:db8::1/128 route-map p1 + network 2001:db8:1::/56 route-map p2 + neighbor 2001:db8::12:1 activate + neighbor 2001:db8::12:2 activate + neighbor 2001:db8::12:2 addpath-tx-all-paths + neighbor 2001:db8::12:3 activate + exit-address-family + + +ip prefix-list r2-toto permit any + +route-map r2-import permit 10 + match ip address prefix-list r2-toto + +route-map r2-export permit 10 + match ip address prefix-list r2-toto +! +route-map p1 permit 10 + set metric 1 +exit +route-map p2 permit 10 + set metric 2 + set origin incomplete +exit + + + +agentx +! diff --git a/tests/topotests/bgp_snmp_bgp4v2mib/rr/zebra.conf b/tests/topotests/bgp_snmp_bgp4v2mib/rr/zebra.conf new file mode 100644 index 0000000000..092673b8a9 --- /dev/null +++ b/tests/topotests/bgp_snmp_bgp4v2mib/rr/zebra.conf @@ -0,0 +1,5 @@ +! +interface rr-eth0 + ip address 192.168.12.4/24 + ipv6 address 2001:db8::12:4/64 +! diff --git a/tests/topotests/bgp_snmp_bgp4v2mib/test_bgp_snmp_bgp4v2mib.py b/tests/topotests/bgp_snmp_bgp4v2mib/test_bgp_snmp_bgp4v2mib.py index 14dadd4504..8cd49e3548 100755 --- a/tests/topotests/bgp_snmp_bgp4v2mib/test_bgp_snmp_bgp4v2mib.py +++ b/tests/topotests/bgp_snmp_bgp4v2mib/test_bgp_snmp_bgp4v2mib.py @@ -32,10 +32,14 @@ pytestmark = [pytest.mark.bgpd, pytest.mark.snmp] def build_topo(tgen): tgen.add_router("r1") tgen.add_router("r2") + tgen.add_router("r3") + tgen.add_router("rr") switch = tgen.add_switch("s1") switch.add_link(tgen.gears["r1"]) switch.add_link(tgen.gears["r2"]) + switch.add_link(tgen.gears["r3"]) + switch.add_link(tgen.gears["rr"]) def setup_module(mod): @@ -57,14 +61,15 @@ def setup_module(mod): "-M snmp", ) - tgen.gears["r2"].load_config( + r2 = tgen.gears["r2"] + r2.load_config( TopoRouter.RD_SNMP, - os.path.join(CWD, "{}/snmpd.conf".format(rname)), + os.path.join(CWD, "{}/snmpd.conf".format(r2.name)), "-Le -Ivacm_conf,usmConf,iquery -V -DAgentX", ) - tgen.gears["r2"].load_config( + r2.load_config( TopoRouter.RD_TRAP, - os.path.join(CWD, "{}/snmptrapd.conf".format(rname)), + os.path.join(CWD, "{}/snmptrapd.conf".format(r2.name)), " -On -OQ ", ) @@ -81,27 +86,29 @@ def test_bgp_snmp_bgp4v2(): r1 = tgen.gears["r1"] r2 = tgen.gears["r2"] + rr = tgen.gears["rr"] def _bgp_converge_summary(): output = json.loads(r2.vtysh_cmd("show bgp summary json")) expected = { "ipv4Unicast": { "peers": { - "192.168.12.1": { + "192.168.12.4": { "state": "Established", - "pfxRcd": 2, + "pfxRcd": 6, } } }, "ipv6Unicast": { "peers": { - "2001:db8::12:1": { + "2001:db8::12:4": { "state": "Established", - "pfxRcd": 2, + "pfxRcd": 4, } } }, } + # tgen.mininet_cli() return topotest.json_cmp(output, expected) test_func = functools.partial(_bgp_converge_summary) @@ -144,6 +151,7 @@ def test_bgp_snmp_bgp4v2(): } }, } + # tgen.mininet_cli() return topotest.json_cmp(output, expected) test_func = functools.partial(_bgp_converge_prefixes) @@ -154,11 +162,12 @@ def test_bgp_snmp_bgp4v2(): def _snmpwalk_remote_addr(): expected = { - "1.3.6.1.3.5.1.1.2.1.5.1.1.192.168.12.1": "C0 A8 0C 01", - "1.3.6.1.3.5.1.1.2.1.5.1.2.32.1.13.184.0.0.0.0.0.0.0.0.0.18.0.1": "20 01 0D B8 00 00 00 00 00 00 00 00 00 12 00 01", + "1.3.6.1.3.5.1.1.2.1.5.1.1.192.168.12.4": "C0 A8 0C 04", + "1.3.6.1.3.5.1.1.2.1.5.1.2.32.1.13.184.0.0.0.0.0.0.0.0.0.18.0.4": "20 01 0D B8 00 00 00 00 00 00 00 00 00 12 00 04", } # bgp4V2PeerRemoteAddr + # tgen.mininet_cli() output, _ = snmp.walk(".1.3.6.1.3.5.1.1.2.1.5") return output == expected @@ -168,8 +177,8 @@ def test_bgp_snmp_bgp4v2(): def _snmpwalk_peer_state(): expected = { - "1.3.6.1.3.5.1.1.2.1.13.1.1.192.168.12.1": "6", - "1.3.6.1.3.5.1.1.2.1.13.1.2.32.1.13.184.0.0.0.0.0.0.0.0.0.18.0.1": "6", + "1.3.6.1.3.5.1.1.2.1.13.1.1.192.168.12.4": "6", + "1.3.6.1.3.5.1.1.2.1.13.1.2.32.1.13.184.0.0.0.0.0.0.0.0.0.18.0.4": "6", } # bgp4V2PeerState @@ -182,8 +191,8 @@ def test_bgp_snmp_bgp4v2(): def _snmpwalk_peer_last_error_code_received(): expected = { - "1.3.6.1.3.5.1.1.3.1.1.1.1.192.168.12.1": "0", - "1.3.6.1.3.5.1.1.3.1.1.1.2.32.1.13.184.0.0.0.0.0.0.0.0.0.18.0.1": "0", + "1.3.6.1.3.5.1.1.3.1.1.1.1.192.168.12.4": "0", + "1.3.6.1.3.5.1.1.3.1.1.1.2.32.1.13.184.0.0.0.0.0.0.0.0.0.18.0.4": "0", } # bgp4V2PeerLastErrorCodeReceived @@ -198,14 +207,19 @@ def test_bgp_snmp_bgp4v2(): def _snmpwalk_origin(): expected = { - "1.3.6.1.3.5.1.1.9.1.9.1.1.1.1.10.0.0.0.31.1.192.168.12.1.1": "1", - "1.3.6.1.3.5.1.1.9.1.9.1.1.1.1.10.0.0.2.32.1.192.168.12.1.1": "3", - "1.3.6.1.3.5.1.1.9.1.9.1.2.1.2.32.1.13.184.0.0.0.0.0.0.0.0.0.0.0.1.128.2.32.1.13.184.0.0.0.0.0.0.0.0.0.18.0.1.1": "1", - "1.3.6.1.3.5.1.1.9.1.9.1.2.1.2.32.1.13.184.0.1.0.0.0.0.0.0.0.0.0.0.56.2.32.1.13.184.0.0.0.0.0.0.0.0.0.18.0.1.1": "3", + "1.3.6.1.3.5.1.1.9.1.9.1.1.1.1.10.10.10.10.32.1.192.168.12.4.1": "1", + "1.3.6.1.3.5.1.1.9.1.9.1.1.1.1.10.10.10.10.32.1.192.168.12.4.2": "1", + "1.3.6.1.3.5.1.1.9.1.9.1.1.1.1.10.0.0.0.31.1.192.168.12.4.1": "1", + "1.3.6.1.3.5.1.1.9.1.9.1.1.1.1.10.0.0.0.31.1.192.168.12.4.2": "1", + "1.3.6.1.3.5.1.1.9.1.9.1.1.1.1.10.0.0.2.32.1.192.168.12.4.1": "3", + "1.3.6.1.3.5.1.1.9.1.9.1.1.1.1.10.0.0.2.32.1.192.168.12.4.2": "3", + "1.3.6.1.3.5.1.1.9.1.9.1.2.1.2.32.1.13.184.0.0.0.0.0.0.0.0.0.0.0.1.128.2.32.1.13.184.0.0.0.0.0.0.0.0.0.18.0.4.1": "1", + "1.3.6.1.3.5.1.1.9.1.9.1.2.1.2.32.1.13.184.0.0.0.0.0.0.0.0.0.0.0.1.128.2.32.1.13.184.0.0.0.0.0.0.0.0.0.18.0.4.2": "1", + "1.3.6.1.3.5.1.1.9.1.9.1.2.1.2.32.1.13.184.0.1.0.0.0.0.0.0.0.0.0.0.56.2.32.1.13.184.0.0.0.0.0.0.0.0.0.18.0.4.1": "3", + "1.3.6.1.3.5.1.1.9.1.9.1.2.1.2.32.1.13.184.0.1.0.0.0.0.0.0.0.0.0.0.56.2.32.1.13.184.0.0.0.0.0.0.0.0.0.18.0.4.2": "3", } # bgp4V2NlriOrigin - # tgen.mininet_cli() output, _ = snmp.walk(".1.3.6.1.3.5.1.1.9.1.9") return output == expected @@ -215,10 +229,16 @@ def test_bgp_snmp_bgp4v2(): def _snmpwalk_med(): expected = { - "1.3.6.1.3.5.1.1.9.1.17.1.1.1.1.10.0.0.0.31.1.192.168.12.1.1": "1", - "1.3.6.1.3.5.1.1.9.1.17.1.1.1.1.10.0.0.2.32.1.192.168.12.1.1": "2", - "1.3.6.1.3.5.1.1.9.1.17.1.2.1.2.32.1.13.184.0.0.0.0.0.0.0.0.0.0.0.1.128.2.32.1.13.184.0.0.0.0.0.0.0.0.0.18.0.1.1": "1", - "1.3.6.1.3.5.1.1.9.1.17.1.2.1.2.32.1.13.184.0.1.0.0.0.0.0.0.0.0.0.0.56.2.32.1.13.184.0.0.0.0.0.0.0.0.0.18.0.1.1": "2", + "1.3.6.1.3.5.1.1.9.1.17.1.1.1.1.10.10.10.10.32.1.192.168.12.4.1": "0", + "1.3.6.1.3.5.1.1.9.1.17.1.1.1.1.10.10.10.10.32.1.192.168.12.4.2": "0", + "1.3.6.1.3.5.1.1.9.1.17.1.1.1.1.10.0.0.0.31.1.192.168.12.4.1": "1", + "1.3.6.1.3.5.1.1.9.1.17.1.1.1.1.10.0.0.0.31.1.192.168.12.4.2": "0", + "1.3.6.1.3.5.1.1.9.1.17.1.1.1.1.10.0.0.2.32.1.192.168.12.4.1": "2", + "1.3.6.1.3.5.1.1.9.1.17.1.1.1.1.10.0.0.2.32.1.192.168.12.4.2": "0", + "1.3.6.1.3.5.1.1.9.1.17.1.2.1.2.32.1.13.184.0.0.0.0.0.0.0.0.0.0.0.1.128.2.32.1.13.184.0.0.0.0.0.0.0.0.0.18.0.4.1": "1", + "1.3.6.1.3.5.1.1.9.1.17.1.2.1.2.32.1.13.184.0.0.0.0.0.0.0.0.0.0.0.1.128.2.32.1.13.184.0.0.0.0.0.0.0.0.0.18.0.4.2": "0", + "1.3.6.1.3.5.1.1.9.1.17.1.2.1.2.32.1.13.184.0.1.0.0.0.0.0.0.0.0.0.0.56.2.32.1.13.184.0.0.0.0.0.0.0.0.0.18.0.4.1": "2", + "1.3.6.1.3.5.1.1.9.1.17.1.2.1.2.32.1.13.184.0.1.0.0.0.0.0.0.0.0.0.0.56.2.32.1.13.184.0.0.0.0.0.0.0.0.0.18.0.4.2": "0", } # bgp4V2NlriMed @@ -230,96 +250,65 @@ def test_bgp_snmp_bgp4v2(): assertmsg = "Can't fetch SNMP for bgp4V2NlriMed" assert result, assertmsg + # + # traps + # + + # + # bgp4 traps + # def _snmptrap_ipv4(): - expected = [ - ("1.3.6.1.2.1.15.3.1.7.192.168.12.1", "192.168.12.1"), - ("1.3.6.1.2.1.15.3.1.14.192.168.12.1", '"06 04 "'), - ("1.3.6.1.2.1.15.3.1.2.192.168.12.1", "7"), - ("1.3.6.1.2.1.15.3.1.7.192.168.12.1", "192.168.12.1"), - ("1.3.6.1.2.1.15.3.1.14.192.168.12.1", '"06 04 "'), - ("1.3.6.1.2.1.15.3.1.2.192.168.12.1", "6"), - ] - - # load trapd resulting file - # tgen.mininet_cli() + def __get_notif_bgp4_in_trap_file(router): + snmptrapfile = "{}/{}/snmptrapd.log".format(router.logdir, router.name) + outputfile = open(snmptrapfile).read() + output = snmp.get_notif_bgp4(outputfile) - snmptrapfile = "{}/{}/snmptrapd.log".format(r2.logdir, r2.name) - outputfile = open(snmptrapfile).read() - output = snmp.trap(outputfile) - return output == expected + return output + + output = __get_notif_bgp4_in_trap_file(r2) + logger.info("output bgp4") + logger.info(output) + return snmp.is_notif_bgp4_valid(output, "192.168.12.4") # skip tests is SNMP not installed if not os.path.isfile("/usr/sbin/snmptrapd"): error_msg = "SNMP not installed - skipping" pytest.skip(error_msg) - snmptrapfile = "{}/{}/snmptrapd.log".format(r2.logdir, r2.name) - trap_file = open(snmptrapfile, "w") - trap_file.truncate(0) - trap_file.close() - r1.vtysh_cmd("clear bgp *") + rr.vtysh_cmd("clear bgp *") _, result = topotest.run_and_expect(_snmptrap_ipv4, True, count=2, wait=10) assertmsg = "Can't fetch SNMP trap for ipv4" assert result, assertmsg + # + # bgp4v2 traps + # def _snmptrap_ipv6(): - expected = [ - ("1.3.6.1.3.5.1.1.2.1.13.1.1.192.168.12.1", "7"), - ("1.3.6.1.3.5.1.1.2.1.6.1.1.192.168.12.1", "179"), - ("1.3.6.1.3.5.1.1.3.1.1.1.1.192.168.12.1", "6"), - ("1.3.6.1.3.5.1.1.3.1.2.1.1.192.168.12.1", "4"), - ("1.3.6.1.3.5.1.1.3.1.4.1.1.192.168.12.1", '"00 "'), - ("1.3.6.1.3.5.1.1.2.1.13.1.2.32.1.13.184.0.0.0.0.0.0.0.0.0.18.0.1", "7"), - ("1.3.6.1.3.5.1.1.2.1.6.1.2.32.1.13.184.0.0.0.0.0.0.0.0.0.18.0.1", "179"), - ("1.3.6.1.3.5.1.1.3.1.1.1.2.32.1.13.184.0.0.0.0.0.0.0.0.0.18.0.1", "6"), - ("1.3.6.1.3.5.1.1.3.1.2.1.2.32.1.13.184.0.0.0.0.0.0.0.0.0.18.0.1", "4"), - ( - "1.3.6.1.3.5.1.1.3.1.4.1.2.32.1.13.184.0.0.0.0.0.0.0.0.0.18.0.1", - '"00 "', - ), - ("1.3.6.1.3.5.1.1.2.1.13.1.1.192.168.12.1", "6"), - ("1.3.6.1.3.5.1.1.2.1.6.1.1.192.168.12.1", "179"), - ("1.3.6.1.3.5.1.1.2.1.13.1.2.32.1.13.184.0.0.0.0.0.0.0.0.0.18.0.1", "6"), - ("1.3.6.1.3.5.1.1.2.1.6.1.2.32.1.13.184.0.0.0.0.0.0.0.0.0.18.0.1", "179"), - ] - - expected2 = [ - ("1.3.6.1.3.5.1.1.2.1.13.1.2.32.1.13.184.0.0.0.0.0.0.0.0.0.18.0.1", "7"), - ("1.3.6.1.3.5.1.1.2.1.6.1.2.32.1.13.184.0.0.0.0.0.0.0.0.0.18.0.1", "179"), - ("1.3.6.1.3.5.1.1.3.1.1.1.2.32.1.13.184.0.0.0.0.0.0.0.0.0.18.0.1", "6"), - ("1.3.6.1.3.5.1.1.3.1.2.1.2.32.1.13.184.0.0.0.0.0.0.0.0.0.18.0.1", "4"), - ( - "1.3.6.1.3.5.1.1.3.1.4.1.2.32.1.13.184.0.0.0.0.0.0.0.0.0.18.0.1", - '"00 "', - ), - ("1.3.6.1.3.5.1.1.2.1.13.1.1.192.168.12.1", "7"), - ("1.3.6.1.3.5.1.1.2.1.6.1.1.192.168.12.1", "179"), - ("1.3.6.1.3.5.1.1.3.1.1.1.1.192.168.12.1", "6"), - ("1.3.6.1.3.5.1.1.3.1.2.1.1.192.168.12.1", "4"), - ("1.3.6.1.3.5.1.1.3.1.4.1.1.192.168.12.1", '"00 "'), - ("1.3.6.1.3.5.1.1.2.1.13.1.1.192.168.12.1", "6"), - ("1.3.6.1.3.5.1.1.2.1.6.1.1.192.168.12.1", "179"), - ("1.3.6.1.3.5.1.1.2.1.13.1.2.32.1.13.184.0.0.0.0.0.0.0.0.0.18.0.1", "6"), - ("1.3.6.1.3.5.1.1.2.1.6.1.2.32.1.13.184.0.0.0.0.0.0.0.0.0.18.0.1", "179"), - ] - - # load trapd resulting file - # tgen.mininet_cli() + def __get_notif_bgp4v2_in_trap_file(router): + snmptrapfile = "{}/{}/snmptrapd.log".format(router.logdir, router.name) + outputfile = open(snmptrapfile).read() + output = snmp.get_notif_bgp4v2(outputfile) - snmptrapfile = "{}/{}/snmptrapd.log".format(r2.logdir, r2.name) - outputfile = open(snmptrapfile).read() - output = snmp.trap(outputfile) + return output + + # tgen.mininet_cli() + output = __get_notif_bgp4v2_in_trap_file(r2) + logger.info("output bgp4v2") logger.info(output) - output_cut = output[:14] - return output_cut == expected or output_cut == expected2 + p_ipv4_addr = "1.192.168.12.4" + p_ipv6_addr = "2.32.1.13.184.0.0.0.0.0.0.0.0.0.18.0.4" + return ( + snmp.is_notif_bgp4v2_valid(output, p_ipv4_addr, "Estab") + and snmp.is_notif_bgp4v2_valid(output, p_ipv6_addr, "Estab") + and snmp.is_notif_bgp4v2_valid(output, p_ipv4_addr, "Backward") + and snmp.is_notif_bgp4v2_valid(output, p_ipv6_addr, "Backward") + ) - snmptrapfile = "{}/{}/snmptrapd.log".format(r2.logdir, r2.name) - trap_file = open(snmptrapfile, "w") - trap_file.truncate(0) - trap_file.close() + sleep(10) r2.vtysh_cmd("conf\nbgp snmp traps bgp4-mibv2") r2.vtysh_cmd("conf\nno bgp snmp traps rfc4273") - r1.vtysh_cmd("clear bgp *") + rr.vtysh_cmd("clear bgp *") + sleep(30) _, result = topotest.run_and_expect(_snmptrap_ipv6, True, count=2, wait=10) assertmsg = "Can't fetch SNMP trap for ipv6" assert result, assertmsg diff --git a/tests/topotests/lib/snmptest.py b/tests/topotests/lib/snmptest.py index 598ad05f58..5c4e97a5d2 100644 --- a/tests/topotests/lib/snmptest.py +++ b/tests/topotests/lib/snmptest.py @@ -73,39 +73,6 @@ class SnmpTester(object): # third token onwards is the value of the object return tokens[0].split(".", 1)[1] - def _parse_notification_trap(self, snmp_out): - # we use the "=" as separator thus we will have - # element of list formated "value oid" - # value for index i is corresponding to index i-1 - results = snmp_out.strip().split("=") - - # remove the notification part date, notification OID - del results[0:2] - - index = 0 - oid_list = [] - next_oid = "" - oid = "" - while index < len(results): - result = results[index].strip().split() - if index < len(results) - 1: - raw_oid = result[-1] - # remove initial "." of oid - next_oid = raw_oid.split(".", 1)[1] - # remove oid from result to have only value - del result[-1] - if index > 0: - value = " ".join(result) - # ignore remote port oid 1.3.6.1.3.5.1.1.2.1.9 since - # it's value is variable - local_port = re.search("1.3.6.1.3.5.1.1.2.1.9", oid) - if not local_port: - oid_list.append((oid, value)) - - oid = next_oid - index += 1 - return oid_list - def _parse_multiline(self, snmp_output): results = snmp_output.strip().split("\n") @@ -117,15 +84,6 @@ class SnmpTester(object): return out_dict, out_list - def _parse_multiline_trap(self, results): - out_list = [] - results = [elem for index, elem in enumerate(results) if index % 2 != 0] - - for response in results: - oid_list = self._parse_notification_trap(response) - out_list += oid_list - return out_list - def get(self, oid): cmd = "snmpget {0} {1}".format(self._snmp_config(), oid) @@ -149,10 +107,148 @@ class SnmpTester(object): result = self.router.cmd(cmd) return self._parse_multiline(result) - def trap(self, outputfile): - whitecleanfile = re.sub("\t", " ", outputfile) + def parse_notif_ipv4(self, notif): + # normalise values + notif = re.sub(":", "", notif) + notif = re.sub('"([0-9]{2}) ([0-9]{2}) "', r"\1\2", notif) + notif = re.sub('"([0-9]{2}) "', r"\1", notif) + elems = re.findall("([0-9,\.]+) = ([0-9,\.]+)", notif) + + # remove common part + elems = elems[1:] + return elems + + def is_notif_bgp4_valid(self, output_list, address): + oid_notif_type = ".1.3.6.1.6.3.1.1.4.1.0" + peer_notif_established = ".1.3.6.1.2.1.15.0.1" + peer_notif_backward = ".1.3.6.1.2.1.15.0.2" + oid_peer_last_error = ".1.3.6.1.2.1.15.3.1.14" + oid_peer_remote_addr = ".1.3.6.1.2.1.15.3.1.7" + oid_peer_state = ".1.3.6.1.2.1.15.3.1.2" + + nb_notif = len(output_list) + for nb in range(0, nb_notif - 1): + # identify type of notification + # established or BackwardTransition + + if output_list[nb][0][0] != "{}".format(oid_notif_type): + return False + + if output_list[nb][0][1] == "{}".format(peer_notif_established): + logger.info("Established notification") + elif output_list[nb][0][1] == "{}".format(peer_notif_backward): + logger.info("Backward transition notification") + else: + return False + + # same behavior for 2 notification type in bgp4 + if output_list[nb][1][0] != "{}.{}".format(oid_peer_remote_addr, address): + return False + + if output_list[nb][2][0] != "{}.{}".format(oid_peer_last_error, address): + return False + if output_list[nb][3][0] != "{}.{}".format(oid_peer_state, address): + return False + + return True + + def is_notif_bgp4v2_valid(self, output_list, address, type_requested): + oid_notif_type = ".1.3.6.1.6.3.1.1.4.1.0" + peer_notif_established = ".1.3.6.1.3.5.1.0.1" + peer_notif_backward = ".1.3.6.1.3.5.1.0.2" + oid_peer_state = ".1.3.6.1.3.5.1.1.2.1.13" + oid_peer_local_port = ".1.3.6.1.3.5.1.1.2.1.6" + oid_peer_remote_port = ".1.3.6.1.3.5.1.1.2.1.9" + oid_peer_err_code_recv = ".1.3.6.1.3.5.1.1.3.1.1" + oid_peer_err_sub_code_recv = ".1.3.6.1.3.5.1.1.3.1.2" + oid_peer_err_recv_text = ".1.3.6.1.3.5.1.1.3.1.4" + + nb_notif = len(output_list) + for nb in range(nb_notif): + if output_list[nb][0][0] != "{}".format(oid_notif_type): + return False + + if output_list[nb][0][1] == "{}".format(peer_notif_established): + logger.info("Established notification") + notif_type = "Estab" + + elif output_list[nb][0][1] == "{}".format(peer_notif_backward): + logger.info("Backward transition notification") + notif_type = "Backward" + else: + return False + + if notif_type != type_requested: + continue + + if output_list[nb][1][0] != "{}.1.{}".format(oid_peer_state, address): + continue + + if output_list[nb][2][0] != "{}.1.{}".format(oid_peer_local_port, address): + return False + + if output_list[nb][3][0] != "{}.1.{}".format(oid_peer_remote_port, address): + return False + + if notif_type == "Estab": + return True + + if output_list[nb][4][0] != "{}.1.{}".format( + oid_peer_err_code_recv, address + ): + return False + + if output_list[nb][5][0] != "{}.1.{}".format( + oid_peer_err_sub_code_recv, address + ): + return False + + if output_list[nb][6][0] != "{}.1.{}".format( + oid_peer_err_recv_text, address + ): + return False + + return True + + return False + + def get_notif_bgp4(self, output_file): + notif_list = [] + whitecleanfile = re.sub("\t", " ", output_file) results = whitecleanfile.strip().split("\n") - return self._parse_multiline_trap(results) + + # don't consider SNMP additional messages + notifs_first = [elem for elem in results if not ("SNMP" in elem)] + # don't consider additional application messages + notifs = [elem for index, elem in enumerate(notifs_first) if index % 2 != 0] + + oid_v4 = "1\.3\.6\.1\.2\.1\.15" + for one_notif in notifs: + is_ipv4_notif = re.search(oid_v4, one_notif) + if is_ipv4_notif != None: + formated_notif = self.parse_notif_ipv4(one_notif) + notif_list.append(formated_notif) + + return notif_list + + def get_notif_bgp4v2(self, output_file): + notif_list = [] + whitecleanfile = re.sub("\t", " ", output_file) + results = whitecleanfile.strip().split("\n") + + # don't consider SNMP additional messages + notifs_first = [elem for elem in results if not ("SNMP" in elem)] + # don't consider additional application messages + notifs = [elem for index, elem in enumerate(results) if index % 2 != 0] + + oid_v6 = "1\.3\.6\.1\.3\.5\.1" + for one_notif in notifs: + is_ipv6_notif = re.search(oid_v6, one_notif) + if is_ipv6_notif != None: + formated_notif = self.parse_notif_ipv4(one_notif) + notif_list.append(formated_notif) + + return notif_list def test_oid(self, oid, value): print("oid: {}".format(self.get_next(oid))) diff --git a/tests/topotests/mgmt_debug_flags/r1/frr.conf b/tests/topotests/mgmt_debug_flags/r1/frr.conf new file mode 100644 index 0000000000..ba95b8d493 --- /dev/null +++ b/tests/topotests/mgmt_debug_flags/r1/frr.conf @@ -0,0 +1,11 @@ +log timestamp precision 6 +log file frr.log + +! debug mgmt backend datastore frontend transaction +! debug mgmt client frontend +! debug mgmt client backend + +interface r1-eth0 + ip address 1.1.1.1/24 +exit +ip route 11.11.11.11/32 1.1.1.2
\ No newline at end of file diff --git a/tests/topotests/mgmt_debug_flags/test_debug.py b/tests/topotests/mgmt_debug_flags/test_debug.py new file mode 100644 index 0000000000..b0ab71e9bd --- /dev/null +++ b/tests/topotests/mgmt_debug_flags/test_debug.py @@ -0,0 +1,129 @@ +#!/usr/bin/env python +# -*- coding: utf-8 eval: (blacken-mode 1) -*- +# SPDX-License-Identifier: ISC +# +# Copyright (c) 2021, LabN Consulting, L.L.C. +# Copyright (c) 2019-2020 by +# Donatas Abraitis <donatas.abraitis@gmail.com> +# +# noqa: E501 +# +""" +Test static route functionality +""" +import pytest +from lib.common_config import step +from lib.topogen import Topogen +from munet.watchlog import WatchLog + +pytestmark = [pytest.mark.staticd] + + +@pytest.fixture(scope="module") +def tgen(request): + "Setup/Teardown the environment and provide tgen argument to tests" + + topodef = {"s1": ("r1",)} + tgen = Topogen(topodef, request.module.__name__) + tgen.start_topology() + + for rname, router in tgen.routers().items(): + router.load_frr_config("frr.conf") + + tgen.start_router() + yield tgen + tgen.stop_topology() + + +def test_client_debug_enable(tgen): + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + r1 = tgen.gears["r1"] + + # Start watching log files + watch_mgmtd_log = WatchLog(r1.net.rundir / "mgmtd.log") + watch_staticd_log = WatchLog(r1.net.rundir / "staticd.log") + + def __test_debug(r1, on): + watch_mgmtd_log.snapshot() + watch_staticd_log.snapshot() + + # Add ip route and remove look for debug. + r1.vtysh_cmd("conf t\nip route 11.11.11.11/32 1.1.1.2") + r1.vtysh_cmd("conf t\nno ip route 11.11.11.11/32 1.1.1.2") + + new_mgmt_logs = watch_mgmtd_log.snapshot() + new_be_logs = watch_staticd_log.snapshot() + + fe_cl_msg = "Sending SET_CONFIG_REQ" + fe_ad_msg = "Got SETCFG_REQ" + be_ad_msg = "Sending CFGDATA_CREATE_REQ" + be_cl_msg = "Got CFG_APPLY_REQ" + + if on: + assert fe_cl_msg in new_mgmt_logs + assert fe_ad_msg in new_mgmt_logs + assert be_ad_msg in new_mgmt_logs + assert be_cl_msg in new_be_logs + else: + assert fe_cl_msg not in new_mgmt_logs + assert fe_ad_msg not in new_mgmt_logs + assert be_ad_msg not in new_mgmt_logs + assert be_cl_msg not in new_be_logs + + step("test debug off") + __test_debug(r1, False) + + # Turn it on + step("tests debug on") + r1.vtysh_cmd("debug mgmt client frontend") + r1.vtysh_cmd("debug mgmt client backend") + r1.vtysh_cmd("debug mgmt backend frontend") + __test_debug(r1, True) + + # Turn it off + step("tests debug off") + r1.vtysh_cmd("no debug mgmt client frontend") + r1.vtysh_cmd("no debug mgmt client backend") + r1.vtysh_cmd("no debug mgmt backend frontend") + __test_debug(r1, False) + + # Configure it on + step("tests debug on") + r1.vtysh_cmd("conf t\ndebug mgmt client frontend") + r1.vtysh_cmd("conf t\ndebug mgmt client backend") + r1.vtysh_cmd("conf t\ndebug mgmt backend frontend") + __test_debug(r1, True) + + # Configure it off + step("tests debug off") + r1.vtysh_cmd("conf t\nno debug mgmt client frontend") + r1.vtysh_cmd("conf t\nno debug mgmt client backend") + r1.vtysh_cmd("conf t\nno debug mgmt backend frontend") + __test_debug(r1, False) + + # Turn it on + step("tests debug on") + r1.vtysh_cmd("debug mgmt client frontend") + r1.vtysh_cmd("debug mgmt client backend") + r1.vtysh_cmd("debug mgmt backend frontend") + __test_debug(r1, True) + # Configure it on + step("tests debug on") + r1.vtysh_cmd("conf t\ndebug mgmt client frontend") + r1.vtysh_cmd("conf t\ndebug mgmt client backend") + r1.vtysh_cmd("conf t\ndebug mgmt backend frontend") + __test_debug(r1, True) + # Turn it off + step("tests debug on") + r1.vtysh_cmd("no debug mgmt client frontend") + r1.vtysh_cmd("no debug mgmt client backend") + r1.vtysh_cmd("no debug mgmt backend frontend") + __test_debug(r1, True) + # Configure it off + step("tests debug off") + r1.vtysh_cmd("conf t\nno debug mgmt client frontend") + r1.vtysh_cmd("conf t\nno debug mgmt client backend") + r1.vtysh_cmd("conf t\nno debug mgmt backend frontend") + __test_debug(r1, False) diff --git a/tests/topotests/ospf6_topo1/r1/ospf6d.conf b/tests/topotests/ospf6_topo1/r1/ospf6d.conf index 5f1ceee964..d2693ec07d 100644 --- a/tests/topotests/ospf6_topo1/r1/ospf6d.conf +++ b/tests/topotests/ospf6_topo1/r1/ospf6d.conf @@ -10,11 +10,13 @@ log file ospf6d.log ! debug ospf6 flooding ! interface r1-stubnet + ipv6 ospf6 area 0.0.0.0 ipv6 ospf6 network broadcast ipv6 ospf6 hello-interval 2 ipv6 ospf6 dead-interval 10 ! interface r1-sw5 + ipv6 ospf6 area 0.0.0.0 ipv6 ospf6 network broadcast ipv6 ospf6 hello-interval 2 ipv6 ospf6 dead-interval 10 @@ -23,8 +25,6 @@ router ospf6 ospf6 router-id 10.0.0.1 log-adjacency-changes detail redistribute static - interface r1-stubnet area 0.0.0.0 - interface r1-sw5 area 0.0.0.0 ! line vty exec-timeout 0 0 diff --git a/tests/topotests/ospf6_topo1/r2/ospf6d.conf b/tests/topotests/ospf6_topo1/r2/ospf6d.conf index d51b41e1e5..c9e88f1545 100644 --- a/tests/topotests/ospf6_topo1/r2/ospf6d.conf +++ b/tests/topotests/ospf6_topo1/r2/ospf6d.conf @@ -10,11 +10,13 @@ log file ospf6d.log ! debug ospf6 flooding ! interface r2-stubnet + ipv6 ospf6 area 0.0.0.0 ipv6 ospf6 network broadcast ipv6 ospf6 hello-interval 2 ipv6 ospf6 dead-interval 10 ! interface r2-sw5 + ipv6 ospf6 area 0.0.0.0 ipv6 ospf6 network broadcast ipv6 ospf6 hello-interval 2 ipv6 ospf6 dead-interval 10 @@ -23,8 +25,6 @@ router ospf6 ospf6 router-id 10.0.0.2 log-adjacency-changes detail redistribute static - interface r2-stubnet area 0.0.0.0 - interface r2-sw5 area 0.0.0.0 ! line vty exec-timeout 0 0 diff --git a/tests/topotests/ospf6_topo1/r3/ospf6d.conf b/tests/topotests/ospf6_topo1/r3/ospf6d.conf index cad71ac067..e1c3e44d0e 100644 --- a/tests/topotests/ospf6_topo1/r3/ospf6d.conf +++ b/tests/topotests/ospf6_topo1/r3/ospf6d.conf @@ -10,16 +10,19 @@ log file ospf6d.log ! debug ospf6 flooding ! interface r3-stubnet + ipv6 ospf6 area 0.0.0.0 ipv6 ospf6 network broadcast ipv6 ospf6 hello-interval 2 ipv6 ospf6 dead-interval 10 ! interface r3-sw5 + ipv6 ospf6 area 0.0.0.0 ipv6 ospf6 network broadcast ipv6 ospf6 hello-interval 2 ipv6 ospf6 dead-interval 10 ! interface r3-sw6 + ipv6 ospf6 area 0.0.0.1 ipv6 ospf6 network broadcast ipv6 ospf6 hello-interval 2 ipv6 ospf6 dead-interval 10 @@ -28,9 +31,6 @@ router ospf6 ospf6 router-id 10.0.0.3 log-adjacency-changes detail redistribute static - interface r3-stubnet area 0.0.0.0 - interface r3-sw5 area 0.0.0.0 - interface r3-sw6 area 0.0.0.1 ! line vty exec-timeout 0 0 diff --git a/tests/topotests/ospf6_topo1/r4/ospf6d.conf b/tests/topotests/ospf6_topo1/r4/ospf6d.conf index f0b166bc4b..230ec7aad4 100644 --- a/tests/topotests/ospf6_topo1/r4/ospf6d.conf +++ b/tests/topotests/ospf6_topo1/r4/ospf6d.conf @@ -10,11 +10,13 @@ log file ospf6d.log ! debug ospf6 flooding ! interface r4-stubnet + ipv6 ospf6 area 0.0.0.1 ipv6 ospf6 network broadcast ipv6 ospf6 hello-interval 2 ipv6 ospf6 dead-interval 10 ! interface r4-sw6 + ipv6 ospf6 area 0.0.0.1 ipv6 ospf6 network broadcast ipv6 ospf6 hello-interval 2 ipv6 ospf6 dead-interval 10 @@ -23,8 +25,6 @@ router ospf6 ospf6 router-id 10.0.0.4 log-adjacency-changes detail redistribute static - interface r4-stubnet area 0.0.0.1 - interface r4-sw6 area 0.0.0.1 ! line vty exec-timeout 0 0 diff --git a/tests/topotests/ospf_topo1/r1/ospf6d.conf b/tests/topotests/ospf_topo1/r1/ospf6d.conf index ca3497b4a5..0e6c7dadfb 100644 --- a/tests/topotests/ospf_topo1/r1/ospf6d.conf +++ b/tests/topotests/ospf_topo1/r1/ospf6d.conf @@ -4,10 +4,12 @@ router ospf6 redistribute kernel redistribute connected redistribute static - interface r1-eth0 area 0.0.0.0 - interface r1-eth1 area 0.0.0.0 +! +interface r1-eth0 + ipv6 ospf6 area 0.0.0.0 ! int r1-eth1 + ipv6 ospf6 area 0.0.0.0 ipv6 ospf6 dead-interval 10 ipv6 ospf6 hello-interval 2 ! diff --git a/tests/topotests/ospf_topo1/r2/ospf6d.conf b/tests/topotests/ospf_topo1/r2/ospf6d.conf index 44047e1a4e..f6a1f50530 100644 --- a/tests/topotests/ospf_topo1/r2/ospf6d.conf +++ b/tests/topotests/ospf_topo1/r2/ospf6d.conf @@ -4,14 +4,14 @@ router ospf6 redistribute kernel redistribute connected redistribute static - interface r2-eth0 area 0.0.0.0 - interface r2-eth1 area 0.0.0.0 ! int r2-eth0 + ipv6 ospf6 area 0.0.0.0 ipv6 ospf6 hello-interval 2 ipv6 ospf6 dead-interval 10 ! int r2-eth1 + ipv6 ospf6 area 0.0.0.0 ipv6 ospf6 hello-interval 2 ipv6 ospf6 dead-interval 10 ! diff --git a/tests/topotests/ospf_topo1/r3/ospf6d.conf b/tests/topotests/ospf_topo1/r3/ospf6d.conf index 13ad9a7356..278a016968 100644 --- a/tests/topotests/ospf_topo1/r3/ospf6d.conf +++ b/tests/topotests/ospf_topo1/r3/ospf6d.conf @@ -4,19 +4,19 @@ router ospf6 redistribute kernel redistribute connected redistribute static - interface r3-eth0 area 0.0.0.0 - interface r3-eth1 area 0.0.0.0 - interface r3-eth2 area 0.0.0.1 ! int r3-eth0 + ipv6 ospf6 area 0.0.0.0 ipv6 ospf6 hello-interval 2 ipv6 ospf6 dead-interval 10 ! int r3-eth1 + ipv6 ospf6 area 0.0.0.0 ipv6 ospf6 hello-interval 2 ipv6 ospf6 dead-interval 10 ! int r3-eth2 + ipv6 ospf6 area 0.0.0.1 ipv6 ospf6 hello-interval 2 ipv6 ospf6 dead-interval 10 ! diff --git a/tests/topotests/ospf_topo1/r4/ospf6d.conf b/tests/topotests/ospf_topo1/r4/ospf6d.conf index f9bde0e83c..777dd0b7b7 100644 --- a/tests/topotests/ospf_topo1/r4/ospf6d.conf +++ b/tests/topotests/ospf_topo1/r4/ospf6d.conf @@ -4,14 +4,14 @@ router ospf6 redistribute kernel redistribute connected redistribute static - interface r4-eth0 area 0.0.0.1 - interface r4-eth1 area 0.0.0.1 ! int r4-eth0 + ipv6 ospf6 area 0.0.0.1 ipv6 ospf6 hello-interval 2 ipv6 ospf6 dead-interval 10 ! int r4-eth1 + ipv6 ospf6 area 0.0.0.1 ipv6 ospf6 hello-interval 2 ipv6 ospf6 dead-interval 10 ! diff --git a/tests/topotests/zebra_multiple_connected/test_zebra_multiple_connected.py b/tests/topotests/zebra_multiple_connected/test_zebra_multiple_connected.py index 529520cd9e..0b2937c12a 100644 --- a/tests/topotests/zebra_multiple_connected/test_zebra_multiple_connected.py +++ b/tests/topotests/zebra_multiple_connected/test_zebra_multiple_connected.py @@ -144,6 +144,23 @@ def test_zebra_system_recursion(): assert result is None, "Kernel route is missing from zebra" +def test_zebra_noprefix_connected(): + "Test that a noprefixroute created does not create a connected route" + + tgen = get_topogen() + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + router = tgen.gears["r1"] + router.run("ip addr add 192.168.44.1/24 dev r1-eth1 noprefixroute") + expected = "% Network not in table" + test_func = partial( + topotest.router_output_cmp, router, "show ip route 192.168.44.0/24", expected + ) + result, diff = topotest.run_and_expect(test_func, "", count=20, wait=1) + assert result, "Connected Route should not have been added" + + if __name__ == "__main__": args = ["-s"] + sys.argv[1:] sys.exit(pytest.main(args)) diff --git a/zebra/connected.c b/zebra/connected.c index 297234b6af..404f892f6e 100644 --- a/zebra/connected.c +++ b/zebra/connected.c @@ -282,13 +282,15 @@ void connected_up(struct interface *ifp, struct connected *ifc) return; } - rib_add(afi, SAFI_UNICAST, zvrf->vrf->vrf_id, ZEBRA_ROUTE_CONNECT, 0, - flags, &p, NULL, &nh, 0, zvrf->table_id, metric, 0, 0, 0, - false); + if (!CHECK_FLAG(ifc->flags, ZEBRA_IFA_NOPREFIXROUTE)) { + rib_add(afi, SAFI_UNICAST, zvrf->vrf->vrf_id, + ZEBRA_ROUTE_CONNECT, 0, flags, &p, NULL, &nh, 0, + zvrf->table_id, metric, 0, 0, 0, false); - rib_add(afi, SAFI_MULTICAST, zvrf->vrf->vrf_id, ZEBRA_ROUTE_CONNECT, 0, - flags, &p, NULL, &nh, 0, zvrf->table_id, metric, 0, 0, 0, - false); + rib_add(afi, SAFI_MULTICAST, zvrf->vrf->vrf_id, + ZEBRA_ROUTE_CONNECT, 0, flags, &p, NULL, &nh, 0, + zvrf->table_id, metric, 0, 0, 0, false); + } if (install_local) { rib_add(afi, SAFI_UNICAST, zvrf->vrf->vrf_id, ZEBRA_ROUTE_LOCAL, @@ -481,11 +483,15 @@ void connected_down(struct interface *ifp, struct connected *ifc) * Same logic as for connected_up(): push the changes into the * head. */ - rib_delete(afi, SAFI_UNICAST, zvrf->vrf->vrf_id, ZEBRA_ROUTE_CONNECT, 0, - 0, &p, NULL, &nh, 0, zvrf->table_id, 0, 0, false); + if (!CHECK_FLAG(ifc->flags, ZEBRA_IFA_NOPREFIXROUTE)) { + rib_delete(afi, SAFI_UNICAST, zvrf->vrf->vrf_id, + ZEBRA_ROUTE_CONNECT, 0, 0, &p, NULL, &nh, 0, + zvrf->table_id, 0, 0, false); - rib_delete(afi, SAFI_MULTICAST, zvrf->vrf->vrf_id, ZEBRA_ROUTE_CONNECT, - 0, 0, &p, NULL, &nh, 0, zvrf->table_id, 0, 0, false); + rib_delete(afi, SAFI_MULTICAST, zvrf->vrf->vrf_id, + ZEBRA_ROUTE_CONNECT, 0, 0, &p, NULL, &nh, 0, + zvrf->table_id, 0, 0, false); + } if (remove_local) { rib_delete(afi, SAFI_UNICAST, zvrf->vrf->vrf_id, diff --git a/zebra/if_netlink.c b/zebra/if_netlink.c index 2cedb29960..551ef6533e 100644 --- a/zebra/if_netlink.c +++ b/zebra/if_netlink.c @@ -1423,6 +1423,9 @@ int netlink_interface_addr_dplane(struct nlmsghdr *h, ns_id_t ns_id, if (kernel_flags & IFA_F_SECONDARY) dplane_ctx_intf_set_secondary(ctx); + if (kernel_flags & IFA_F_NOPREFIXROUTE) + dplane_ctx_intf_set_noprefixroute(ctx); + /* Label */ if (tb[IFA_LABEL]) { label = (char *)RTA_DATA(tb[IFA_LABEL]); diff --git a/zebra/interface.c b/zebra/interface.c index c4a952e1a7..39d24f1883 100644 --- a/zebra/interface.c +++ b/zebra/interface.c @@ -1317,6 +1317,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); @@ -2335,6 +2338,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)); diff --git a/zebra/rib.h b/zebra/rib.h index 7ce6fbe609..61d9953d81 100644 --- a/zebra/rib.h +++ b/zebra/rib.h @@ -430,6 +430,7 @@ extern int rib_queue_nhg_ctx_add(struct nhg_ctx *ctx); /* Enqueue incoming nhg from proto daemon for processing */ extern int rib_queue_nhe_add(struct nhg_hash_entry *nhe); +extern int rib_queue_nhe_del(struct nhg_hash_entry *nhe); /* Enqueue evpn route for processing */ int zebra_rib_queue_evpn_route_add(vrf_id_t vrf_id, const struct ethaddr *rmac, diff --git a/zebra/zapi_msg.c b/zebra/zapi_msg.c index 2d1614ca54..761eafeb13 100644 --- a/zebra/zapi_msg.c +++ b/zebra/zapi_msg.c @@ -1959,20 +1959,19 @@ static void zread_nhg_del(ZAPI_HANDLER_ARGS) return; } - /* - * Delete the received nhg id - */ - nhe = zebra_nhg_proto_del(api_nhg.id, api_nhg.proto); + /* Create a temporary nhe */ + nhe = zebra_nhg_alloc(); + nhe->id = api_nhg.id; + nhe->type = api_nhg.proto; + nhe->zapi_instance = client->instance; + nhe->zapi_session = client->session_id; + + /* Sanity check - Empty nexthop and group */ + nhe->nhg.nexthop = NULL; + + /* Enqueue to workqueue for processing */ + rib_queue_nhe_del(nhe); - if (nhe) { - zebra_nhg_decrement_ref(nhe); - zsend_nhg_notify(api_nhg.proto, client->instance, - client->session_id, api_nhg.id, - ZAPI_NHG_REMOVED); - } else - zsend_nhg_notify(api_nhg.proto, client->instance, - client->session_id, api_nhg.id, - ZAPI_NHG_REMOVE_FAIL); /* Stats */ client->nhg_del_cnt++; } diff --git a/zebra/zebra_dplane.c b/zebra/zebra_dplane.c index 28319c5bdf..369394e845 100644 --- a/zebra/zebra_dplane.c +++ b/zebra/zebra_dplane.c @@ -230,6 +230,7 @@ struct dplane_intf_info { #define DPLANE_INTF_BROADCAST (1 << 2) #define DPLANE_INTF_HAS_DEST DPLANE_INTF_CONNECTED #define DPLANE_INTF_HAS_LABEL (1 << 4) +#define DPLANE_INTF_NOPREFIXROUTE (1 << 5) /* Interface address/prefix */ struct prefix prefix; @@ -2541,6 +2542,13 @@ bool dplane_ctx_intf_is_connected(const struct zebra_dplane_ctx *ctx) return (ctx->u.intf.flags & DPLANE_INTF_CONNECTED); } +bool dplane_ctx_intf_is_noprefixroute(const struct zebra_dplane_ctx *ctx) +{ + DPLANE_CTX_VALID(ctx); + + return (ctx->u.intf.flags & DPLANE_INTF_NOPREFIXROUTE); +} + bool dplane_ctx_intf_is_secondary(const struct zebra_dplane_ctx *ctx) { DPLANE_CTX_VALID(ctx); @@ -2569,6 +2577,13 @@ void dplane_ctx_intf_set_secondary(struct zebra_dplane_ctx *ctx) ctx->u.intf.flags |= DPLANE_INTF_SECONDARY; } +void dplane_ctx_intf_set_noprefixroute(struct zebra_dplane_ctx *ctx) +{ + DPLANE_CTX_VALID(ctx); + + ctx->u.intf.flags |= DPLANE_INTF_NOPREFIXROUTE; +} + void dplane_ctx_intf_set_broadcast(struct zebra_dplane_ctx *ctx) { DPLANE_CTX_VALID(ctx); diff --git a/zebra/zebra_dplane.h b/zebra/zebra_dplane.h index 87c2e03656..6dc52ead14 100644 --- a/zebra/zebra_dplane.h +++ b/zebra/zebra_dplane.h @@ -658,6 +658,8 @@ bool dplane_ctx_intf_is_connected(const struct zebra_dplane_ctx *ctx); void dplane_ctx_intf_set_connected(struct zebra_dplane_ctx *ctx); bool dplane_ctx_intf_is_secondary(const struct zebra_dplane_ctx *ctx); void dplane_ctx_intf_set_secondary(struct zebra_dplane_ctx *ctx); +bool dplane_ctx_intf_is_noprefixroute(const struct zebra_dplane_ctx *ctx); +void dplane_ctx_intf_set_noprefixroute(struct zebra_dplane_ctx *ctx); bool dplane_ctx_intf_is_broadcast(const struct zebra_dplane_ctx *ctx); void dplane_ctx_intf_set_broadcast(struct zebra_dplane_ctx *ctx); const struct prefix *dplane_ctx_get_intf_addr( diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c index af94adf05a..980fced8a7 100644 --- a/zebra/zebra_rib.c +++ b/zebra/zebra_rib.c @@ -186,6 +186,7 @@ struct wq_nhg_wrapper { struct nhg_ctx *ctx; struct nhg_hash_entry *nhe; } u; + bool deletion; }; #define WQ_NHG_WRAPPER_TYPE_CTX 0x01 @@ -339,7 +340,7 @@ static char *_dump_re_status(const struct route_entry *re, char *buf, : "", CHECK_FLAG(re->status, ROUTE_ENTRY_QUEUED) ? "Queued " : "", CHECK_FLAG(re->status, ROUTE_ENTRY_ROUTE_REPLACING) - ? "Replacing" + ? "Replacing " : "", CHECK_FLAG(re->status, ROUTE_ENTRY_INSTALLED) ? "Installed " : "", @@ -1233,6 +1234,7 @@ static void rib_process(struct route_node *rn) rib_dest_t *dest; struct zebra_vrf *zvrf = NULL; struct vrf *vrf; + struct route_entry *proto_re_changed = NULL; vrf_id_t vrf_id = VRF_UNKNOWN; @@ -1302,6 +1304,7 @@ static void rib_process(struct route_node *rn) * skip it. */ if (CHECK_FLAG(re->status, ROUTE_ENTRY_CHANGED)) { + proto_re_changed = re; if (!nexthop_active_update(rn, re)) { const struct prefix *p; struct rib_table_info *info; @@ -1387,6 +1390,8 @@ static void rib_process(struct route_node *rn) * new_selected --- RE entry that is newly SELECTED * old_fib --- RE entry currently in kernel FIB * new_fib --- RE entry that is newly to be in kernel FIB + * proto_re_changed -- RE that is the last changed entry in the + * list of RE's. * * new_selected will get SELECTED flag, and is going to be redistributed * the zclients. new_fib (which can be new_selected) will be installed @@ -1441,6 +1446,22 @@ static void rib_process(struct route_node *rn) } } + /* + * If zebra has a new_selected and a proto_re_changed + * entry that was not the old selected and the protocol + * is different, zebra should notify the upper level + * protocol that the sent down entry was not selected + */ + if (new_selected && proto_re_changed && + proto_re_changed != old_selected && + new_selected->type != proto_re_changed->type) { + struct rib_table_info *info = srcdest_rnode_table_info(rn); + + zsend_route_notify_owner(rn, proto_re_changed, + ZAPI_ROUTE_BETTER_ADMIN_WON, info->afi, + info->safi); + } + /* Update fib according to selection results */ if (new_fib && old_fib) rib_process_update_fib(zvrf, rn, old_fib, new_fib); @@ -2511,7 +2532,7 @@ static void process_subq_evpn(struct listnode *lnode) static void process_subq_nhg(struct listnode *lnode) { struct nhg_ctx *ctx; - struct nhg_hash_entry *nhe, *newnhe; + struct nhg_hash_entry *nhe, *newnhe, *oldnhe; struct wq_nhg_wrapper *w; uint8_t qindex = META_QUEUE_NHG; @@ -2543,15 +2564,33 @@ static void process_subq_nhg(struct listnode *lnode) subqueue2str(qindex)); /* Process incoming nhg update, probably from a proto daemon */ - newnhe = zebra_nhg_proto_add(nhe->id, nhe->type, - nhe->zapi_instance, - nhe->zapi_session, &nhe->nhg, 0); + if (w->deletion) { + /* + * Delete the received nhg id + */ + oldnhe = zebra_nhg_proto_del(nhe->id, nhe->type); + if (oldnhe) { + zsend_nhg_notify(nhe->type, nhe->zapi_instance, + nhe->zapi_session, nhe->id, + ZAPI_NHG_REMOVED); + zebra_nhg_decrement_ref(oldnhe); + } else + zsend_nhg_notify(nhe->type, nhe->zapi_instance, + nhe->zapi_session, nhe->id, + ZAPI_NHG_REMOVE_FAIL); - /* Report error to daemon via ZAPI */ - if (newnhe == NULL) - zsend_nhg_notify(nhe->type, nhe->zapi_instance, - nhe->zapi_session, nhe->id, - ZAPI_NHG_FAIL_INSTALL); + } else { + newnhe = zebra_nhg_proto_add(nhe->id, nhe->type, + nhe->zapi_instance, + nhe->zapi_session, + &nhe->nhg, 0); + + /* Report error to daemon via ZAPI */ + if (newnhe == NULL) + zsend_nhg_notify(nhe->type, nhe->zapi_instance, + nhe->zapi_session, nhe->id, + ZAPI_NHG_FAIL_INSTALL); + } /* Free temp nhe - we own that memory. */ zebra_nhg_free(nhe); @@ -3319,7 +3358,8 @@ static int rib_meta_queue_nhg_ctx_add(struct meta_queue *mq, void *data) return 0; } -static int rib_meta_queue_nhg_add(struct meta_queue *mq, void *data) +static int rib_meta_queue_nhg_process(struct meta_queue *mq, void *data, + bool deletion) { struct nhg_hash_entry *nhe = NULL; uint8_t qindex = META_QUEUE_NHG; @@ -3334,6 +3374,7 @@ static int rib_meta_queue_nhg_add(struct meta_queue *mq, void *data) w->type = WQ_NHG_WRAPPER_TYPE_NHG; w->u.nhe = nhe; + w->deletion = deletion; listnode_add(mq->subq[qindex], w); mq->size++; @@ -3345,6 +3386,16 @@ static int rib_meta_queue_nhg_add(struct meta_queue *mq, void *data) return 0; } +static int rib_meta_queue_nhg_add(struct meta_queue *mq, void *data) +{ + return rib_meta_queue_nhg_process(mq, data, false); +} + +static int rib_meta_queue_nhg_del(struct meta_queue *mq, void *data) +{ + return rib_meta_queue_nhg_process(mq, data, true); +} + static int rib_meta_queue_evpn_add(struct meta_queue *mq, void *data) { listnode_add(mq->subq[META_QUEUE_EVPN], data); @@ -3453,6 +3504,17 @@ int rib_queue_nhe_add(struct nhg_hash_entry *nhe) } /* + * Enqueue incoming nhg from proto daemon for processing + */ +int rib_queue_nhe_del(struct nhg_hash_entry *nhe) +{ + if (nhe == NULL) + return -1; + + return mq_add_handler(nhe, rib_meta_queue_nhg_del); +} + +/* * Enqueue evpn route for processing */ int zebra_rib_queue_evpn_route_add(vrf_id_t vrf_id, const struct ethaddr *rmac, |
