diff options
73 files changed, 1017 insertions, 652 deletions
diff --git a/babeld/babel_zebra.c b/babeld/babel_zebra.c index 8dea1431e2..e909f8ea7a 100644 --- a/babeld/babel_zebra.c +++ b/babeld/babel_zebra.c @@ -237,7 +237,7 @@ babel_zebra_connected (struct zclient *zclient) void babelz_zebra_init(void) { - zclient = zclient_new_notify(master, &zclient_options_default); + zclient = zclient_new(master, &zclient_options_default); zclient_init(zclient, ZEBRA_ROUTE_BABEL, 0, &babeld_privs); zclient->zebra_connected = babel_zebra_connected; diff --git a/bfdd/ptm_adapter.c b/bfdd/ptm_adapter.c index a5fae3383c..f9c7c16fb1 100644 --- a/bfdd/ptm_adapter.c +++ b/bfdd/ptm_adapter.c @@ -381,6 +381,21 @@ static int _ptm_msg_read(struct stream *msg, int command, if (bpc->bpc_has_localif) { STREAM_GET(bpc->bpc_localif, msg, ifnamelen); bpc->bpc_localif[ifnamelen] = 0; + + /* + * IPv6 link-local addresses must use scope id, + * otherwise the session lookup will always fail + * and we'll have multiple sessions showing up. + * + * This problem only happens with single hop + * since it is not possible to have link-local + * address for multi hop sessions. + */ + if (bpc->bpc_ipv4 == false + && IN6_IS_ADDR_LINKLOCAL( + &bpc->bpc_peer.sa_sin6.sin6_addr)) + bpc->bpc_peer.sa_sin6.sin6_scope_id = + ptm_bfd_fetch_ifindex(bpc->bpc_localif); } } @@ -566,7 +581,7 @@ static void bfdd_zebra_connected(struct zclient *zc) void bfdd_zclient_init(struct zebra_privs_t *bfdd_priv) { - zclient = zclient_new_notify(master, &zclient_options_default); + zclient = zclient_new(master, &zclient_options_default); assert(zclient != NULL); zclient_init(zclient, ZEBRA_ROUTE_BFD, 0, bfdd_priv); diff --git a/bgpd/bgp_evpn.c b/bgpd/bgp_evpn.c index c91a2ab6bd..cff050a9ef 100644 --- a/bgpd/bgp_evpn.c +++ b/bgpd/bgp_evpn.c @@ -1693,6 +1693,58 @@ static int update_evpn_route_entry(struct bgp *bgp, struct bgpevpn *vpn, } /* + * If the local route was not selected evict it and tell zebra to re-add + * the best remote dest. + * + * Typically a local path added by zebra is expected to be selected as + * best. In which case when a remote path wins as best (later) + * evpn_route_select_install itself evicts the older-local-best path. + * + * However if bgp's add and zebra's add cross paths (race condition) it + * is possible that the local path is no longer the "older" best path. + * It is a path that was never designated as best and hence requires + * additional handling to prevent bgp from injecting and holding on to a + * non-best local path. + */ +static void evpn_cleanup_local_non_best_route(struct bgp *bgp, + struct bgpevpn *vpn, + struct bgp_node *rn, + struct bgp_path_info *local_pi) +{ + struct bgp_path_info *tmp_pi; + struct bgp_path_info *curr_select = NULL; + uint8_t flags = 0; + char buf[PREFIX_STRLEN]; + + /* local path was not picked as the winner; kick it out */ + if (bgp_debug_zebra(NULL)) { + zlog_debug("evicting local evpn prefix %s as remote won", + prefix2str(&rn->p, buf, sizeof(buf))); + } + evpn_delete_old_local_route(bgp, vpn, rn, local_pi); + bgp_path_info_reap(rn, local_pi); + + /* tell zebra to re-add the best remote path */ + for (tmp_pi = rn->info; tmp_pi; tmp_pi = tmp_pi->next) { + if (CHECK_FLAG(tmp_pi->flags, BGP_PATH_SELECTED)) { + curr_select = tmp_pi; + break; + } + } + if (curr_select && + curr_select->type == ZEBRA_ROUTE_BGP + && curr_select->sub_type == BGP_ROUTE_IMPORTED) { + if (curr_select->attr->sticky) + SET_FLAG(flags, ZEBRA_MACIP_TYPE_STICKY); + if (curr_select->attr->default_gw) + SET_FLAG(flags, ZEBRA_MACIP_TYPE_GW); + evpn_zebra_install(bgp, vpn, (struct prefix_evpn *)&rn->p, + curr_select->attr->nexthop, flags, + mac_mobility_seqnum(curr_select->attr)); + } +} + +/* * Create or update EVPN route (of type based on prefix) for specified VNI * and schedule for processing. */ @@ -1754,10 +1806,23 @@ static int update_evpn_route(struct bgp *bgp, struct bgpevpn *vpn, assert(pi); attr_new = pi->attr; + /* lock ri to prevent freeing in evpn_route_select_install */ + bgp_path_info_lock(pi); /* Perform route selection; this is just to set the flags correctly * as local route in the VNI always wins. */ evpn_route_select_install(bgp, vpn, rn); + /* + * If the new local route was not selected evict it and tell zebra + * to re-add the best remote dest. BGP doesn't retain non-best local + * routes. + */ + if (!CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) { + route_change = 0; + evpn_cleanup_local_non_best_route(bgp, vpn, rn, pi); + } + bgp_path_info_unlock(pi); + bgp_unlock_node(rn); /* If this is a new route or some attribute has changed, export the @@ -1928,8 +1993,10 @@ static int delete_evpn_route(struct bgp *bgp, struct bgpevpn *vpn, /* Delete route entry in the VNI route table. This can just be removed. */ delete_evpn_route_entry(bgp, afi, safi, rn, &pi); - if (pi) + if (pi) { bgp_path_info_reap(rn, pi); + evpn_route_select_install(bgp, vpn, rn); + } bgp_unlock_node(rn); return 0; diff --git a/bgpd/bgp_evpn_vty.c b/bgpd/bgp_evpn_vty.c index 29f9f64cca..aa5eabeade 100644 --- a/bgpd/bgp_evpn_vty.c +++ b/bgpd/bgp_evpn_vty.c @@ -3195,7 +3195,7 @@ DEFUN (no_bgp_evpn_advertise_type5, */ DEFUN(show_bgp_l2vpn_evpn_vni, show_bgp_l2vpn_evpn_vni_cmd, - "show bgp l2vpn evpn vni [(1-16777215)] [json]", + "show bgp l2vpn evpn vni [" CMD_VNI_RANGE "] [json]", SHOW_STR BGP_STR L2VPN_HELP_STR @@ -3623,7 +3623,7 @@ DEFUN(show_bgp_l2vpn_evpn_route_esi, * Display per-VNI EVPN routing table. */ DEFUN(show_bgp_l2vpn_evpn_route_vni, show_bgp_l2vpn_evpn_route_vni_cmd, - "show bgp l2vpn evpn route vni (1-16777215) [<type <macip|multicast> | vtep A.B.C.D>] [json]", + "show bgp l2vpn evpn route vni " CMD_VNI_RANGE " [<type <macip|multicast> | vtep A.B.C.D>] [json]", SHOW_STR BGP_STR L2VPN_HELP_STR @@ -3696,7 +3696,7 @@ DEFUN(show_bgp_l2vpn_evpn_route_vni, show_bgp_l2vpn_evpn_route_vni_cmd, */ DEFUN(show_bgp_l2vpn_evpn_route_vni_macip, show_bgp_l2vpn_evpn_route_vni_macip_cmd, - "show bgp l2vpn evpn route vni (1-16777215) mac WORD [ip WORD] [json]", + "show bgp l2vpn evpn route vni " CMD_VNI_RANGE " mac WORD [ip WORD] [json]", SHOW_STR BGP_STR L2VPN_HELP_STR @@ -3766,7 +3766,7 @@ DEFUN(show_bgp_l2vpn_evpn_route_vni_macip, */ DEFUN(show_bgp_l2vpn_evpn_route_vni_multicast, show_bgp_l2vpn_evpn_route_vni_multicast_cmd, - "show bgp l2vpn evpn route vni (1-16777215) multicast A.B.C.D [json]", + "show bgp l2vpn evpn route vni " CMD_VNI_RANGE " multicast A.B.C.D [json]", SHOW_STR BGP_STR L2VPN_HELP_STR @@ -4019,7 +4019,7 @@ DEFUN(test_withdraw_evpn_type4_route, } ALIAS_HIDDEN(show_bgp_l2vpn_evpn_vni, show_bgp_evpn_vni_cmd, - "show bgp evpn vni [(1-16777215)]", SHOW_STR BGP_STR EVPN_HELP_STR + "show bgp evpn vni [" CMD_VNI_RANGE "]", SHOW_STR BGP_STR EVPN_HELP_STR "Show VNI\n" "VNI number\n") @@ -4060,7 +4060,7 @@ ALIAS_HIDDEN( ALIAS_HIDDEN( show_bgp_l2vpn_evpn_route_vni, show_bgp_evpn_route_vni_cmd, - "show bgp evpn route vni (1-16777215) [<type <macip|multicast> | vtep A.B.C.D>]", + "show bgp evpn route vni " CMD_VNI_RANGE " [<type <macip|multicast> | vtep A.B.C.D>]", SHOW_STR BGP_STR EVPN_HELP_STR "EVPN route information\n" "VXLAN Network Identifier\n" @@ -4073,7 +4073,7 @@ ALIAS_HIDDEN( ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_macip, show_bgp_evpn_route_vni_macip_cmd, - "show bgp evpn route vni (1-16777215) mac WORD [ip WORD]", + "show bgp evpn route vni " CMD_VNI_RANGE " mac WORD [ip WORD]", SHOW_STR BGP_STR EVPN_HELP_STR "EVPN route information\n" "VXLAN Network Identifier\n" @@ -4085,7 +4085,7 @@ ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_macip, ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_multicast, show_bgp_evpn_route_vni_multicast_cmd, - "show bgp evpn route vni (1-16777215) multicast A.B.C.D", + "show bgp evpn route vni " CMD_VNI_RANGE " multicast A.B.C.D", SHOW_STR BGP_STR EVPN_HELP_STR "EVPN route information\n" "VXLAN Network Identifier\n" @@ -4108,7 +4108,7 @@ ALIAS_HIDDEN(show_bgp_l2vpn_evpn_import_rt, show_bgp_evpn_import_rt_cmd, DEFUN_NOSH (bgp_evpn_vni, bgp_evpn_vni_cmd, - "vni (1-16777215)", + "vni " CMD_VNI_RANGE, "VXLAN Network Identifier\n" "VNI number\n") { @@ -4134,7 +4134,7 @@ DEFUN_NOSH (bgp_evpn_vni, DEFUN (no_bgp_evpn_vni, no_bgp_evpn_vni_cmd, - "no vni (1-16777215)", + "no vni " CMD_VNI_RANGE, NO_STR "VXLAN Network Identifier\n" "VNI number\n") diff --git a/bgpd/bgp_fsm.c b/bgpd/bgp_fsm.c index 8aa35eddfc..1f0cfd6e25 100644 --- a/bgpd/bgp_fsm.c +++ b/bgpd/bgp_fsm.c @@ -1043,8 +1043,9 @@ int bgp_stop(struct peer *peer) "%%ADJCHANGE: neighbor %s(%s) in vrf %s Down %s", peer->host, (peer->hostname) ? peer->hostname : "Unknown", - vrf ? ((vrf->vrf_id != VRF_DEFAULT) ? vrf->name - : "Default") + vrf ? ((vrf->vrf_id != VRF_DEFAULT) + ? vrf->name + : VRF_DEFAULT_NAME) : "", peer_down_str[(int)peer->last_reset]); } @@ -1564,8 +1565,9 @@ static int bgp_establish(struct peer *peer) zlog_info("%%ADJCHANGE: neighbor %s(%s) in vrf %s Up", peer->host, (peer->hostname) ? peer->hostname : "Unknown", - vrf ? ((vrf->vrf_id != VRF_DEFAULT) ? vrf->name - : "Default") + vrf ? ((vrf->vrf_id != VRF_DEFAULT) + ? vrf->name + : VRF_DEFAULT_NAME) : ""); } /* assign update-group/subgroup */ diff --git a/bgpd/bgp_mplsvpn.c b/bgpd/bgp_mplsvpn.c index 385716970b..d4204126e1 100644 --- a/bgpd/bgp_mplsvpn.c +++ b/bgpd/bgp_mplsvpn.c @@ -1492,7 +1492,7 @@ void vrf_import_from_vrf(struct bgp *to_bgp, struct bgp *from_bgp, struct ecommunity *ecom; bool first_export = false; - export_name = to_bgp->name ? to_bgp->name : BGP_DEFAULT_NAME; + export_name = to_bgp->name ? to_bgp->name : VRF_DEFAULT_NAME; idir = BGP_VPN_POLICY_DIR_FROMVPN; edir = BGP_VPN_POLICY_DIR_TOVPN; @@ -1501,7 +1501,7 @@ void vrf_import_from_vrf(struct bgp *to_bgp, struct bgp *from_bgp, * any VRF is importing from "import_vrf". */ vname = (from_bgp->name ? XSTRDUP(MTYPE_TMP, from_bgp->name) - : XSTRDUP(MTYPE_TMP, BGP_DEFAULT_NAME)); + : XSTRDUP(MTYPE_TMP, VRF_DEFAULT_NAME)); listnode_add(to_bgp->vpn_policy[afi].import_vrf, vname); @@ -1557,8 +1557,8 @@ void vrf_unimport_from_vrf(struct bgp *to_bgp, struct bgp *from_bgp, struct ecommunity *ecom; struct listnode *node; - export_name = to_bgp->name ? to_bgp->name : BGP_DEFAULT_NAME; - tmp_name = from_bgp->name ? from_bgp->name : BGP_DEFAULT_NAME; + export_name = to_bgp->name ? to_bgp->name : VRF_DEFAULT_NAME; + tmp_name = from_bgp->name ? from_bgp->name : VRF_DEFAULT_NAME; idir = BGP_VPN_POLICY_DIR_FROMVPN; edir = BGP_VPN_POLICY_DIR_TOVPN; diff --git a/bgpd/bgp_nexthop.c b/bgpd/bgp_nexthop.c index 2ef792e129..1cb7e4c5e1 100644 --- a/bgpd/bgp_nexthop.c +++ b/bgpd/bgp_nexthop.c @@ -666,7 +666,7 @@ static void bgp_show_all_instances_nexthops_vty(struct vty *vty) for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) { vty_out(vty, "\nInstance %s:\n", (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) - ? "Default" + ? VRF_DEFAULT_NAME : bgp->name); bgp_show_nexthops(vty, bgp, 0); } diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index a407ffba41..8ae74a008c 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -453,6 +453,7 @@ static int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new, char exist_buf[PATH_ADDPATH_STR_BUFFER]; uint32_t new_mm_seq; uint32_t exist_mm_seq; + int nh_cmp; *paths_eq = 0; @@ -545,6 +546,28 @@ static int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new, exist_mm_seq); return 0; } + + /* + * if sequence numbers are the same path with the lowest IP + * wins + */ + nh_cmp = bgp_path_info_nexthop_cmp(new, exist); + if (nh_cmp < 0) { + if (debug) + zlog_debug( + "%s: %s wins over %s due to same MM seq %u and lower IP %s", + pfx_buf, new_buf, exist_buf, new_mm_seq, + inet_ntoa(new->attr->nexthop)); + return 1; + } + if (nh_cmp > 0) { + if (debug) + zlog_debug( + "%s: %s loses to %s due to same MM seq %u and higher IP %s", + pfx_buf, new_buf, exist_buf, new_mm_seq, + inet_ntoa(new->attr->nexthop)); + return 0; + } } /* 1. Weight check. */ @@ -8365,8 +8388,9 @@ static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi, "{\n \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64 ",\n \"routerId\": \"%s\",\n \"routes\": { ", bgp->vrf_id == VRF_UNKNOWN ? -1 : (int)bgp->vrf_id, - bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT ? "Default" - : bgp->name, + bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT + ? VRF_DEFAULT_NAME + : bgp->name, table->version, inet_ntoa(bgp->router_id)); *json_header_depth = 2; if (rd) { @@ -8742,12 +8766,12 @@ static void bgp_show_all_instances_routes_vty(struct vty *vty, afi_t afi, vty_out(vty, "\"%s\":", (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) - ? "Default" + ? VRF_DEFAULT_NAME : bgp->name); } else { vty_out(vty, "\nInstance %s:\n", (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) - ? "Default" + ? VRF_DEFAULT_NAME : bgp->name); } bgp_show(vty, bgp, afi, safi, bgp_show_type_normal, NULL, @@ -8882,7 +8906,7 @@ void route_vty_out_detail_header(struct vty *vty, struct bgp *bgp, vty_out(vty, ", table %s", (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) - ? "Default-IP-Routing-Table" + ? VRF_DEFAULT_NAME : bgp->name); } else vty_out(vty, ", no best path"); diff --git a/bgpd/bgp_routemap.c b/bgpd/bgp_routemap.c index 60a4e994c9..f7c4175383 100644 --- a/bgpd/bgp_routemap.c +++ b/bgpd/bgp_routemap.c @@ -3438,7 +3438,7 @@ DEFUN (no_match_evpn_route_type, DEFUN (match_evpn_vni, match_evpn_vni_cmd, - "match evpn vni (1-16777215)", + "match evpn vni " CMD_VNI_RANGE, MATCH_STR EVPN_HELP_STR "Match VNI\n" @@ -3450,7 +3450,7 @@ DEFUN (match_evpn_vni, DEFUN (no_match_evpn_vni, no_match_evpn_vni_cmd, - "no match evpn vni (1-16777215)", + "no match evpn vni " CMD_VNI_RANGE, NO_STR MATCH_STR EVPN_HELP_STR diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index 45136cf454..c57cd38151 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -822,6 +822,87 @@ DEFUN_HIDDEN (no_bgp_multiple_instance, return CMD_SUCCESS; } +DEFUN_HIDDEN (bgp_local_mac, + bgp_local_mac_cmd, + "bgp local-mac vni " CMD_VNI_RANGE " mac WORD seq (0-4294967295)", + BGP_STR + "Local MAC config\n" + "VxLAN Network Identifier\n" + "VNI number\n" + "local mac\n" + "mac address\n" + "mac-mobility sequence\n" + "seq number\n") +{ + int rv; + vni_t vni; + struct ethaddr mac; + struct ipaddr ip; + uint32_t seq; + struct bgp *bgp; + + vni = strtoul(argv[3]->arg, NULL, 10); + if (!prefix_str2mac(argv[5]->arg, &mac)) { + vty_out(vty, "%% Malformed MAC address\n"); + return CMD_WARNING; + } + memset(&ip, 0, sizeof(ip)); + seq = strtoul(argv[7]->arg, NULL, 10); + + bgp = bgp_get_default(); + if (!bgp) { + vty_out(vty, "Default BGP instance is not there\n"); + return CMD_WARNING; + } + + rv = bgp_evpn_local_macip_add(bgp, vni, &mac, &ip, 0 /* flags */, seq); + if (rv < 0) { + vty_out(vty, "Internal error\n"); + return CMD_WARNING; + } + + return CMD_SUCCESS; +} + +DEFUN_HIDDEN (no_bgp_local_mac, + no_bgp_local_mac_cmd, + "no bgp local-mac vni " CMD_VNI_RANGE " mac WORD", + NO_STR + BGP_STR + "Local MAC config\n" + "VxLAN Network Identifier\n" + "VNI number\n" + "local mac\n" + "mac address\n") +{ + int rv; + vni_t vni; + struct ethaddr mac; + struct ipaddr ip; + struct bgp *bgp; + + vni = strtoul(argv[4]->arg, NULL, 10); + if (!prefix_str2mac(argv[6]->arg, &mac)) { + vty_out(vty, "%% Malformed MAC address\n"); + return CMD_WARNING; + } + memset(&ip, 0, sizeof(ip)); + + bgp = bgp_get_default(); + if (!bgp) { + vty_out(vty, "Default BGP instance is not there\n"); + return CMD_WARNING; + } + + rv = bgp_evpn_local_macip_del(bgp, vni, &mac, &ip); + if (rv < 0) { + vty_out(vty, "Internal error\n"); + return CMD_WARNING; + } + + return CMD_SUCCESS; +} + #if (CONFDATE > 20190601) CPP_NOTICE("bgpd: time to remove deprecated cli bgp config-type cisco") CPP_NOTICE("This includes BGP_OPT_CISCO_CONFIG") @@ -6784,7 +6865,7 @@ DEFPY(bgp_imexport_vrf, bgp_imexport_vrf_cmd, safi = bgp_node_safi(vty); if (((BGP_INSTANCE_TYPE_DEFAULT == bgp->inst_type) - && (strcmp(import_name, BGP_DEFAULT_NAME) == 0)) + && (strcmp(import_name, VRF_DEFAULT_NAME) == 0)) || (bgp->name && (strcmp(import_name, bgp->name) == 0))) { vty_out(vty, "%% Cannot %s vrf %s into itself\n", remove ? "unimport" : "import", import_name); @@ -6806,7 +6887,7 @@ DEFPY(bgp_imexport_vrf, bgp_imexport_vrf_cmd, vrf_bgp = bgp_lookup_by_name(import_name); if (!vrf_bgp) { - if (strcmp(import_name, BGP_DEFAULT_NAME) == 0) + if (strcmp(import_name, VRF_DEFAULT_NAME) == 0) vrf_bgp = bgp_default; else /* Auto-create assuming the same AS */ @@ -7403,7 +7484,7 @@ DEFUN (show_bgp_vrfs, } if (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) { - name = "Default"; + name = VRF_DEFAULT_NAME; type = "DFLT"; } else { name = bgp->name; @@ -7770,7 +7851,7 @@ static int bgp_show_summary(struct vty *vty, struct bgp *bgp, int afi, int safi, json, "vrfName", (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) - ? "Default" + ? VRF_DEFAULT_NAME : bgp->name); } else { vty_out(vty, @@ -8197,12 +8278,12 @@ static void bgp_show_all_instances_summary_vty(struct vty *vty, afi_t afi, vty_out(vty, "\"%s\":", (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) - ? "Default" + ? VRF_DEFAULT_NAME : bgp->name); } else { vty_out(vty, "\nInstance %s:\n", (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) - ? "Default" + ? VRF_DEFAULT_NAME : bgp->name); } bgp_show_summary_afi_safi(vty, bgp, afi, safi, use_json, json); @@ -10852,7 +10933,7 @@ static void bgp_show_all_instances_neighbors_vty(struct vty *vty, json_object_string_add( json, "vrfName", (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) - ? "Default" + ? VRF_DEFAULT_NAME : bgp->name); if (!is_first) @@ -10862,12 +10943,12 @@ static void bgp_show_all_instances_neighbors_vty(struct vty *vty, vty_out(vty, "\"%s\":", (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) - ? "Default" + ? VRF_DEFAULT_NAME : bgp->name); } else { vty_out(vty, "\nInstance %s:\n", (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) - ? "Default" + ? VRF_DEFAULT_NAME : bgp->name); } @@ -11301,7 +11382,7 @@ static void bgp_show_all_instances_updgrps_vty(struct vty *vty, afi_t afi, for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) { vty_out(vty, "\nInstance %s:\n", (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) - ? "Default" + ? VRF_DEFAULT_NAME : bgp->name); update_group_show(bgp, afi, safi, vty, 0); } @@ -12593,6 +12674,10 @@ void bgp_vty_init(void) install_element(CONFIG_NODE, &bgp_config_type_cmd); install_element(CONFIG_NODE, &no_bgp_config_type_cmd); + /* "bgp local-mac" hidden commands. */ + install_element(CONFIG_NODE, &bgp_local_mac_cmd); + install_element(CONFIG_NODE, &no_bgp_local_mac_cmd); + /* bgp route-map delay-timer commands. */ install_element(CONFIG_NODE, &bgp_set_route_map_delay_timer_cmd); install_element(CONFIG_NODE, &no_bgp_set_route_map_delay_timer_cmd); diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c index 50b790eb11..62f977eee1 100644 --- a/bgpd/bgp_zebra.c +++ b/bgpd/bgp_zebra.c @@ -2574,7 +2574,7 @@ void bgp_zebra_init(struct thread_master *master, unsigned short instance) zclient_num_connects = 0; /* Set default values. */ - zclient = zclient_new_notify(master, &zclient_options_default); + zclient = zclient_new(master, &zclient_options_default); zclient_init(zclient, ZEBRA_ROUTE_BGP, 0, &bgpd_privs); zclient->zebra_connected = bgp_zebra_connected; zclient->router_id_update = bgp_router_id_update; diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h index c04fe69035..e14b0f39e0 100644 --- a/bgpd/bgpd.h +++ b/bgpd/bgpd.h @@ -368,7 +368,6 @@ struct bgp { /* vrf-route leaking flags */ #define BGP_CONFIG_VRF_TO_VRF_IMPORT (1 << 7) #define BGP_CONFIG_VRF_TO_VRF_EXPORT (1 << 8) -#define BGP_DEFAULT_NAME "default" /* Route table for next-hop lookup cache. */ struct bgp_table *nexthop_cache_table[AFI_MAX]; diff --git a/bgpd/rfapi/vnc_zebra.c b/bgpd/rfapi/vnc_zebra.c index 97d520eda7..a43cf1f6a9 100644 --- a/bgpd/rfapi/vnc_zebra.c +++ b/bgpd/rfapi/vnc_zebra.c @@ -913,7 +913,7 @@ extern struct zebra_privs_t bgpd_privs; void vnc_zebra_init(struct thread_master *master) { /* Set default values. */ - zclient_vnc = zclient_new_notify(master, &zclient_options_default); + zclient_vnc = zclient_new(master, &zclient_options_default); zclient_init(zclient_vnc, ZEBRA_ROUTE_VNC, 0, &bgpd_privs); zclient_vnc->redistribute_route_add = vnc_zebra_read_route; diff --git a/configure.ac b/configure.ac index 6782c539ed..3a6e7883fb 100755 --- a/configure.ac +++ b/configure.ac @@ -522,7 +522,7 @@ AC_CHECK_LIB(json-c, json_object_get, LIBS="$LIBS -ljson-c", [], [-lm]) if test "$ac_cv_lib_json_c_json_object_get" = no; then AC_CHECK_LIB(json, json_object_get, LIBS="$LIBS -ljson") if test "$ac_cv_lib_json_json_object_get" = no; then - AC_MSG_ERROR([lib json is needed to compile]) + AC_MSG_ERROR([libjson is needed to compile]) fi fi ]) diff --git a/doc/developer/building-frr-for-centos6.rst b/doc/developer/building-frr-for-centos6.rst index 5f9ce705f2..c57573cb9f 100644 --- a/doc/developer/building-frr-for-centos6.rst +++ b/doc/developer/building-frr-for-centos6.rst @@ -244,7 +244,7 @@ Load the modifed sysctl's on the system: Add init.d startup files ^^^^^^^^^^^^^^^^^^^^^^^^ -.. code-block:: +.. code-block:: shell sudo install -p -m 755 redhat/frr.init /etc/init.d/frr sudo chkconfig --add frr @@ -252,13 +252,13 @@ Add init.d startup files Enable FRR daemon at startup ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -.. code-block:: +.. code-block:: shell sudo chkconfig frr on Start FRR manually (or reboot) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -.. code-block:: +.. code-block:: shell sudo /etc/init.d/frr start diff --git a/doc/developer/building-frr-for-ubuntu1804.rst b/doc/developer/building-frr-for-ubuntu1804.rst index 2d1edc063d..e69ded8f73 100644 --- a/doc/developer/building-frr-for-ubuntu1804.rst +++ b/doc/developer/building-frr-for-ubuntu1804.rst @@ -115,7 +115,7 @@ Create empty FRR configuration files ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Although not strictly necessary, it's good practice to create empty -configuration files _before_ starting FRR. This assures that the permissions +configuration files _before_ starting FRR. This assures that the permissions are correct. If the files are not already present, FRR will create them. It's also important to consider _which_ files to create. FRR supports writing diff --git a/doc/developer/building-libyang.rst b/doc/developer/building-libyang.rst index 9757ad454e..005b6ba786 100644 --- a/doc/developer/building-libyang.rst +++ b/doc/developer/building-libyang.rst @@ -40,23 +40,3 @@ When building libyang on CentOS 6, it's also necessary to pass the Note: please check the `libyang build requirements <https://github.com/CESNET/libyang/blob/master/README.md#build-requirements>`_ first. - -Libyang uses loadable libraries an YANG modules. It supports -environment variables to allow overriding the load paths for each of -these. With FRR, this override currently must be done at the time of -running FRR's configure command using new options. The new options are: - -.. code-block:: shell - - --with-yangmodelsdir=DIR - yang models directory (${datarootdir}/yang) - --with-libyang-pluginsdir=DIR - yangmodule plugins directory - (${libdir}/frr/libyang_plugins) - -an example which uses the compile directory is: - -.. code-block:: shell - - ./configure --with-libyang-pluginsdir="`pwd`/yang/libyang_plugins/.libs" \ - --with-yangmodelsdir="`pwd`/yang" diff --git a/doc/developer/conf.py b/doc/developer/conf.py index 61253c4b2f..254c9f6bfc 100644 --- a/doc/developer/conf.py +++ b/doc/developer/conf.py @@ -131,7 +131,7 @@ language = None # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. -exclude_patterns = ['_build'] +exclude_patterns = ['_build', 'building-libyang.rst'] # The reST default role (used for this markup: `text`) to use for all # documents. diff --git a/doc/developer/maintainer-release-build.rst b/doc/developer/maintainer-release-build.rst index 907bd14ee6..85aaa5365a 100644 --- a/doc/developer/maintainer-release-build.rst +++ b/doc/developer/maintainer-release-build.rst @@ -1,5 +1,5 @@ -Release Build Procedure for FRR maintainers -========================================================= +Release Build Procedure for FRR Maintainers +=========================================== 1. Rename branch (if needed) diff --git a/doc/developer/modules.rst b/doc/developer/modules.rst index bde7682e4e..99c79462ab 100644 --- a/doc/developer/modules.rst +++ b/doc/developer/modules.rst @@ -103,9 +103,9 @@ standard entry point for loadable modules. Command line parameters ----------------------- -Command line parameters can be passed directly to a module by appending a -colon to the module name when loading it, e.g. ``-M mymodule:myparameter``. -The text after the colon will be accessible in the module's code through +Command line parameters can be passed directly to a module by appending a +colon to the module name when loading it, e.g. ``-M mymodule:myparameter``. +The text after the colon will be accessible in the module's code through ``THIS_MODULE->load_args``. For example, see how the format parameter is configured in the ``zfpm_init()`` function inside ``zebra_fpm.c``. diff --git a/doc/developer/next-hop-tracking.rst b/doc/developer/next-hop-tracking.rst index e6484102a8..a9af5e749c 100644 --- a/doc/developer/next-hop-tracking.rst +++ b/doc/developer/next-hop-tracking.rst @@ -269,7 +269,7 @@ RNH table:: O O / \ O O - + struct rnh { uint8_t flags; diff --git a/doc/developer/packaging-debian.rst b/doc/developer/packaging-debian.rst index 4ea784c0fc..c812a38212 100644 --- a/doc/developer/packaging-debian.rst +++ b/doc/developer/packaging-debian.rst @@ -1,5 +1,5 @@ -Debian -====== +Packaging Debian +================ (Tested on Ubuntu 12.04, 14.04, 16.04, 17.10, 18.04, Debian 8 and 9) diff --git a/doc/developer/packaging.rst b/doc/developer/packaging.rst index e9bb3a5409..27e6e155fb 100644 --- a/doc/developer/packaging.rst +++ b/doc/developer/packaging.rst @@ -5,4 +5,5 @@ Packaging .. toctree:: :maxdepth: 2 + maintainer-release-build packaging-debian diff --git a/doc/developer/process-architecture.rst b/doc/developer/process-architecture.rst index 806afa644c..6e0eb68188 100644 --- a/doc/developer/process-architecture.rst +++ b/doc/developer/process-architecture.rst @@ -118,7 +118,7 @@ The following diagram illustrates a simplified version of this infrastructure. .. todo: replace these with SVG .. figure:: ../figures/threadmaster-single.png :align: center - + Lifecycle of a program using a single threadmaster. The series of "task" boxes represents the current ready task queue. The various @@ -183,7 +183,7 @@ running their own ``threadmaster``-based event loop. .. todo: replace these with SVG .. figure:: ../figures/threadmaster-multiple.png :align: center - + Lifecycle of a program using multiple pthreads, each running their own ``threadmaster`` diff --git a/doc/user/installation.rst b/doc/user/installation.rst index b7f0712a1b..9654cc2eb8 100644 --- a/doc/user/installation.rst +++ b/doc/user/installation.rst @@ -255,6 +255,24 @@ options to the configuration script. Configure zebra to use `dir` for local state files, such as pid files and unix sockets. +.. option:: --with-yangmodelsdir <dir> + + Look for YANG modules in `dir` [`prefix`/share/yang]. Note that the FRR + YANG modules will be installed here. + +.. option:: --with-libyang-pluginsdir <dir> + + Look for libyang plugins in `dir` [`prefix`/lib/frr/libyang_plugins]. + Note that the FRR libyang plugins will be installed here. + +When it's desired to run FRR without installing it in the system, it's possible +to configure it as follows to look for YANG modules and libyang plugins in the +compile directory: +.. code-block:: shell + + ./configure --with-libyang-pluginsdir="`pwd`/yang/libyang_plugins/.libs" \ + --with-yangmodelsdir="`pwd`/yang" + .. _least-privilege-support: Least-Privilege Support @@ -367,7 +385,7 @@ Additional kernel modules are also needed to support MPLS forwarding. appropriate value. :makevar:`VRF forwarding` - General information on Linux VRF support can be found in + General information on Linux VRF support can be found in https://www.kernel.org/doc/Documentation/networking/vrf.txt. Kernel support for VRFs was introduced in 4.3 and improved upon through 4.13, which is the version most used in FRR testing (as of June @@ -403,7 +421,7 @@ Additional kernel modules are also needed to support MPLS forwarding. included in future kernel versions so upgrading your kernel may also address this issue. - + Building ^^^^^^^^ diff --git a/doc/user/isisd.rst b/doc/user/isisd.rst index ee681858d1..f7607a54f7 100644 --- a/doc/user/isisd.rst +++ b/doc/user/isisd.rst @@ -30,14 +30,11 @@ configuration file :file:`isisd.conf`. ISIS router =========== -To start ISIS process you have to specify the ISIS router. As of this +To start the ISIS process you have to specify the ISIS router. As of this writing, *isisd* does not support multiple ISIS processes. -.. index:: router isis WORD -.. clicmd:: router isis WORD - -.. index:: no router isis WORD -.. clicmd:: no router isis WORD +.. index:: [no] router isis WORD +.. clicmd:: [no] router isis WORD Enable or disable the ISIS process by specifying the ISIS domain with 'WORD'. *isisd* does not yet support multiple ISIS processes but you must @@ -197,17 +194,15 @@ ISIS region ISIS interface ============== -.. index:: ip router isis WORD -.. clicmd:: ip router isis WORD - -.. index:: no ip router isis WORD -.. clicmd:: no ip router isis WORD - .. _ip-router-isis-word: - Activate ISIS adjacency on this interface. Note that the name - of ISIS instance must be the same as the one used to configure the ISIS process - (see command :clicmd:`router isis WORD`). +.. index:: [no] <ip|ipv6> router isis WORD +.. clicmd:: [no] <ip|ipv6> router isis WORD + + Activate ISIS adjacency on this interface. Note that the name of ISIS + instance must be the same as the one used to configure the ISIS process (see + command :clicmd:`router isis WORD`). To enable IPv4, issue ``ip router isis + WORD``; to enable IPv6, issue ``ipv6 router isis WORD``. .. index:: isis circuit-type [level-1 | level-1-2 | level-2] .. clicmd:: isis circuit-type [level-1 | level-1-2 | level-2] diff --git a/doc/user/ospfd.rst b/doc/user/ospfd.rst index e843136396..b6a7cd5de0 100644 --- a/doc/user/ospfd.rst +++ b/doc/user/ospfd.rst @@ -979,14 +979,17 @@ Traffic Engineering Router Information ================== -.. index:: router-info [as | area <A.B.C.D>] -.. clicmd:: router-info [as | area <A.B.C.D>] +.. index:: router-info [as | area] +.. clicmd:: router-info [as | area] .. index:: no router-info .. clicmd:: no router-info Enable Router Information (:rfc:`4970`) LSA advertisement with AS scope - (default) or Area scope flooding when area is specified. + (default) or Area scope flooding when area is specified. Old syntax + `router-info area <A.B.C.D>` is always supported but mark as deprecated + as the area ID is no more necessary. Indeed, router information support + multi-area and detect automatically the areas. .. index:: pce address <A.B.C.D> .. clicmd:: pce address <A.B.C.D> diff --git a/doc/user/static.rst b/doc/user/static.rst index 6755c809eb..1705b6379e 100644 --- a/doc/user/static.rst +++ b/doc/user/static.rst @@ -9,7 +9,7 @@ of static routes. .. _starting-static: -Starting STATIC +Starting STATIC =============== Default configuration file for *staticd* is :file:`staticd.conf`. The typical @@ -45,11 +45,11 @@ a static prefix and gateway. initial form of the command. GATEWAY is gateway for the prefix it currently must match the v4 or v6 route type specified at the start of the command. GATEWAY can also be treated as an interface name. If the interface name - is ``null0`` then zebra installs a blackhole route. TABLENO + is ``null0`` then zebra installs a blackhole route. TABLENO is an optional parameter for namespaces that allows you to create the route in a specified table associated with the vrf namespace. table will be rejected if you are not using namespace based vrfs. ``nexthop-vrf`` - allows you to create a leaked route with a nexthop in the specified VRFNAME + allows you to create a leaked route with a nexthop in the specified VRFNAME vrf VRFNAME allows you to create the route in a specified vrf. ``nexthop-vrf`` cannot be currently used with namespace based vrfs currently as well. diff --git a/doc/user/zebra.rst b/doc/user/zebra.rst index 1cfb7953d4..dc2c95cd7a 100644 --- a/doc/user/zebra.rst +++ b/doc/user/zebra.rst @@ -186,7 +186,7 @@ Standard Commands Enable/disable link-detect on platforms which support this. Currently only Linux and Solaris, and only where network interface drivers support reporting link-state via the ``IFF_RUNNING`` flag. - + In FRR, link-detect is on by default. .. _link-parameters-commands: diff --git a/eigrpd/eigrp_zebra.c b/eigrpd/eigrp_zebra.c index 3a3d6aae12..29bd23b514 100644 --- a/eigrpd/eigrp_zebra.c +++ b/eigrpd/eigrp_zebra.c @@ -116,7 +116,7 @@ void eigrp_zebra_init(void) { struct zclient_options opt = {.receive_notify = false}; - zclient = zclient_new_notify(master, &opt); + zclient = zclient_new(master, &opt); zclient_init(zclient, ZEBRA_ROUTE_EIGRP, 0, &eigrpd_privs); zclient->zebra_connected = eigrp_zebra_connected; diff --git a/isisd/isis_lsp.c b/isisd/isis_lsp.c index bb090f42ed..38239d5919 100644 --- a/isisd/isis_lsp.c +++ b/isisd/isis_lsp.c @@ -406,8 +406,12 @@ static void lsp_seqno_update(struct isis_lsp *lsp0) for (ALL_LIST_ELEMENTS_RO(lsp0->lspu.frags, node, lsp)) { if (lsp->tlvs) lsp_inc_seqno(lsp, 0); - else + else if (lsp->hdr.rem_lifetime) { + /* Purge should only be applied when the fragment has + * non-zero remaining lifetime. + */ lsp_purge(lsp, lsp0->level, NULL); + } } return; @@ -578,29 +582,17 @@ void lsp_insert(struct isis_lsp *lsp, dict_t *lspdb) void lsp_build_list_nonzero_ht(uint8_t *start_id, uint8_t *stop_id, struct list *list, dict_t *lspdb) { - dnode_t *first, *last, *curr; - - first = dict_lower_bound(lspdb, start_id); - if (!first) - return; - - last = dict_upper_bound(lspdb, stop_id); + for (dnode_t *curr = dict_lower_bound(lspdb, start_id); + curr; curr = dict_next(lspdb, curr)) { + struct isis_lsp *lsp = curr->dict_data; - curr = first; - - if (((struct isis_lsp *)(curr->dict_data))->hdr.rem_lifetime) - listnode_add(list, first->dict_data); - - while (curr) { - curr = dict_next(lspdb, curr); - if (curr - && ((struct isis_lsp *)(curr->dict_data))->hdr.rem_lifetime) - listnode_add(list, curr->dict_data); - if (curr == last) + if (memcmp(lsp->hdr.lsp_id, stop_id, + ISIS_SYS_ID_LEN + 2) > 0) break; - } - return; + if (lsp->hdr.rem_lifetime) + listnode_add(list, lsp); + } } static void lsp_set_time(struct isis_lsp *lsp) @@ -1306,6 +1298,13 @@ static int lsp_regenerate(struct isis_area *area, int level) lsp->last_generated = time(NULL); lsp_flood(lsp, NULL); for (ALL_LIST_ELEMENTS_RO(lsp->lspu.frags, node, frag)) { + if (!frag->tlvs) { + /* Updating and flooding should only affect fragments + * carrying data + */ + continue; + } + frag->hdr.lsp_bits = lsp_bits_generate( level, area->overload_bit, area->attached_bit); /* Set the lifetime values of all the fragments to the same @@ -1361,7 +1360,7 @@ static int lsp_refresh(struct thread *thread) if ((area->is_type & level) == 0) return ISIS_ERROR; - if (monotime_since(&area->last_lsp_refresh_event[level - 1], NULL) < 50000L) { + if (monotime_since(&area->last_lsp_refresh_event[level - 1], NULL) < 100000L) { sched_debug("ISIS (%s): Still unstable, postpone LSP L%d refresh", area->area_tag, level); _lsp_regenerate_schedule(area, level, 0, false, @@ -1999,13 +1998,13 @@ void lsp_set_all_srmflags(struct isis_lsp *lsp, bool set) void lsp_flood(struct isis_lsp *lsp, struct isis_circuit *circuit) { - if (!fabricd) { + if (!fabricd) lsp_set_all_srmflags(lsp, true); - if (circuit) - isis_tx_queue_del(circuit->tx_queue, lsp); - } else { + else fabricd_lsp_flood(lsp); - } + + if (circuit) + isis_tx_queue_del(circuit->tx_queue, lsp); } static int lsp_handle_adj_state_change(struct isis_adjacency *adj) diff --git a/isisd/isis_zebra.c b/isisd/isis_zebra.c index 33d8a0f771..101bd57cc9 100644 --- a/isisd/isis_zebra.c +++ b/isisd/isis_zebra.c @@ -87,12 +87,6 @@ static int isis_zebra_if_add(int command, struct zclient *zclient, ifp = zebra_interface_add_read(zclient->ibuf, vrf_id); - if (isis->debugs & DEBUG_ZEBRA) - zlog_debug( - "Zebra I/F add: %s index %d flags %ld metric %d mtu %d", - ifp->name, ifp->ifindex, (long)ifp->flags, ifp->metric, - ifp->mtu); - if (if_is_operative(ifp)) isis_csm_state_change(IF_UP_FROM_Z, circuit_scan_by_ifp(ifp), ifp); @@ -116,12 +110,6 @@ static int isis_zebra_if_del(int command, struct zclient *zclient, zlog_warn("Zebra: got delete of %s, but interface is still up", ifp->name); - if (isis->debugs & DEBUG_ZEBRA) - zlog_debug( - "Zebra I/F delete: %s index %d flags %ld metric %d mtu %d", - ifp->name, ifp->ifindex, (long)ifp->flags, ifp->metric, - ifp->mtu); - isis_csm_state_change(IF_DOWN_FROM_Z, circuit_scan_by_ifp(ifp), ifp); /* Cannot call if_delete because we should retain the pseudo interface @@ -425,7 +413,7 @@ static void isis_zebra_connected(struct zclient *zclient) void isis_zebra_init(struct thread_master *master) { - zclient = zclient_new_notify(master, &zclient_options_default); + zclient = zclient_new(master, &zclient_options_default); zclient_init(zclient, PROTO_TYPE, 0, &isisd_privs); zclient->zebra_connected = isis_zebra_connected; zclient->router_id_update = isis_router_id_update_zebra; diff --git a/isisd/isisd.c b/isisd/isisd.c index 54bdbf3eb3..ce45ba65ec 100644 --- a/isisd/isisd.c +++ b/isisd/isisd.c @@ -720,24 +720,11 @@ void print_debug(struct vty *vty, int flags, int onoff) vty_out(vty, "IS-IS Adjacency related packets debugging is %s\n", onoffs); - if (flags & DEBUG_CHECKSUM_ERRORS) - vty_out(vty, "IS-IS checksum errors debugging is %s\n", onoffs); - if (flags & DEBUG_LOCAL_UPDATES) - vty_out(vty, "IS-IS local updates debugging is %s\n", onoffs); - if (flags & DEBUG_PROTOCOL_ERRORS) - vty_out(vty, "IS-IS protocol errors debugging is %s\n", onoffs); if (flags & DEBUG_SNP_PACKETS) vty_out(vty, "IS-IS CSNP/PSNP packets debugging is %s\n", onoffs); if (flags & DEBUG_SPF_EVENTS) vty_out(vty, "IS-IS SPF events debugging is %s\n", onoffs); - if (flags & DEBUG_SPF_STATS) - vty_out(vty, - "IS-IS SPF Timing and Statistics Data debugging is %s\n", - onoffs); - if (flags & DEBUG_SPF_TRIGGERS) - vty_out(vty, "IS-IS SPF triggering events debugging is %s\n", - onoffs); if (flags & DEBUG_UPDATE_PACKETS) vty_out(vty, "IS-IS Update related packet debugging is %s\n", onoffs); @@ -784,18 +771,6 @@ static int config_write_debug(struct vty *vty) vty_out(vty, "debug " PROTO_NAME " adj-packets\n"); write++; } - if (flags & DEBUG_CHECKSUM_ERRORS) { - vty_out(vty, "debug " PROTO_NAME " checksum-errors\n"); - write++; - } - if (flags & DEBUG_LOCAL_UPDATES) { - vty_out(vty, "debug " PROTO_NAME " local-updates\n"); - write++; - } - if (flags & DEBUG_PROTOCOL_ERRORS) { - vty_out(vty, "debug " PROTO_NAME " protocol-errors\n"); - write++; - } if (flags & DEBUG_SNP_PACKETS) { vty_out(vty, "debug " PROTO_NAME " snp-packets\n"); write++; @@ -804,14 +779,6 @@ static int config_write_debug(struct vty *vty) vty_out(vty, "debug " PROTO_NAME " spf-events\n"); write++; } - if (flags & DEBUG_SPF_STATS) { - vty_out(vty, "debug " PROTO_NAME " spf-statistics\n"); - write++; - } - if (flags & DEBUG_SPF_TRIGGERS) { - vty_out(vty, "debug " PROTO_NAME " spf-triggers\n"); - write++; - } if (flags & DEBUG_UPDATE_PACKETS) { vty_out(vty, "debug " PROTO_NAME " update-packets\n"); write++; @@ -876,87 +843,6 @@ DEFUN (no_debug_isis_adj, return CMD_SUCCESS; } -DEFUN (debug_isis_csum, - debug_isis_csum_cmd, - "debug " PROTO_NAME " checksum-errors", - DEBUG_STR - PROTO_HELP - "IS-IS LSP checksum errors\n") -{ - isis->debugs |= DEBUG_CHECKSUM_ERRORS; - print_debug(vty, DEBUG_CHECKSUM_ERRORS, 1); - - return CMD_SUCCESS; -} - -DEFUN (no_debug_isis_csum, - no_debug_isis_csum_cmd, - "no debug " PROTO_NAME " checksum-errors", - NO_STR - UNDEBUG_STR - PROTO_HELP - "IS-IS LSP checksum errors\n") -{ - isis->debugs &= ~DEBUG_CHECKSUM_ERRORS; - print_debug(vty, DEBUG_CHECKSUM_ERRORS, 0); - - return CMD_SUCCESS; -} - -DEFUN (debug_isis_lupd, - debug_isis_lupd_cmd, - "debug " PROTO_NAME " local-updates", - DEBUG_STR - PROTO_HELP - "IS-IS local update packets\n") -{ - isis->debugs |= DEBUG_LOCAL_UPDATES; - print_debug(vty, DEBUG_LOCAL_UPDATES, 1); - - return CMD_SUCCESS; -} - -DEFUN (no_debug_isis_lupd, - no_debug_isis_lupd_cmd, - "no debug " PROTO_NAME " local-updates", - NO_STR - UNDEBUG_STR - PROTO_HELP - "IS-IS local update packets\n") -{ - isis->debugs &= ~DEBUG_LOCAL_UPDATES; - print_debug(vty, DEBUG_LOCAL_UPDATES, 0); - - return CMD_SUCCESS; -} - -DEFUN (debug_isis_err, - debug_isis_err_cmd, - "debug " PROTO_NAME " protocol-errors", - DEBUG_STR - PROTO_HELP - "IS-IS LSP protocol errors\n") -{ - isis->debugs |= DEBUG_PROTOCOL_ERRORS; - print_debug(vty, DEBUG_PROTOCOL_ERRORS, 1); - - return CMD_SUCCESS; -} - -DEFUN (no_debug_isis_err, - no_debug_isis_err_cmd, - "no debug " PROTO_NAME " protocol-errors", - NO_STR - UNDEBUG_STR - PROTO_HELP - "IS-IS LSP protocol errors\n") -{ - isis->debugs &= ~DEBUG_PROTOCOL_ERRORS; - print_debug(vty, DEBUG_PROTOCOL_ERRORS, 0); - - return CMD_SUCCESS; -} - DEFUN (debug_isis_snp, debug_isis_snp_cmd, "debug " PROTO_NAME " snp-packets", @@ -1038,60 +924,6 @@ DEFUN (no_debug_isis_spfevents, return CMD_SUCCESS; } -DEFUN (debug_isis_spfstats, - debug_isis_spfstats_cmd, - "debug " PROTO_NAME " spf-statistics ", - DEBUG_STR - PROTO_HELP - "IS-IS SPF Timing and Statistic Data\n") -{ - isis->debugs |= DEBUG_SPF_STATS; - print_debug(vty, DEBUG_SPF_STATS, 1); - - return CMD_SUCCESS; -} - -DEFUN (no_debug_isis_spfstats, - no_debug_isis_spfstats_cmd, - "no debug " PROTO_NAME " spf-statistics", - NO_STR - UNDEBUG_STR - PROTO_HELP - "IS-IS SPF Timing and Statistic Data\n") -{ - isis->debugs &= ~DEBUG_SPF_STATS; - print_debug(vty, DEBUG_SPF_STATS, 0); - - return CMD_SUCCESS; -} - -DEFUN (debug_isis_spftrigg, - debug_isis_spftrigg_cmd, - "debug " PROTO_NAME " spf-triggers", - DEBUG_STR - PROTO_HELP - "IS-IS SPF triggering events\n") -{ - isis->debugs |= DEBUG_SPF_TRIGGERS; - print_debug(vty, DEBUG_SPF_TRIGGERS, 1); - - return CMD_SUCCESS; -} - -DEFUN (no_debug_isis_spftrigg, - no_debug_isis_spftrigg_cmd, - "no debug " PROTO_NAME " spf-triggers", - NO_STR - UNDEBUG_STR - PROTO_HELP - "IS-IS SPF triggering events\n") -{ - isis->debugs &= ~DEBUG_SPF_TRIGGERS; - print_debug(vty, DEBUG_SPF_TRIGGERS, 0); - - return CMD_SUCCESS; -} - DEFUN (debug_isis_rtevents, debug_isis_rtevents_cmd, "debug " PROTO_NAME " route-events", @@ -2229,22 +2061,12 @@ void isis_init() install_element(ENABLE_NODE, &debug_isis_adj_cmd); install_element(ENABLE_NODE, &no_debug_isis_adj_cmd); - install_element(ENABLE_NODE, &debug_isis_csum_cmd); - install_element(ENABLE_NODE, &no_debug_isis_csum_cmd); - install_element(ENABLE_NODE, &debug_isis_lupd_cmd); - install_element(ENABLE_NODE, &no_debug_isis_lupd_cmd); - install_element(ENABLE_NODE, &debug_isis_err_cmd); - install_element(ENABLE_NODE, &no_debug_isis_err_cmd); install_element(ENABLE_NODE, &debug_isis_snp_cmd); install_element(ENABLE_NODE, &no_debug_isis_snp_cmd); install_element(ENABLE_NODE, &debug_isis_upd_cmd); install_element(ENABLE_NODE, &no_debug_isis_upd_cmd); install_element(ENABLE_NODE, &debug_isis_spfevents_cmd); install_element(ENABLE_NODE, &no_debug_isis_spfevents_cmd); - install_element(ENABLE_NODE, &debug_isis_spfstats_cmd); - install_element(ENABLE_NODE, &no_debug_isis_spfstats_cmd); - install_element(ENABLE_NODE, &debug_isis_spftrigg_cmd); - install_element(ENABLE_NODE, &no_debug_isis_spftrigg_cmd); install_element(ENABLE_NODE, &debug_isis_rtevents_cmd); install_element(ENABLE_NODE, &no_debug_isis_rtevents_cmd); install_element(ENABLE_NODE, &debug_isis_events_cmd); @@ -2260,22 +2082,12 @@ void isis_init() install_element(CONFIG_NODE, &debug_isis_adj_cmd); install_element(CONFIG_NODE, &no_debug_isis_adj_cmd); - install_element(CONFIG_NODE, &debug_isis_csum_cmd); - install_element(CONFIG_NODE, &no_debug_isis_csum_cmd); - install_element(CONFIG_NODE, &debug_isis_lupd_cmd); - install_element(CONFIG_NODE, &no_debug_isis_lupd_cmd); - install_element(CONFIG_NODE, &debug_isis_err_cmd); - install_element(CONFIG_NODE, &no_debug_isis_err_cmd); install_element(CONFIG_NODE, &debug_isis_snp_cmd); install_element(CONFIG_NODE, &no_debug_isis_snp_cmd); install_element(CONFIG_NODE, &debug_isis_upd_cmd); install_element(CONFIG_NODE, &no_debug_isis_upd_cmd); install_element(CONFIG_NODE, &debug_isis_spfevents_cmd); install_element(CONFIG_NODE, &no_debug_isis_spfevents_cmd); - install_element(CONFIG_NODE, &debug_isis_spfstats_cmd); - install_element(CONFIG_NODE, &no_debug_isis_spfstats_cmd); - install_element(CONFIG_NODE, &debug_isis_spftrigg_cmd); - install_element(CONFIG_NODE, &no_debug_isis_spftrigg_cmd); install_element(CONFIG_NODE, &debug_isis_rtevents_cmd); install_element(CONFIG_NODE, &no_debug_isis_rtevents_cmd); install_element(CONFIG_NODE, &debug_isis_events_cmd); diff --git a/isisd/isisd.h b/isisd/isisd.h index 51b359aad4..fe9abff93c 100644 --- a/isisd/isisd.h +++ b/isisd/isisd.h @@ -204,22 +204,16 @@ int isis_area_passwd_hmac_md5_set(struct isis_area *area, int level, extern struct thread_master *master; #define DEBUG_ADJ_PACKETS (1<<0) -#define DEBUG_CHECKSUM_ERRORS (1<<1) -#define DEBUG_LOCAL_UPDATES (1<<2) -#define DEBUG_PROTOCOL_ERRORS (1<<3) -#define DEBUG_SNP_PACKETS (1<<4) -#define DEBUG_UPDATE_PACKETS (1<<5) -#define DEBUG_SPF_EVENTS (1<<6) -#define DEBUG_SPF_STATS (1<<7) -#define DEBUG_SPF_TRIGGERS (1<<8) -#define DEBUG_RTE_EVENTS (1<<9) -#define DEBUG_EVENTS (1<<10) -#define DEBUG_ZEBRA (1<<11) -#define DEBUG_PACKET_DUMP (1<<12) -#define DEBUG_LSP_GEN (1<<13) -#define DEBUG_LSP_SCHED (1<<14) -#define DEBUG_FABRICD_FLOODING (1<<15) -#define DEBUG_BFD (1<<16) +#define DEBUG_SNP_PACKETS (1<<1) +#define DEBUG_UPDATE_PACKETS (1<<2) +#define DEBUG_SPF_EVENTS (1<<3) +#define DEBUG_RTE_EVENTS (1<<4) +#define DEBUG_EVENTS (1<<5) +#define DEBUG_PACKET_DUMP (1<<6) +#define DEBUG_LSP_GEN (1<<7) +#define DEBUG_LSP_SCHED (1<<8) +#define DEBUG_FABRICD_FLOODING (1<<9) +#define DEBUG_BFD (1<<10) #define lsp_debug(...) \ do { \ @@ -233,7 +227,7 @@ extern struct thread_master *master; zlog_debug(__VA_ARGS__); \ } while (0) -#define DEBUG_TE (1<<13) +#define DEBUG_TE DEBUG_LSP_GEN #define IS_DEBUG_ISIS(x) (isis->debugs & x) diff --git a/ldpd/lde.c b/ldpd/lde.c index 4f74d93044..2aa96546ec 100644 --- a/ldpd/lde.c +++ b/ldpd/lde.c @@ -1627,7 +1627,7 @@ lde_address_list_free(struct lde_nbr *ln) static void zclient_sync_init(unsigned short instance) { /* Initialize special zclient for synchronous message exchanges. */ - zclient_sync = zclient_new_notify(master, &zclient_options_default); + zclient_sync = zclient_new(master, &zclient_options_default); zclient_sync->sock = -1; zclient_sync->redist_default = ZEBRA_ROUTE_LDP; zclient_sync->instance = instance; diff --git a/ldpd/ldp_zebra.c b/ldpd/ldp_zebra.c index c8b775cb8e..9dc5677358 100644 --- a/ldpd/ldp_zebra.c +++ b/ldpd/ldp_zebra.c @@ -533,7 +533,7 @@ void ldp_zebra_init(struct thread_master *master) { /* Set default values. */ - zclient = zclient_new_notify(master, &zclient_options_default); + zclient = zclient_new(master, &zclient_options_default); zclient_init(zclient, ZEBRA_ROUTE_LDP, 0, &ldpd_privs); /* set callbacks */ diff --git a/lib/command.h b/lib/command.h index 873ecdda98..11514fd5e8 100644 --- a/lib/command.h +++ b/lib/command.h @@ -378,6 +378,7 @@ struct cmd_node { #define WATCHFRR_STR "watchfrr information\n" #define ZEBRA_STR "Zebra information\n" +#define CMD_VNI_RANGE "(1-16777215)" #define CONF_BACKUP_EXT ".sav" /* Command warnings. */ diff --git a/lib/zclient.c b/lib/zclient.c index 45a9f7be9e..b879326d71 100644 --- a/lib/zclient.c +++ b/lib/zclient.c @@ -58,8 +58,8 @@ int zclient_debug = 0; struct zclient_options zclient_options_default = {.receive_notify = false}; /* Allocate zclient structure. */ -struct zclient *zclient_new_notify(struct thread_master *master, - struct zclient_options *opt) +struct zclient *zclient_new(struct thread_master *master, + struct zclient_options *opt) { struct zclient *zclient; zclient = XCALLOC(MTYPE_ZCLIENT, sizeof(struct zclient)); @@ -199,7 +199,7 @@ void zclient_reset(struct zclient *zclient) * @param zclient a pointer to zclient structure * @return socket fd just to make sure that connection established * @see zclient_init - * @see zclient_new_notify + * @see zclient_new */ int zclient_socket_connect(struct zclient *zclient) { diff --git a/lib/zclient.h b/lib/zclient.h index 97ebb0811c..07fe512a3c 100644 --- a/lib/zclient.h +++ b/lib/zclient.h @@ -422,23 +422,10 @@ struct zclient_options { bool receive_notify; }; -/* Prototypes of zebra client service functions. */ -extern struct zclient *zclient_new(struct thread_master *); - -/* clang-format off */ -#if CONFDATE > 20181101 -CPP_NOTICE("zclient_new_notify can take over or zclient_new now"); -#endif -/* clang-format on */ - extern struct zclient_options zclient_options_default; -extern struct zclient *zclient_new_notify(struct thread_master *m, - struct zclient_options *opt); - -#define zclient_new(A) \ - zclient_new_notify((A), &zclient_options_default); \ - CPP_WARN("Please transition to using zclient_new_notify"); +extern struct zclient *zclient_new(struct thread_master *m, + struct zclient_options *opt); extern void zclient_init(struct zclient *, int, unsigned short, struct zebra_privs_t *privs); diff --git a/nhrpd/nhrp_route.c b/nhrpd/nhrp_route.c index e7b187f3b6..dae00bbcea 100644 --- a/nhrpd/nhrp_route.c +++ b/nhrpd/nhrp_route.c @@ -344,7 +344,7 @@ void nhrp_zebra_init(void) zebra_rib[AFI_IP] = route_table_init(); zebra_rib[AFI_IP6] = route_table_init(); - zclient = zclient_new_notify(master, &zclient_options_default); + zclient = zclient_new(master, &zclient_options_default); zclient->zebra_connected = nhrp_zebra_connected; zclient->interface_add = nhrp_interface_add; zclient->interface_delete = nhrp_interface_delete; diff --git a/ospf6d/ospf6_area.c b/ospf6d/ospf6_area.c index bc52864313..30f0e9e774 100644 --- a/ospf6d/ospf6_area.c +++ b/ospf6d/ospf6_area.c @@ -567,9 +567,10 @@ void ospf6_area_config_write(struct vty *vty) DEFUN (area_filter_list, area_filter_list_cmd, - "area A.B.C.D filter-list prefix WORD <in|out>", + "area <A.B.C.D|(0-4294967295)> filter-list prefix WORD <in|out>", "OSPF6 area parameters\n" "OSPF6 area ID in IP address format\n" + "OSPF6 area ID as a decimal value\n" "Filter networks between OSPF6 areas\n" "Filter prefixes between OSPF6 areas\n" "Name of an IPv6 prefix-list\n" @@ -605,10 +606,11 @@ DEFUN (area_filter_list, DEFUN (no_area_filter_list, no_area_filter_list_cmd, - "no area A.B.C.D filter-list prefix WORD <in|out>", + "no area <A.B.C.D|(0-4294967295)> filter-list prefix WORD <in|out>", NO_STR "OSPF6 area parameters\n" "OSPF6 area ID in IP address format\n" + "OSPF6 area ID as a decimal value\n" "Filter networks between OSPF6 areas\n" "Filter prefixes between OSPF6 areas\n" "Name of an IPv6 prefix-list\n" @@ -662,9 +664,10 @@ void ospf6_area_plist_update(struct prefix_list *plist, int add) DEFUN (area_import_list, area_import_list_cmd, - "area A.B.C.D import-list NAME", + "area <A.B.C.D|(0-4294967295)> import-list NAME", "OSPF6 area parameters\n" "OSPF6 area ID in IP address format\n" + "OSPF6 area ID as a decimal value\n" "Set the filter for networks from other areas announced to the specified one\n" "Name of the acess-list\n") { @@ -690,10 +693,11 @@ DEFUN (area_import_list, DEFUN (no_area_import_list, no_area_import_list_cmd, - "no area A.B.C.D import-list NAME", + "no area <A.B.C.D|(0-4294967295)> import-list NAME", NO_STR "OSPF6 area parameters\n" "OSPF6 area ID in IP address format\n" + "OSPF6 area ID as a decimal value\n" "Unset the filter for networks announced to other areas\n" "Name of the access-list\n") { @@ -715,9 +719,10 @@ DEFUN (no_area_import_list, DEFUN (area_export_list, area_export_list_cmd, - "area A.B.C.D export-list NAME", + "area <A.B.C.D|(0-4294967295)> export-list NAME", "OSPF6 area parameters\n" "OSPF6 area ID in IP address format\n" + "OSPF6 area ID as a decimal value\n" "Set the filter for networks announced to other areas\n" "Name of the acess-list\n") { @@ -743,10 +748,11 @@ DEFUN (area_export_list, DEFUN (no_area_export_list, no_area_export_list_cmd, - "no area A.B.C.D export-list NAME", + "no area <A.B.C.D|(0-4294967295)> export-list NAME", NO_STR "OSPF6 area parameters\n" "OSPF6 area ID in IP address format\n" + "OSPF6 area ID as a decimal value\n" "Unset the filter for networks announced to other areas\n" "Name of the access-list\n") { diff --git a/ospf6d/ospf6_zebra.c b/ospf6d/ospf6_zebra.c index c968b35d90..5db9b529ef 100644 --- a/ospf6d/ospf6_zebra.c +++ b/ospf6d/ospf6_zebra.c @@ -586,7 +586,7 @@ static void ospf6_zebra_connected(struct zclient *zclient) void ospf6_zebra_init(struct thread_master *master) { /* Allocate zebra structure. */ - zclient = zclient_new_notify(master, &zclient_options_default); + zclient = zclient_new(master, &zclient_options_default); zclient_init(zclient, ZEBRA_ROUTE_OSPF6, 0, &ospf6d_privs); zclient->zebra_connected = ospf6_zebra_connected; zclient->router_id_update = ospf6_router_id_update_zebra; diff --git a/ospfd/ospf_memory.c b/ospfd/ospf_memory.c index 1332104b0a..c4dc0136ed 100644 --- a/ospfd/ospf_memory.c +++ b/ospfd/ospf_memory.c @@ -52,6 +52,7 @@ DEFINE_MTYPE(OSPFD, OSPF_IF_INFO, "OSPF if info") DEFINE_MTYPE(OSPFD, OSPF_IF_PARAMS, "OSPF if params") DEFINE_MTYPE(OSPFD, OSPF_MESSAGE, "OSPF message") DEFINE_MTYPE(OSPFD, OSPF_MPLS_TE, "OSPF MPLS parameters") +DEFINE_MTYPE(OSPFD, OSPF_ROUTER_INFO, "OSPF Router Info parameters") DEFINE_MTYPE(OSPFD, OSPF_PCE_PARAMS, "OSPF PCE parameters") DEFINE_MTYPE(OSPFD, OSPF_EXT_PARAMS, "OSPF Extended parameters") DEFINE_MTYPE(OSPFD, OSPF_SR_PARAMS, "OSPF Segment Routing parameters") diff --git a/ospfd/ospf_memory.h b/ospfd/ospf_memory.h index 50c6f33ecf..861de64c25 100644 --- a/ospfd/ospf_memory.h +++ b/ospfd/ospf_memory.h @@ -51,6 +51,7 @@ DECLARE_MTYPE(OSPF_IF_INFO) DECLARE_MTYPE(OSPF_IF_PARAMS) DECLARE_MTYPE(OSPF_MESSAGE) DECLARE_MTYPE(OSPF_MPLS_TE) +DECLARE_MTYPE(OSPF_ROUTER_INFO) DECLARE_MTYPE(OSPF_PCE_PARAMS) DECLARE_MTYPE(OSPF_SR_PARAMS) DECLARE_MTYPE(OSPF_EXT_PARAMS) diff --git a/ospfd/ospf_ri.c b/ospfd/ospf_ri.c index bef16761f2..72f6dbe08e 100644 --- a/ospfd/ospf_ri.c +++ b/ospfd/ospf_ri.c @@ -59,60 +59,6 @@ #include "ospfd/ospf_ri.h" #include "ospfd/ospf_errors.h" -/* Store Router Information PCE TLV and SubTLV in network byte order. */ -struct ospf_pce_info { - bool enabled; - struct ri_tlv_pce pce_header; - struct ri_pce_subtlv_address pce_address; - struct ri_pce_subtlv_path_scope pce_scope; - struct list *pce_domain; - struct list *pce_neighbor; - struct ri_pce_subtlv_cap_flag pce_cap_flag; -}; - -/* - * Store Router Information Segment Routing TLV and SubTLV - * in network byte order - */ -struct ospf_ri_sr_info { - bool enabled; - /* Algorithms supported by the node */ - struct ri_sr_tlv_sr_algorithm algo; - /* - * Segment Routing Global Block i.e. label range - * Only one range supported in this code - */ - struct ri_sr_tlv_sid_label_range range; - /* Maximum SID Depth supported by the node */ - struct ri_sr_tlv_node_msd msd; -}; - -/* Following structure are internal use only. */ -struct ospf_router_info { - bool enabled; - - uint8_t registered; - uint8_t scope; - -/* Flags to manage this router information. */ -#define RIFLG_LSA_ENGAGED 0x1 -#define RIFLG_LSA_FORCED_REFRESH 0x2 - uint32_t flags; - - /* area pointer if flooding is Type 10 Null if flooding is AS scope */ - struct ospf_area *area; - struct in_addr area_id; - - /* Store Router Information Capabilities LSA */ - struct ri_tlv_router_cap router_cap; - - /* Store PCE capability LSA */ - struct ospf_pce_info pce_info; - - /* Store SR capability LSA */ - struct ospf_ri_sr_info sr_info; -}; - /* * Global variable to manage Opaque-LSA/Router Information on this node. * Note that all parameter values are stored in network byte order. @@ -126,28 +72,29 @@ static struct ospf_router_info OspfRI; static void ospf_router_info_ism_change(struct ospf_interface *oi, int old_status); -static void ospf_router_info_nsm_change(struct ospf_neighbor *nbr, - int old_status); static void ospf_router_info_config_write_router(struct vty *vty); static void ospf_router_info_show_info(struct vty *vty, struct ospf_lsa *lsa); static int ospf_router_info_lsa_originate(void *arg); static struct ospf_lsa *ospf_router_info_lsa_refresh(struct ospf_lsa *lsa); -static void ospf_router_info_lsa_schedule(enum lsa_opcode opcode); +static void ospf_router_info_lsa_schedule(struct ospf_ri_area_info *ai, + enum lsa_opcode opcode); static void ospf_router_info_register_vty(void); static int ospf_router_info_lsa_update(struct ospf_lsa *lsa); +static void del_area_info(void *val); static void del_pce_info(void *val); int ospf_router_info_init(void) { - zlog_info("RI -> Initialize Router Information"); + zlog_info("RI (%s): Initialize Router Information", __func__); memset(&OspfRI, 0, sizeof(struct ospf_router_info)); OspfRI.enabled = false; OspfRI.registered = 0; OspfRI.scope = OSPF_OPAQUE_AS_LSA; - OspfRI.area_id.s_addr = 0; - OspfRI.flags = 0; + OspfRI.as_flags = RIFLG_LSA_INACTIVE; + OspfRI.area_info = list_new(); + OspfRI.area_info->del = del_area_info; /* Initialize pce domain and neighbor list */ OspfRI.pce_info.enabled = false; @@ -171,13 +118,15 @@ static int ospf_router_info_register(uint8_t scope) if (OspfRI.registered) return rc; - zlog_info("RI -> Register Router Information with scope %s(%d)", + zlog_info("RI (%s): Register Router Information with scope %s(%d)", + __func__, scope == OSPF_OPAQUE_AREA_LSA ? "Area" : "AS", scope); rc = ospf_register_opaque_functab( scope, OPAQUE_TYPE_ROUTER_INFORMATION_LSA, NULL, /* new interface */ NULL, /* del interface */ - ospf_router_info_ism_change, ospf_router_info_nsm_change, + ospf_router_info_ism_change, + NULL, /* NSM change */ ospf_router_info_config_write_router, NULL, /* Config. write interface */ NULL, /* Config. write debug */ @@ -188,7 +137,7 @@ static int ospf_router_info_register(uint8_t scope) if (rc != 0) { flog_warn( EC_OSPF_OPAQUE_REGISTRATION, - "ospf_router_info_init: Failed to register functions"); + "RI (%s): Failed to register functions", __func__); return rc; } @@ -235,10 +184,14 @@ void ospf_router_info_finish(void) OspfRI.enabled = false; } +static void del_area_info(void *val) +{ + XFREE(MTYPE_OSPF_ROUTER_INFO, val); +} + static void del_pce_info(void *val) { XFREE(MTYPE_OSPF_PCE_PARAMS, val); - return; } /* Catch RI LSA flooding Scope for ospf_ext.[h,c] code */ @@ -248,14 +201,26 @@ struct scope_info ospf_router_info_get_flooding_scope(void) if (OspfRI.scope == OSPF_OPAQUE_AS_LSA) { flooding_scope.scope = OSPF_OPAQUE_AS_LSA; - flooding_scope.area_id.s_addr = 0; + flooding_scope.areas = NULL; return flooding_scope; } flooding_scope.scope = OSPF_OPAQUE_AREA_LSA; - flooding_scope.area_id.s_addr = OspfRI.area_id.s_addr; + flooding_scope.areas = OspfRI.area_info; return flooding_scope; } +static struct ospf_ri_area_info *lookup_by_area(struct ospf_area *area) +{ + struct listnode *node, *nnode; + struct ospf_ri_area_info *ai; + + for (ALL_LIST_ELEMENTS(OspfRI.area_info, node, nnode, ai)) + if (ai->area == area) + return ai; + + return NULL; +} + /*------------------------------------------------------------------------* * Followings are control functions for ROUTER INFORMATION parameters *management. @@ -525,6 +490,9 @@ static void initialize_params(struct ospf_router_info *ori) { uint32_t cap = 0; struct ospf *top; + struct listnode *node, *nnode; + struct ospf_area *area; + struct ospf_ri_area_info *new; /* * Initialize default Router Information Capabilities. @@ -536,14 +504,22 @@ static void initialize_params(struct ospf_router_info *ori) /* If Area address is not null and exist, retrieve corresponding * structure */ top = ospf_lookup_by_vrf_id(VRF_DEFAULT); - zlog_info("RI-> Initialize Router Info for %s scope within area %s", - OspfRI.scope == OSPF_OPAQUE_AREA_LSA ? "Area" : "AS", - inet_ntoa(OspfRI.area_id)); + zlog_info("RI (%s): Initialize Router Info for %s scope", __func__, + OspfRI.scope == OSPF_OPAQUE_AREA_LSA ? "Area" : "AS"); - /* Try to get the Area context at this step. Do it latter if not - * available */ - if ((OspfRI.scope == OSPF_OPAQUE_AREA_LSA) && (OspfRI.area == NULL)) - OspfRI.area = ospf_area_lookup_by_area_id(top, OspfRI.area_id); + /* Try to get available Area's context from ospf at this step. + * Do it latter if not available */ + if (OspfRI.scope == OSPF_OPAQUE_AREA_LSA) { + for (ALL_LIST_ELEMENTS(top->areas, node, nnode, area)) { + zlog_debug("RI (%s): Add area %s to Router Information", + __func__, inet_ntoa(area->area_id)); + new = XCALLOC(MTYPE_OSPF_ROUTER_INFO, + sizeof(struct ospf_ri_area_info)); + new->area = area; + new->flags = RIFLG_LSA_INACTIVE; + listnode_add(OspfRI.area_info, new); + } + } /* * Initialize default PCE Information values @@ -597,16 +573,31 @@ static int is_mandated_params_set(struct ospf_router_info ori) */ void ospf_router_info_update_sr(bool enable, struct sr_srgb srgb, uint8_t msd) { + struct listnode *node, *nnode; + struct ospf_ri_area_info *ai; + + /* First, check if Router Information is registered or not */ + if (!OspfRI.registered) + ospf_router_info_register(OSPF_OPAQUE_AREA_LSA); + + /* Verify that scope is AREA */ + if (OspfRI.scope != OSPF_OPAQUE_AREA_LSA) { + zlog_err( + "RI (%s): Router Info is %s flooding: Change scope to Area flooding for Segment Routing", + __func__, + OspfRI.scope == OSPF_OPAQUE_AREA_LSA ? "Area" : "AS"); + return; + } - /* First activate and initialize Router Information is necessary */ + /* Then, activate and initialize Router Information if necessary */ if (!OspfRI.enabled) { OspfRI.enabled = true; initialize_params(&OspfRI); } if (IS_DEBUG_OSPF_SR) - zlog_debug("RI-> %s Routing Information for Segment Routing", - enable ? "Enable" : "Disable"); + zlog_debug("RI (%s): %s Routing Information for Segment Routing", + __func__, enable ? "Enable" : "Disable"); /* Unset or Set SR parameters */ if (!enable) { @@ -626,10 +617,14 @@ void ospf_router_info_update_sr(bool enable, struct sr_srgb srgb, uint8_t msd) } /* Refresh if already engaged or originate RI LSA */ - if (CHECK_FLAG(OspfRI.flags, RIFLG_LSA_ENGAGED)) - ospf_router_info_lsa_schedule(REFRESH_THIS_LSA); - else - ospf_router_info_lsa_schedule(REORIGINATE_THIS_LSA); + for (ALL_LIST_ELEMENTS(OspfRI.area_info, node, nnode, ai)) { + if (CHECK_FLAG(ai->flags, RIFLG_LSA_ENGAGED)) + ospf_router_info_lsa_schedule(ai, REFRESH_THIS_LSA); + else + ospf_router_info_lsa_schedule(ai, + REORIGINATE_THIS_LSA); + + } } /*------------------------------------------------------------------------* @@ -638,14 +633,22 @@ void ospf_router_info_update_sr(bool enable, struct sr_srgb srgb, uint8_t msd) static void ospf_router_info_ism_change(struct ospf_interface *oi, int old_state) { - /* So far, nothing to do here. */ - return; -} -static void ospf_router_info_nsm_change(struct ospf_neighbor *nbr, - int old_state) -{ - /* So far, nothing to do here. */ + struct ospf_ri_area_info *ai; + + /* Collect area information */ + ai = lookup_by_area(oi->area); + + /* Check if area is not yet registered */ + if (ai != NULL) + return; + + /* Add this new area to the list */ + ai = XCALLOC(MTYPE_OSPF_ROUTER_INFO, sizeof(struct ospf_ri_area_info)); + ai->area = oi->area; + ai->flags = RIFLG_LSA_INACTIVE; + listnode_add(OspfRI.area_info, ai); + return; } @@ -723,7 +726,7 @@ static void ospf_router_info_lsa_body_set(struct stream *s) } /* Create new opaque-LSA. */ -static struct ospf_lsa *ospf_router_info_lsa_new() +static struct ospf_lsa *ospf_router_info_lsa_new(struct ospf_area *area) { struct ospf *top; struct stream *s; @@ -768,8 +771,7 @@ static struct ospf_lsa *ospf_router_info_lsa_new() /* Now, create an OSPF LSA instance. */ new = ospf_lsa_new_and_data(length); - new->area = OspfRI.area; /* Area must be null if the Opaque type is AS - scope, fulfill otherwise */ + new->area = area; if (new->area && new->area->ospf) new->vrf_id = new->area->ospf->vrf_id; @@ -783,36 +785,31 @@ static struct ospf_lsa *ospf_router_info_lsa_new() return new; } -static int ospf_router_info_lsa_originate1(void *arg) +static int ospf_router_info_lsa_originate_as(void *arg) { struct ospf_lsa *new; struct ospf *top; - struct ospf_area *area; int rc = -1; vrf_id_t vrf_id = VRF_DEFAULT; - /* First check if the area is known if flooding scope is Area */ + /* Sanity Check */ if (OspfRI.scope == OSPF_OPAQUE_AREA_LSA) { - area = (struct ospf_area *)arg; - if (area->area_id.s_addr != OspfRI.area_id.s_addr) { - zlog_debug( - "RI -> This is not the Router Information Area. Stop processing"); - return rc; - } - OspfRI.area = area; - if (area->ospf) - vrf_id = area->ospf->vrf_id; + flog_warn( + EC_OSPF_LSA_INSTALL_FAILURE, + "RI (%s): wrong flooding scope AREA instead of AS ?", + __func__); + return rc; } /* Create new Opaque-LSA/ROUTER INFORMATION instance. */ - new = ospf_router_info_lsa_new(); - new->vrf_id = vrf_id; + new = ospf_router_info_lsa_new(NULL); + new->vrf_id = VRF_DEFAULT; + top = (struct ospf *)arg; - /* Get ospf info */ - top = ospf_lookup_by_vrf_id(vrf_id); + /* Check ospf info */ if (top == NULL) { - zlog_debug("%s: ospf instance not found for vrf id %u", - __PRETTY_FUNCTION__, vrf_id); + zlog_debug("RI (%s): ospf instance not found for vrf id %u", + __func__, vrf_id); ospf_lsa_unlock(&new); return rc; } @@ -821,22 +818,86 @@ static int ospf_router_info_lsa_originate1(void *arg) if (ospf_lsa_install(top, NULL /*oi */, new) == NULL) { flog_warn( EC_OSPF_LSA_INSTALL_FAILURE, - "ospf_router_info_lsa_originate1: ospf_lsa_install() ?"); + "RI (%s): ospf_lsa_install() ?", __func__); + ospf_lsa_unlock(&new); + return rc; + } + + /* Update new LSA origination count. */ + top->lsa_originate_count++; + + /* Flood new LSA through AREA or AS. */ + SET_FLAG(OspfRI.as_flags, RIFLG_LSA_ENGAGED); + ospf_flood_through_as(top, NULL /*nbr */, new); + + if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) { + zlog_debug( + "LSA[Type%d:%s]: Originate Opaque-LSA/ROUTER INFORMATION", + new->data->type, inet_ntoa(new->data->id)); + ospf_lsa_header_dump(new->data); + } + + rc = 0; + return rc; +} + +static int ospf_router_info_lsa_originate_area(void *arg) +{ + struct ospf_lsa *new; + struct ospf *top; + struct ospf_ri_area_info *ai = NULL; + int rc = -1; + vrf_id_t vrf_id = VRF_DEFAULT; + + /* Sanity Check */ + if (OspfRI.scope == OSPF_OPAQUE_AS_LSA) { + flog_warn( + EC_OSPF_LSA_INSTALL_FAILURE, + "RI (%s): wrong flooding scope AS instead of AREA ?", + __func__); + return rc; + } + + /* Create new Opaque-LSA/ROUTER INFORMATION instance. */ + ai = lookup_by_area((struct ospf_area *)arg); + if (ai == NULL) { + zlog_debug( + "RI (%s): There is no context for this Router Information. Stop processing", + __func__); + return rc; + } + if (ai->area->ospf) { + vrf_id = ai->area->ospf->vrf_id; + top = ai->area->ospf; + } else { + top = ospf_lookup_by_vrf_id(vrf_id); + } + new = ospf_router_info_lsa_new(ai->area); + new->vrf_id = vrf_id; + + /* Check ospf info */ + if (top == NULL) { + zlog_debug("RI (%s): ospf instance not found for vrf id %u", + __func__, vrf_id); ospf_lsa_unlock(&new); return rc; } - /* Now this Router Info parameter entry has associated LSA. */ - SET_FLAG(OspfRI.flags, RIFLG_LSA_ENGAGED); + /* Install this LSA into LSDB. */ + if (ospf_lsa_install(top, NULL /*oi */, new) == NULL) { + flog_warn( + EC_OSPF_LSA_INSTALL_FAILURE, + "RI (%s): ospf_lsa_install() ?", __func__); + ospf_lsa_unlock(&new); + return rc; + } /* Update new LSA origination count. */ top->lsa_originate_count++; - /* Flood new LSA through AS. */ - if (OspfRI.scope == OSPF_OPAQUE_AS_LSA) - ospf_flood_through_as(top, NULL /*nbr */, new); - else - ospf_flood_through_area(OspfRI.area, NULL /*nbr */, new); + /* Flood new LSA through AREA or AS. */ + SET_FLAG(ai->flags, RIFLG_LSA_ENGAGED); + ospf_flood_through_area(ai->area, NULL /*nbr */, new); if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) { zlog_debug( @@ -852,38 +913,62 @@ static int ospf_router_info_lsa_originate1(void *arg) static int ospf_router_info_lsa_originate(void *arg) { + struct ospf_ri_area_info *ai; int rc = -1; if (!OspfRI.enabled) { - zlog_info( - "ospf_router_info_lsa_originate: ROUTER INFORMATION is disabled now."); + zlog_info("RI (%s): ROUTER INFORMATION is disabled now.", + __func__); rc = 0; /* This is not an error case. */ return rc; } /* Check if Router Information LSA is already engaged */ - if (CHECK_FLAG(OspfRI.flags, RIFLG_LSA_ENGAGED)) { - if (CHECK_FLAG(OspfRI.flags, RIFLG_LSA_FORCED_REFRESH)) { - UNSET_FLAG(OspfRI.flags, RIFLG_LSA_FORCED_REFRESH); - ospf_router_info_lsa_schedule(REFRESH_THIS_LSA); + if (OspfRI.scope == OSPF_OPAQUE_AS_LSA) { + if ((CHECK_FLAG(OspfRI.as_flags, RIFLG_LSA_ENGAGED)) + && (CHECK_FLAG(OspfRI.as_flags, + RIFLG_LSA_FORCED_REFRESH))) { + UNSET_FLAG(OspfRI.as_flags, RIFLG_LSA_FORCED_REFRESH); + ospf_router_info_lsa_schedule(NULL, REFRESH_THIS_LSA); + rc = 0; + return rc; } } else { - if (!is_mandated_params_set(OspfRI)) + ai = lookup_by_area((struct ospf_area *)arg); + if (ai == NULL) { flog_warn( EC_OSPF_LSA, - "ospf_router_info_lsa_originate: lacks mandated ROUTER INFORMATION parameters"); - - /* Ok, let's try to originate an LSA */ - if (ospf_router_info_lsa_originate1(arg) != 0) + "RI (%s): Missing area information", __func__); return rc; + } + if ((CHECK_FLAG(ai->flags, RIFLG_LSA_ENGAGED)) + && (CHECK_FLAG(ai->flags, RIFLG_LSA_FORCED_REFRESH))) { + UNSET_FLAG(ai->flags, RIFLG_LSA_FORCED_REFRESH); + ospf_router_info_lsa_schedule(ai, REFRESH_THIS_LSA); + rc = 0; + return rc; + } } - rc = 0; + /* Router Information is not yet Engaged, check parameters */ + if (!is_mandated_params_set(OspfRI)) + flog_warn( + EC_OSPF_LSA, + "RI (%s): lacks mandated ROUTER INFORMATION parameters", + __func__); + + /* Ok, let's try to originate an LSA */ + if (OspfRI.scope == OSPF_OPAQUE_AS_LSA) + rc = ospf_router_info_lsa_originate_as(arg); + else + rc = ospf_router_info_lsa_originate_area(arg); + return rc; } static struct ospf_lsa *ospf_router_info_lsa_refresh(struct ospf_lsa *lsa) { + struct ospf_ri_area_info *ai = NULL; struct ospf_lsa *new = NULL; struct ospf *top; @@ -893,8 +978,8 @@ static struct ospf_lsa *ospf_router_info_lsa_refresh(struct ospf_lsa *lsa) * status change. * It seems a slip among routers in the routing domain. */ - zlog_info( - "ospf_router_info_lsa_refresh: ROUTER INFORMATION is disabled now."); + zlog_info("RI (%s): ROUTER INFORMATION is disabled now.", + __func__); lsa->data->ls_age = htons(OSPF_LSA_MAXAGE); /* Flush it anyway. */ } @@ -903,37 +988,66 @@ static struct ospf_lsa *ospf_router_info_lsa_refresh(struct ospf_lsa *lsa) if (GET_OPAQUE_ID(ntohl(lsa->data->id.s_addr)) != 0) { flog_warn( EC_OSPF_LSA, - "ospf_router_info_lsa_refresh: Unsupported Router Information ID"); + "RI (%s): Unsupported Router Information ID", + __func__); return NULL; } - /* If the lsa's age reached to MaxAge, start flushing procedure. */ - if (IS_LSA_MAXAGE(lsa)) { - UNSET_FLAG(OspfRI.flags, RIFLG_LSA_ENGAGED); - ospf_opaque_lsa_flush_schedule(lsa); - return NULL; - } - - /* Create new Opaque-LSA/ROUTER INFORMATION instance. */ - new = ospf_router_info_lsa_new(); - new->data->ls_seqnum = lsa_seqnum_increment(lsa); - new->vrf_id = lsa->vrf_id; - - /* Install this LSA into LSDB. */ - /* Given "lsa" will be freed in the next function. */ - top = ospf_lookup_by_vrf_id(lsa->vrf_id); - if (ospf_lsa_install(top, NULL /*oi */, new) == NULL) { - flog_warn(EC_OSPF_LSA_INSTALL_FAILURE, - "ospf_router_info_lsa_refresh: ospf_lsa_install() ?"); - ospf_lsa_unlock(&new); - return new; - } - - /* Flood updated LSA through AS or AREA depending of OspfRI.scope. */ - if (OspfRI.scope == OSPF_OPAQUE_AS_LSA) + /* Process LSA depending of the flooding scope */ + if (OspfRI.scope == OSPF_OPAQUE_AREA_LSA) { + /* Get context AREA context */ + ai = lookup_by_area(lsa->area); + if (ai == NULL) { + flog_warn( + EC_OSPF_LSA, + "RI (%s): No associated Area", __func__); + return NULL; + } + /* Flush LSA, if the lsa's age reached to MaxAge. */ + if (IS_LSA_MAXAGE(lsa)) { + UNSET_FLAG(ai->flags, RIFLG_LSA_ENGAGED); + ospf_opaque_lsa_flush_schedule(lsa); + return NULL; + } + /* Create new Opaque-LSA/ROUTER INFORMATION instance. */ + new = ospf_router_info_lsa_new(ai->area); + new->data->ls_seqnum = lsa_seqnum_increment(lsa); + new->vrf_id = lsa->vrf_id; + /* Install this LSA into LSDB. */ + /* Given "lsa" will be freed in the next function. */ + top = ospf_lookup_by_vrf_id(lsa->vrf_id); + if (ospf_lsa_install(top, NULL /*oi */, new) == NULL) { + flog_warn(EC_OSPF_LSA_INSTALL_FAILURE, + "RI (%s): ospf_lsa_install() ?", __func__); + ospf_lsa_unlock(&new); + return new; + } + /* Flood updated LSA through AREA */ + ospf_flood_through_area(ai->area, NULL /*nbr */, new); + + } else { /* AS Flooding scope */ + /* Flush LSA, if the lsa's age reached to MaxAge. */ + if (IS_LSA_MAXAGE(lsa)) { + UNSET_FLAG(OspfRI.as_flags, RIFLG_LSA_ENGAGED); + ospf_opaque_lsa_flush_schedule(lsa); + return NULL; + } + /* Create new Opaque-LSA/ROUTER INFORMATION instance. */ + new = ospf_router_info_lsa_new(NULL); + new->data->ls_seqnum = lsa_seqnum_increment(lsa); + new->vrf_id = lsa->vrf_id; + /* Install this LSA into LSDB. */ + /* Given "lsa" will be freed in the next function. */ + top = ospf_lookup_by_vrf_id(lsa->vrf_id); + if (ospf_lsa_install(top, NULL /*oi */, new) == NULL) { + flog_warn(EC_OSPF_LSA_INSTALL_FAILURE, + "RI (%s): ospf_lsa_install() ?", __func__); + ospf_lsa_unlock(&new); + return new; + } + /* Flood updated LSA through AS */ ospf_flood_through_as(top, NULL /*nbr */, new); - else - ospf_flood_through_area(OspfRI.area, NULL /*nbr */, new); + } /* Debug logging. */ if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) { @@ -946,7 +1060,8 @@ static struct ospf_lsa *ospf_router_info_lsa_refresh(struct ospf_lsa *lsa) return new; } -static void ospf_router_info_lsa_schedule(enum lsa_opcode opcode) +static void ospf_router_info_lsa_schedule(struct ospf_ri_area_info *ai, + enum lsa_opcode opcode) { struct ospf_lsa lsa; struct lsa_header lsah; @@ -956,28 +1071,44 @@ static void ospf_router_info_lsa_schedule(enum lsa_opcode opcode) memset(&lsa, 0, sizeof(lsa)); memset(&lsah, 0, sizeof(lsah)); - zlog_debug("RI-> LSA schedule %s%s%s", + zlog_debug("RI (%s): LSA schedule %s%s%s", __func__, opcode == REORIGINATE_THIS_LSA ? "Re-Originate" : "", opcode == REFRESH_THIS_LSA ? "Refresh" : "", opcode == FLUSH_THIS_LSA ? "Flush" : ""); - /* Check LSA flags state coherence */ - if (!CHECK_FLAG(OspfRI.flags, RIFLG_LSA_ENGAGED) - && (opcode != REORIGINATE_THIS_LSA)) - return; + /* Check LSA flags state coherence and collect area information */ + if (OspfRI.scope == OSPF_OPAQUE_AREA_LSA) { + if ((ai == NULL) || (ai->area == NULL)) { + flog_warn( + EC_OSPF_LSA, + "RI (%s): Router Info is Area scope flooding but area is not set", + __func__); + return; + } - if (CHECK_FLAG(OspfRI.flags, RIFLG_LSA_ENGAGED) - && (opcode == REORIGINATE_THIS_LSA)) - opcode = REFRESH_THIS_LSA; + if (!CHECK_FLAG(ai->flags, RIFLG_LSA_ENGAGED) + && (opcode != REORIGINATE_THIS_LSA)) + return; - top = ospf_lookup_by_vrf_id(VRF_DEFAULT); - if ((OspfRI.scope == OSPF_OPAQUE_AREA_LSA) && (OspfRI.area == NULL)) { - flog_warn( - EC_OSPF_LSA, - "ospf_router_info_lsa_schedule(): Router Info is Area scope flooding but area is not set"); - OspfRI.area = ospf_area_lookup_by_area_id(top, OspfRI.area_id); + if (CHECK_FLAG(ai->flags, RIFLG_LSA_ENGAGED) + && (opcode == REORIGINATE_THIS_LSA)) + opcode = REFRESH_THIS_LSA; + + lsa.area = ai->area; + top = ai->area->ospf; + } else { + if (!CHECK_FLAG(OspfRI.as_flags, RIFLG_LSA_ENGAGED) + && (opcode != REORIGINATE_THIS_LSA)) + return; + + if (CHECK_FLAG(OspfRI.as_flags, RIFLG_LSA_ENGAGED) + && (opcode == REORIGINATE_THIS_LSA)) + opcode = REFRESH_THIS_LSA; + + top = ospf_lookup_by_vrf_id(VRF_DEFAULT); + lsa.area = NULL; } - lsa.area = OspfRI.area; + lsa.data = &lsah; lsah.type = OspfRI.scope; @@ -989,7 +1120,7 @@ static void ospf_router_info_lsa_schedule(enum lsa_opcode opcode) case REORIGINATE_THIS_LSA: if (OspfRI.scope == OSPF_OPAQUE_AREA_LSA) ospf_opaque_lsa_reoriginate_schedule( - (void *)OspfRI.area, OSPF_OPAQUE_AREA_LSA, + (void *)ai->area, OSPF_OPAQUE_AREA_LSA, OPAQUE_TYPE_ROUTER_INFORMATION_LSA); else ospf_opaque_lsa_reoriginate_schedule( @@ -1000,7 +1131,10 @@ static void ospf_router_info_lsa_schedule(enum lsa_opcode opcode) ospf_opaque_lsa_refresh_schedule(&lsa); break; case FLUSH_THIS_LSA: - UNSET_FLAG(OspfRI.flags, RIFLG_LSA_ENGAGED); + if (OspfRI.scope == OSPF_OPAQUE_AREA_LSA) + UNSET_FLAG(ai->flags, RIFLG_LSA_ENGAGED); + else + UNSET_FLAG(OspfRI.as_flags, RIFLG_LSA_ENGAGED); ospf_opaque_lsa_flush_schedule(&lsa); break; } @@ -1014,7 +1148,7 @@ static int ospf_router_info_lsa_update(struct ospf_lsa *lsa) /* Sanity Check */ if (lsa == NULL) { - flog_warn(EC_OSPF_LSA, "OSPF-RI (%s): Abort! LSA is NULL", + flog_warn(EC_OSPF_LSA, "RI (%s): Abort! LSA is NULL", __func__); return -1; } @@ -1356,8 +1490,7 @@ static void ospf_router_info_config_write_router(struct vty *vty) if (OspfRI.scope == OSPF_OPAQUE_AS_LSA) vty_out(vty, " router-info as\n"); else - vty_out(vty, " router-info area %s\n", - inet_ntoa(OspfRI.area_id)); + vty_out(vty, " router-info area\n"); if (OspfRI.pce_info.enabled) { @@ -1405,43 +1538,53 @@ static void ospf_router_info_config_write_router(struct vty *vty) /*------------------------------------------------------------------------* * Followings are vty command functions. *------------------------------------------------------------------------*/ +/* Simple wrapper schedule RI LSA action in function of the scope */ +static void ospf_router_info_schedule(enum lsa_opcode opcode) +{ + struct listnode *node, *nnode; + struct ospf_ri_area_info *ai; + + if (OspfRI.scope == OSPF_OPAQUE_AS_LSA) { + if (CHECK_FLAG(OspfRI.as_flags, RIFLG_LSA_ENGAGED)) + ospf_router_info_lsa_schedule(NULL, opcode); + else if (opcode == REORIGINATE_THIS_LSA) + ospf_router_info_lsa_schedule(NULL, opcode); + } else { + for (ALL_LIST_ELEMENTS(OspfRI.area_info, node, nnode, ai)) { + if (CHECK_FLAG(ai->flags, RIFLG_LSA_ENGAGED)) + ospf_router_info_lsa_schedule(ai, opcode); + } + } +} DEFUN (router_info, router_info_area_cmd, - "router-info <as|area A.B.C.D>", + "router-info <as|area [A.B.C.D]>", OSPF_RI_STR "Enable the Router Information functionality with AS flooding scope\n" "Enable the Router Information functionality with Area flooding scope\n" - "OSPF area ID in IP format\n") + "OSPF area ID in IP format (deprecated)\n") { - int idx_ipv4 = 2; - char *area = (argc == 3) ? argv[idx_ipv4]->arg : NULL; - + int idx_mode = 1; uint8_t scope; if (OspfRI.enabled) return CMD_SUCCESS; /* Check and get Area value if present */ - if (area) { - if (!inet_aton(area, &OspfRI.area_id)) { - vty_out(vty, "%% specified Area ID %s is invalid\n", - area); - return CMD_WARNING_CONFIG_FAILED; - } - scope = OSPF_OPAQUE_AREA_LSA; - } else { - OspfRI.area_id.s_addr = 0; + if (strncmp(argv[idx_mode]->arg, "as", 2) == 0) scope = OSPF_OPAQUE_AS_LSA; - } + else + scope = OSPF_OPAQUE_AREA_LSA; /* First start to register Router Information callbacks */ - if ((ospf_router_info_register(scope)) != 0) { + if (!OspfRI.registered && (ospf_router_info_register(scope)) != 0) { vty_out(vty, "%% Unable to register Router Information callbacks."); flog_err( EC_OSPF_INIT_FAIL, - "Unable to register Router Information callbacks. Abort!"); + "RI (%s): Unable to register Router Information callbacks. Abort!", + __func__); return CMD_WARNING_CONFIG_FAILED; } @@ -1463,14 +1606,8 @@ DEFUN (router_info, initialize_params(&OspfRI); - /* Refresh RI LSA if already engaged */ - if (CHECK_FLAG(OspfRI.flags, RIFLG_LSA_ENGAGED)) { - zlog_debug("RI-> Refresh LSA following configuration"); - ospf_router_info_lsa_schedule(REFRESH_THIS_LSA); - } else { - zlog_debug("RI-> Initial origination following configuration"); - ospf_router_info_lsa_schedule(REORIGINATE_THIS_LSA); - } + /* Originate or Refresh RI LSA if already engaged */ + ospf_router_info_schedule(REORIGINATE_THIS_LSA); return CMD_SUCCESS; } @@ -1488,8 +1625,7 @@ DEFUN (no_router_info, if (IS_DEBUG_OSPF_EVENT) zlog_debug("RI-> Router Information: ON -> OFF"); - if (CHECK_FLAG(OspfRI.flags, RIFLG_LSA_ENGAGED)) - ospf_router_info_lsa_schedule(FLUSH_THIS_LSA); + ospf_router_info_schedule(FLUSH_THIS_LSA); OspfRI.enabled = false; @@ -1533,8 +1669,7 @@ DEFUN (pce_address, set_pce_address(value, pi); /* Refresh RI LSA if already engaged */ - if (CHECK_FLAG(OspfRI.flags, RIFLG_LSA_ENGAGED)) - ospf_router_info_lsa_schedule(REFRESH_THIS_LSA); + ospf_router_info_schedule(REFRESH_THIS_LSA); } return CMD_SUCCESS; @@ -1552,8 +1687,7 @@ DEFUN (no_pce_address, unset_param(&OspfRI.pce_info.pce_address); /* Refresh RI LSA if already engaged */ - if (CHECK_FLAG(OspfRI.flags, RIFLG_LSA_ENGAGED)) - ospf_router_info_lsa_schedule(REFRESH_THIS_LSA); + ospf_router_info_schedule(REFRESH_THIS_LSA); return CMD_SUCCESS; } @@ -1583,8 +1717,7 @@ DEFUN (pce_path_scope, set_pce_path_scope(scope, pi); /* Refresh RI LSA if already engaged */ - if (CHECK_FLAG(OspfRI.flags, RIFLG_LSA_ENGAGED)) - ospf_router_info_lsa_schedule(REFRESH_THIS_LSA); + ospf_router_info_schedule(REFRESH_THIS_LSA); } return CMD_SUCCESS; @@ -1602,8 +1735,7 @@ DEFUN (no_pce_path_scope, unset_param(&OspfRI.pce_info.pce_address); /* Refresh RI LSA if already engaged */ - if (CHECK_FLAG(OspfRI.flags, RIFLG_LSA_ENGAGED)) - ospf_router_info_lsa_schedule(REFRESH_THIS_LSA); + ospf_router_info_schedule(REFRESH_THIS_LSA); return CMD_SUCCESS; } @@ -1641,8 +1773,7 @@ DEFUN (pce_domain, set_pce_domain(PCE_DOMAIN_TYPE_AS, as, pce); /* Refresh RI LSA if already engaged */ - if (CHECK_FLAG(OspfRI.flags, RIFLG_LSA_ENGAGED)) - ospf_router_info_lsa_schedule(REFRESH_THIS_LSA); + ospf_router_info_schedule(REFRESH_THIS_LSA); return CMD_SUCCESS; } @@ -1671,8 +1802,7 @@ DEFUN (no_pce_domain, unset_pce_domain(PCE_DOMAIN_TYPE_AS, as, pce); /* Refresh RI LSA if already engaged */ - if (CHECK_FLAG(OspfRI.flags, RIFLG_LSA_ENGAGED)) - ospf_router_info_lsa_schedule(REFRESH_THIS_LSA); + ospf_router_info_schedule(REFRESH_THIS_LSA); return CMD_SUCCESS; } @@ -1711,8 +1841,7 @@ DEFUN (pce_neigbhor, set_pce_neighbor(PCE_DOMAIN_TYPE_AS, as, pce); /* Refresh RI LSA if already engaged */ - if (CHECK_FLAG(OspfRI.flags, RIFLG_LSA_ENGAGED)) - ospf_router_info_lsa_schedule(REFRESH_THIS_LSA); + ospf_router_info_schedule(REFRESH_THIS_LSA); return CMD_SUCCESS; } @@ -1741,8 +1870,7 @@ DEFUN (no_pce_neighbor, unset_pce_neighbor(PCE_DOMAIN_TYPE_AS, as, pce); /* Refresh RI LSA if already engaged */ - if (CHECK_FLAG(OspfRI.flags, RIFLG_LSA_ENGAGED)) - ospf_router_info_lsa_schedule(REFRESH_THIS_LSA); + ospf_router_info_schedule(REFRESH_THIS_LSA); return CMD_SUCCESS; } @@ -1773,8 +1901,7 @@ DEFUN (pce_cap_flag, set_pce_cap_flag(cap, pce); /* Refresh RI LSA if already engaged */ - if (CHECK_FLAG(OspfRI.flags, RIFLG_LSA_ENGAGED)) - ospf_router_info_lsa_schedule(REFRESH_THIS_LSA); + ospf_router_info_schedule(REFRESH_THIS_LSA); } return CMD_SUCCESS; @@ -1791,8 +1918,7 @@ DEFUN (no_pce_cap_flag, unset_param(&OspfRI.pce_info.pce_cap_flag); /* Refresh RI LSA if already engaged */ - if (CHECK_FLAG(OspfRI.flags, RIFLG_LSA_ENGAGED)) - ospf_router_info_lsa_schedule(REFRESH_THIS_LSA); + ospf_router_info_schedule(REFRESH_THIS_LSA); return CMD_SUCCESS; } diff --git a/ospfd/ospf_ri.h b/ospfd/ospf_ri.h index 26bcc1b62a..84511ac5e7 100644 --- a/ospfd/ospf_ri.h +++ b/ospfd/ospf_ri.h @@ -170,7 +170,71 @@ struct ri_pce_subtlv_cap_flag { /* Structure to share flooding scope info for Segment Routing */ struct scope_info { uint8_t scope; - struct in_addr area_id; + struct list *areas; +}; + +/* Flags to manage the Router Information LSA. */ +#define RIFLG_LSA_INACTIVE 0x0 +#define RIFLG_LSA_ENGAGED 0x1 +#define RIFLG_LSA_FORCED_REFRESH 0x2 + +/* Store Router Information PCE TLV and SubTLV in network byte order. */ +struct ospf_pce_info { + bool enabled; + struct ri_tlv_pce pce_header; + struct ri_pce_subtlv_address pce_address; + struct ri_pce_subtlv_path_scope pce_scope; + struct list *pce_domain; + struct list *pce_neighbor; + struct ri_pce_subtlv_cap_flag pce_cap_flag; +}; + +/* + * Store Router Information Segment Routing TLV and SubTLV + * in network byte order + */ +struct ospf_ri_sr_info { + bool enabled; + /* Algorithms supported by the node */ + struct ri_sr_tlv_sr_algorithm algo; + /* + * Segment Routing Global Block i.e. label range + * Only one range supported in this code + */ + struct ri_sr_tlv_sid_label_range range; + /* Maximum SID Depth supported by the node */ + struct ri_sr_tlv_node_msd msd; +}; + +/* Store area information to flood LSA per area */ +struct ospf_ri_area_info { + + uint32_t flags; + + /* area pointer if flooding is Type 10 Null if flooding is AS scope */ + struct ospf_area *area; +}; + +/* Following structure are internal use only. */ +struct ospf_router_info { + bool enabled; + + uint8_t registered; + uint8_t scope; + /* LSA flags are only used when scope is AS flooding */ + uint32_t as_flags; + + /* List of area info to flood RI LSA */ + struct list *area_info; + + /* Store Router Information Capabilities LSA */ + struct ri_tlv_router_cap router_cap; + + /* Store PCE capability LSA */ + struct ospf_pce_info pce_info; + + /* Store SR capability LSA */ + struct ospf_ri_sr_info sr_info; }; /* Prototypes. */ diff --git a/ospfd/ospf_te.c b/ospfd/ospf_te.c index 02698d770a..16347f1c5b 100644 --- a/ospfd/ospf_te.c +++ b/ospfd/ospf_te.c @@ -2398,16 +2398,16 @@ DEFUN (no_ospf_mpls_te_inter_as, zlog_debug("MPLS-TE: Inter-AS support OFF"); if ((OspfMplsTE.enabled) && (OspfMplsTE.inter_as != Off)) { - OspfMplsTE.inter_as = Off; /* Flush all Inter-AS LSA */ for (ALL_LIST_ELEMENTS(OspfMplsTE.iflist, node, nnode, lp)) if (IS_INTER_AS(lp->type) && CHECK_FLAG(lp->flags, LPFLG_LSA_ENGAGED)) ospf_mpls_te_lsa_schedule(lp, FLUSH_THIS_LSA); - } - /* Deregister the Callbacks for Inter-AS support */ - ospf_mpls_te_unregister(); + /* Deregister the Callbacks for Inter-AS support */ + ospf_mpls_te_unregister(); + OspfMplsTE.inter_as = Off; + } return CMD_SUCCESS; } diff --git a/ospfd/ospf_zebra.c b/ospfd/ospf_zebra.c index ed19ae4f31..c7bde55cd9 100644 --- a/ospfd/ospf_zebra.c +++ b/ospfd/ospf_zebra.c @@ -1577,7 +1577,7 @@ static void ospf_zebra_connected(struct zclient *zclient) void ospf_zebra_init(struct thread_master *master, unsigned short instance) { /* Allocate zebra structure. */ - zclient = zclient_new_notify(master, &zclient_options_default); + zclient = zclient_new(master, &zclient_options_default); zclient_init(zclient, ZEBRA_ROUTE_OSPF, instance, &ospfd_privs); zclient->zebra_connected = ospf_zebra_connected; zclient->router_id_update = ospf_router_id_update_zebra; diff --git a/pbrd/pbr_zebra.c b/pbrd/pbr_zebra.c index b7391a171a..9db3edacb9 100644 --- a/pbrd/pbr_zebra.c +++ b/pbrd/pbr_zebra.c @@ -391,7 +391,7 @@ void pbr_zebra_init(void) { struct zclient_options opt = { .receive_notify = true }; - zclient = zclient_new_notify(master, &opt); + zclient = zclient_new(master, &opt); zclient_init(zclient, ZEBRA_ROUTE_PBR, 0, &pbr_privs); zclient->zebra_connected = zebra_connected; diff --git a/pimd/pim_zebra.c b/pimd/pim_zebra.c index 23001031e3..3dfc36a0c2 100644 --- a/pimd/pim_zebra.c +++ b/pimd/pim_zebra.c @@ -746,7 +746,7 @@ static void pim_zebra_connected(struct zclient *zclient) void pim_zebra_init(void) { /* Socket for receiving updates from Zebra daemon */ - zclient = zclient_new_notify(master, &zclient_options_default); + zclient = zclient_new(master, &zclient_options_default); zclient->zebra_connected = pim_zebra_connected; zclient->router_id_update = pim_router_id_update_zebra; diff --git a/pimd/pim_zlookup.c b/pimd/pim_zlookup.c index 0e74866117..6b45313081 100644 --- a/pimd/pim_zlookup.c +++ b/pimd/pim_zlookup.c @@ -120,7 +120,7 @@ void zclient_lookup_free(void) void zclient_lookup_new(void) { - zlookup = zclient_new_notify(master, &zclient_options_default); + zlookup = zclient_new(master, &zclient_options_default); if (!zlookup) { flog_err(EC_LIB_ZAPI_SOCKET, "%s: zclient_new() failure", __PRETTY_FUNCTION__); diff --git a/ripd/rip_zebra.c b/ripd/rip_zebra.c index 2a56cd7b1b..20f543a258 100644 --- a/ripd/rip_zebra.c +++ b/ripd/rip_zebra.c @@ -211,7 +211,7 @@ static void rip_zebra_connected(struct zclient *zclient) void rip_zclient_init(struct thread_master *master) { /* Set default value to the zebra client structure. */ - zclient = zclient_new_notify(master, &zclient_options_default); + zclient = zclient_new(master, &zclient_options_default); zclient_init(zclient, ZEBRA_ROUTE_RIP, 0, &ripd_privs); zclient->zebra_connected = rip_zebra_connected; zclient->interface_add = rip_interface_add; diff --git a/ripngd/ripng_zebra.c b/ripngd/ripng_zebra.c index a8cc9ee128..f2b69c85a7 100644 --- a/ripngd/ripng_zebra.c +++ b/ripngd/ripng_zebra.c @@ -414,7 +414,7 @@ static void ripng_zebra_connected(struct zclient *zclient) void zebra_init(struct thread_master *master) { /* Allocate zebra structure. */ - zclient = zclient_new_notify(master, &zclient_options_default); + zclient = zclient_new(master, &zclient_options_default); zclient_init(zclient, ZEBRA_ROUTE_RIPNG, 0, &ripngd_privs); zclient->zebra_connected = ripng_zebra_connected; diff --git a/sharpd/sharp_zebra.c b/sharpd/sharp_zebra.c index 286f320874..12bab73c5e 100644 --- a/sharpd/sharp_zebra.c +++ b/sharpd/sharp_zebra.c @@ -281,7 +281,7 @@ void sharp_zebra_init(void) { struct zclient_options opt = {.receive_notify = true}; - zclient = zclient_new_notify(master, &opt); + zclient = zclient_new(master, &opt); zclient_init(zclient, ZEBRA_ROUTE_SHARP, 0, &sharp_privs); zclient->zebra_connected = zebra_connected; diff --git a/staticd/static_zebra.c b/staticd/static_zebra.c index 4e168e142c..fd4201e562 100644 --- a/staticd/static_zebra.c +++ b/staticd/static_zebra.c @@ -465,7 +465,7 @@ void static_zebra_init(void) { struct zclient_options opt = { .receive_notify = true }; - zclient = zclient_new_notify(master, &opt); + zclient = zclient_new(master, &opt); zclient_init(zclient, ZEBRA_ROUTE_STATIC, 0, &static_privs); zclient->zebra_capabilities = static_zebra_capabilities; diff --git a/tests/.gitignore b/tests/.gitignore index 37cd245de0..49a4b6e470 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -12,6 +12,7 @@ /bgpd/test_peer_attr /isisd/test_fuzz_isis_tlv /isisd/test_fuzz_isis_tlv_tests.h +/isisd/test_isis_lspdb /isisd/test_isis_vertex_queue /lib/cli/test_cli /lib/cli/test_cli_clippy.c diff --git a/tests/bgpd/test_mpath.c b/tests/bgpd/test_mpath.c index f0797827ce..04fbda42eb 100644 --- a/tests/bgpd/test_mpath.c +++ b/tests/bgpd/test_mpath.c @@ -379,7 +379,7 @@ static int global_test_init(void) { qobj_init(); master = thread_master_create(NULL); - zclient = zclient_new_notify(master, &zclient_options_default); + zclient = zclient_new(master, &zclient_options_default); bgp_master_init(master); vrf_init(NULL, NULL, NULL, NULL, NULL); bgp_option_set(BGP_OPT_NO_LISTEN); diff --git a/tests/isisd/test_isis_lspdb.c b/tests/isisd/test_isis_lspdb.c new file mode 100644 index 0000000000..b9c6f2bbb2 --- /dev/null +++ b/tests/isisd/test_isis_lspdb.c @@ -0,0 +1,87 @@ +#include <zebra.h> + +#include "isisd/isis_lsp.c" + +struct thread_master *master; + +int isis_sock_init(struct isis_circuit *circuit); +int isis_sock_init(struct isis_circuit *circuit) +{ + return 0; +} + +struct zebra_privs_t isisd_privs; + +static void test_lsp_build_list_nonzero_ht(void) +{ + uint8_t lsp_id1[8] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00 + }; + uint8_t lsp_id_end[8] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x5f, 0x00 + }; + uint8_t lsp_id2[8] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00 + }; + + struct isis_area *area = calloc(sizeof(*area), 1); + + area->lsp_mtu = 1500; + + dict_t *lspdb = lsp_db_init(); + + struct isis_lsp *lsp1 = lsp_new(area, lsp_id1, 6000, 0, 0, 0, NULL, + ISIS_LEVEL2); + + lsp_insert(lsp1, lspdb); + + struct isis_lsp *lsp2 = lsp_new(area, lsp_id2, 6000, 0, 0, 0, NULL, + ISIS_LEVEL2); + + lsp_insert(lsp2, lspdb); + + struct list *list = list_new(); + + lsp_build_list_nonzero_ht(lsp_id1, lsp_id_end, list, lspdb); + assert(list->count == 1); + assert(listgetdata(listhead(list)) == lsp1); + list_delete_all_node(list); + + lsp_id_end[5] = 0x03; + lsp_id_end[6] = 0x00; + + lsp_build_list_nonzero_ht(lsp_id1, lsp_id_end, list, lspdb); + assert(list->count == 2); + assert(listgetdata(listhead(list)) == lsp1); + assert(listgetdata(listtail(list)) == lsp2); + list_delete_all_node(list); + + memcpy(lsp_id1, lsp_id2, sizeof(lsp_id1)); + + lsp_build_list_nonzero_ht(lsp_id1, lsp_id_end, list, lspdb); + assert(list->count == 1); + assert(listgetdata(listhead(list)) == lsp2); + list_delete_all_node(list); + + lsp_id1[5] = 0x03; + lsp_id_end[5] = 0x04; + + lsp_build_list_nonzero_ht(lsp_id1, lsp_id_end, list, lspdb); + assert(list->count == 0); + list_delete_all_node(list); + + lsp_id1[5] = 0x00; + + lsp_build_list_nonzero_ht(lsp_id1, lsp_id_end, list, lspdb); + assert(list->count == 2); + assert(listgetdata(listhead(list)) == lsp1); + assert(listgetdata(listtail(list)) == lsp2); + list_delete_all_node(list); +} + +int main(int argc, char **argv) +{ + isis = calloc(sizeof(*isis), 1); + test_lsp_build_list_nonzero_ht(); + return 0; +} diff --git a/tests/isisd/test_isis_lspdb.py b/tests/isisd/test_isis_lspdb.py new file mode 100644 index 0000000000..cd0b5345c7 --- /dev/null +++ b/tests/isisd/test_isis_lspdb.py @@ -0,0 +1,6 @@ +import frrtest + +class TestIsisLSPDB(frrtest.TestMultiOut): + program = './test_isis_lspdb' + +TestIsisLSPDB.exit_cleanly() diff --git a/tests/subdir.am b/tests/subdir.am index a4a754b088..7a693ac0f7 100644 --- a/tests/subdir.am +++ b/tests/subdir.am @@ -24,6 +24,7 @@ TESTS_ISISD = else TESTS_ISISD = \ tests/isisd/test_fuzz_isis_tlv \ + tests/isisd/test_isis_lspdb \ tests/isisd/test_isis_vertex_queue \ # end endif @@ -155,6 +156,10 @@ tests_isisd_test_fuzz_isis_tlv_CPPFLAGS = $(TESTS_CPPFLAGS) -I$(top_builddir)/te tests_isisd_test_fuzz_isis_tlv_LDADD = $(ISISD_TEST_LDADD) tests_isisd_test_fuzz_isis_tlv_SOURCES = tests/isisd/test_fuzz_isis_tlv.c nodist_tests_isisd_test_fuzz_isis_tlv_SOURCES = tests/isisd/test_fuzz_isis_tlv_tests.h +tests_isisd_test_isis_lspdb_CFLAGS = $(TESTS_CFLAGS) +tests_isisd_test_isis_lspdb_CPPFLAGS = $(TESTS_CPPFLAGS) +tests_isisd_test_isis_lspdb_LDADD = $(ISISD_TEST_LDADD) +tests_isisd_test_isis_lspdb_SOURCES = tests/isisd/test_isis_lspdb.c tests_isisd_test_isis_vertex_queue_CFLAGS = $(TESTS_CFLAGS) tests_isisd_test_isis_vertex_queue_CPPFLAGS = $(TESTS_CPPFLAGS) tests_isisd_test_isis_vertex_queue_LDADD = $(ISISD_TEST_LDADD) @@ -267,6 +272,7 @@ EXTRA_DIST += \ tests/helpers/python/frrtest.py \ tests/isisd/test_fuzz_isis_tlv.py \ tests/isisd/test_fuzz_isis_tlv_tests.h.gz \ + tests/isisd/test_isis_lspdb.py \ tests/isisd/test_isis_vertex_queue.py \ tests/lib/cli/test_commands.in \ tests/lib/cli/test_commands.py \ diff --git a/tests/test_lblmgr.c b/tests/test_lblmgr.c index 9d1c05436c..e71e680fad 100644 --- a/tests/test_lblmgr.c +++ b/tests/test_lblmgr.c @@ -119,7 +119,7 @@ void init_zclient(struct thread_master *master, char *lm_zserv_path) { frr_zclient_addr(&zclient_addr, &zclient_addr_len, lm_zserv_path); - zclient = zclient_new_notify(master, &zclient_options_default); + zclient = zclient_new(master, &zclient_options_default); /* zclient_init(zclient, ZEBRA_LABEL_MANAGER, 0); */ zclient->sock = -1; zclient->redist_default = ZEBRA_ROUTE_LDP; diff --git a/tools/etc/frr/daemons.conf b/tools/etc/frr/daemons.conf index bd0e370d1e..94221301eb 100644 --- a/tools/etc/frr/daemons.conf +++ b/tools/etc/frr/daemons.conf @@ -24,7 +24,8 @@ fabricd_options=" --daemon -A 127.0.0.1" # The list of daemons to watch is automatically generated by the init script. watchfrr_enable=yes -watchfrr_options=(-d -r /usr/sbin/servicebBfrrbBrestartbB%s -s /usr/sbin/servicebBfrrbBstartbB%s -k /usr/sbin/servicebBfrrbBstopbB%s -b bB) + +watchfrr_options=(-d -r /usr/lib/frr/frrbBrestartbB%s -s /usr/lib/frr/frrbBstartbB%s -k /usr/lib/frr/frrbBstopbB%s -b bB) # If valgrind_enable is 'yes' the frr daemons will be started via valgrind. # The use case for doing so is tracking down memory leaks, etc in frr. diff --git a/tools/frr.in b/tools/frr.in index ee8dc883dc..ec383bc5a0 100755 --- a/tools/frr.in +++ b/tools/frr.in @@ -127,6 +127,7 @@ start() echo -n " $1" fi + ${SSD} \ --start \ --pidfile=`pidfile $1` \ @@ -148,7 +149,6 @@ start() -- \ `eval echo "$""$1""_options"` -n "$2" else - echo -n " $1" if ! check_daemon $1; then echo -n " (binary does not exist)" return; @@ -210,7 +210,6 @@ stop() # Now we have to wait until $DAEMON has _really_ stopped. # if test -n "$PID" && kill -0 $PID 2>/dev/null; then - echo -n " (waiting) ." cnt=0 while kill -0 $PID 2>/dev/null; do cnt=`expr $cnt + 1` @@ -220,10 +219,8 @@ stop() break fi sleep 2 - echo -n "." done fi - echo -n " $inst" rm -f `pidfile $inst` rm -f `vtyfile $inst` @@ -305,7 +302,6 @@ start_watchfrr() # Start if at least one daemon is activated. if [ $found_one -eq 1 ]; then - echo -n "Starting Frr monitor daemon:" start watchfrr echo "." fi @@ -408,8 +404,6 @@ start_prio() wanted_prio=$1 daemon_list=${daemon:-$DAEMONS} - echo -n "Starting Frr daemons (prio:$wanted_prio):" - for prio_i in `seq 1 $wanted_prio`; do for daemon_name in $daemon_list; do eval daemon_prio=\$${daemon_name} @@ -447,7 +441,6 @@ start_prio() eval "file_list_suffix="$V_PATH"/"$daemon_name-*"" for pidfile in $file_list_suffix.pid; do ${SSD} --stop --quiet --oknodo --pidfile "$pidfile" - echo -n "." rm -rf "$pidfile" done for vtyfile in $file_list_suffix.vty; do @@ -459,7 +452,6 @@ start_prio() fi done done - echo "." } check_status() diff --git a/vtysh/vtysh.c b/vtysh/vtysh.c index 35f719fa54..cd78551cb4 100644 --- a/vtysh/vtysh.c +++ b/vtysh/vtysh.c @@ -1458,7 +1458,7 @@ DEFUNSH_HIDDEN(VTYSH_BGPD, address_family_evpn2, address_family_evpn2_cmd, } #endif -DEFUNSH(VTYSH_BGPD, bgp_evpn_vni, bgp_evpn_vni_cmd, "vni (1-16777215)", +DEFUNSH(VTYSH_BGPD, bgp_evpn_vni, bgp_evpn_vni_cmd, "vni " CMD_VNI_RANGE, "VXLAN Network Identifier\n" "VNI number\n") { diff --git a/zebra/if_netlink.c b/zebra/if_netlink.c index 8e459160c6..f4bd193569 100644 --- a/zebra/if_netlink.c +++ b/zebra/if_netlink.c @@ -243,7 +243,8 @@ static enum zebra_link_type netlink_to_zebra_link_type(unsigned int hwt) } } -static void netlink_determine_zebra_iftype(char *kind, zebra_iftype_t *zif_type) +static void netlink_determine_zebra_iftype(const char *kind, + zebra_iftype_t *zif_type) { *zif_type = ZEBRA_IF_OTHER; @@ -262,6 +263,10 @@ static void netlink_determine_zebra_iftype(char *kind, zebra_iftype_t *zif_type) *zif_type = ZEBRA_IF_MACVLAN; else if (strcmp(kind, "veth") == 0) *zif_type = ZEBRA_IF_VETH; + else if (strcmp(kind, "bond") == 0) + *zif_type = ZEBRA_IF_BOND; + else if (strcmp(kind, "bond_slave") == 0) + *zif_type = ZEBRA_IF_BOND_SLAVE; } #define parse_rtattr_nested(tb, max, rta) \ @@ -585,6 +590,7 @@ static int netlink_interface(struct nlmsghdr *h, ns_id_t ns_id, int startup) zebra_slave_iftype_t zif_slave_type = ZEBRA_IF_SLAVE_NONE; ifindex_t bridge_ifindex = IFINDEX_INTERNAL; ifindex_t link_ifindex = IFINDEX_INTERNAL; + ifindex_t bond_ifindex = IFINDEX_INTERNAL; struct zebra_if *zif; zns = zebra_ns_lookup(ns_id); @@ -635,7 +641,10 @@ static int netlink_interface(struct nlmsghdr *h, ns_id_t ns_id, int startup) if (linkinfo[IFLA_INFO_SLAVE_KIND]) slave_kind = RTA_DATA(linkinfo[IFLA_INFO_SLAVE_KIND]); - netlink_determine_zebra_iftype(kind, &zif_type); + if ((slave_kind != NULL) && strcmp(slave_kind, "bond") == 0) + netlink_determine_zebra_iftype("bond_slave", &zif_type); + else + netlink_determine_zebra_iftype(kind, &zif_type); } /* If VRF, create the VRF structure itself. */ @@ -653,6 +662,9 @@ static int netlink_interface(struct nlmsghdr *h, ns_id_t ns_id, int startup) zif_slave_type = ZEBRA_IF_SLAVE_BRIDGE; bridge_ifindex = *(ifindex_t *)RTA_DATA(tb[IFLA_MASTER]); + } else if (slave_kind && (strcmp(slave_kind, "bond") == 0)) { + zif_slave_type = ZEBRA_IF_SLAVE_BOND; + bond_ifindex = *(ifindex_t *)RTA_DATA(tb[IFLA_MASTER]); } else zif_slave_type = ZEBRA_IF_SLAVE_OTHER; } @@ -700,6 +712,8 @@ static int netlink_interface(struct nlmsghdr *h, ns_id_t ns_id, int startup) netlink_interface_update_l2info(ifp, linkinfo[IFLA_INFO_DATA], 1); if (IS_ZEBRA_IF_BRIDGE_SLAVE(ifp)) zebra_l2if_update_bridge_slave(ifp, bridge_ifindex); + else if (IS_ZEBRA_IF_BOND_SLAVE(ifp)) + zebra_l2if_update_bond_slave(ifp, bond_ifindex); return 0; } @@ -1081,6 +1095,7 @@ int netlink_link_change(struct nlmsghdr *h, ns_id_t ns_id, int startup) zebra_iftype_t zif_type = ZEBRA_IF_OTHER; zebra_slave_iftype_t zif_slave_type = ZEBRA_IF_SLAVE_NONE; ifindex_t bridge_ifindex = IFINDEX_INTERNAL; + ifindex_t bond_ifindex = IFINDEX_INTERNAL; ifindex_t link_ifindex = IFINDEX_INTERNAL; @@ -1180,6 +1195,11 @@ int netlink_link_change(struct nlmsghdr *h, ns_id_t ns_id, int startup) zif_slave_type = ZEBRA_IF_SLAVE_BRIDGE; bridge_ifindex = *(ifindex_t *)RTA_DATA(tb[IFLA_MASTER]); + } else if (slave_kind + && (strcmp(slave_kind, "bond") == 0)) { + zif_slave_type = ZEBRA_IF_SLAVE_BOND; + bond_ifindex = + *(ifindex_t *)RTA_DATA(tb[IFLA_MASTER]); } else zif_slave_type = ZEBRA_IF_SLAVE_OTHER; } @@ -1239,6 +1259,8 @@ int netlink_link_change(struct nlmsghdr *h, ns_id_t ns_id, int startup) if (IS_ZEBRA_IF_BRIDGE_SLAVE(ifp)) zebra_l2if_update_bridge_slave(ifp, bridge_ifindex); + else if (IS_ZEBRA_IF_BOND_SLAVE(ifp)) + zebra_l2if_update_bond_slave(ifp, bond_ifindex); } else if (ifp->vrf_id != vrf_id) { /* VRF change for an interface. */ if (IS_ZEBRA_DEBUG_KERNEL) @@ -1250,7 +1272,7 @@ int netlink_link_change(struct nlmsghdr *h, ns_id_t ns_id, int startup) if_handle_vrf_change(ifp, vrf_id); } else { - int was_bridge_slave; + bool was_bridge_slave, was_bond_slave; /* Interface update. */ if (IS_ZEBRA_DEBUG_KERNEL) @@ -1273,6 +1295,7 @@ int netlink_link_change(struct nlmsghdr *h, ns_id_t ns_id, int startup) /* 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); netlink_interface_update_hw_addr(tb, ifp); @@ -1312,6 +1335,8 @@ int netlink_link_change(struct nlmsghdr *h, ns_id_t ns_id, int startup) if (IS_ZEBRA_IF_BRIDGE_SLAVE(ifp) || was_bridge_slave) zebra_l2if_update_bridge_slave(ifp, bridge_ifindex); + else if (IS_ZEBRA_IF_BOND_SLAVE(ifp) || was_bond_slave) + zebra_l2if_update_bond_slave(ifp, bond_ifindex); } } else { /* Delete interface notification from kernel */ diff --git a/zebra/interface.c b/zebra/interface.c index afb08f7012..76e0a09c17 100644 --- a/zebra/interface.c +++ b/zebra/interface.c @@ -1150,6 +1150,15 @@ static const char *zebra_ziftype_2str(zebra_iftype_t zif_type) return "VETH"; break; + case ZEBRA_IF_BOND: + return "bond"; + + case ZEBRA_IF_BOND_SLAVE: + return "bond_slave"; + + case ZEBRA_IF_MACVLAN: + return "macvlan"; + default: return "Unknown"; break; @@ -1279,6 +1288,15 @@ static void if_dump_vty(struct vty *vty, struct interface *ifp) br_slave->bridge_ifindex); } + if (IS_ZEBRA_IF_BOND_SLAVE(ifp)) { + struct zebra_l2info_bondslave *bond_slave; + + bond_slave = &zebra_if->bondslave_info; + if (bond_slave->bond_ifindex != IFINDEX_INTERNAL) + vty_out(vty, " Master (bond) ifindex %u\n", + bond_slave->bond_ifindex); + } + if (zebra_if->link_ifindex != IFINDEX_INTERNAL) { vty_out(vty, " Link ifindex %u", zebra_if->link_ifindex); if (zebra_if->link) diff --git a/zebra/interface.h b/zebra/interface.h index e4c05e8dc4..01dd697772 100644 --- a/zebra/interface.h +++ b/zebra/interface.h @@ -1,3 +1,4 @@ + /* Interface function header. * Copyright (C) 1999 Kunihiro Ishiguro * @@ -192,6 +193,8 @@ typedef enum { ZEBRA_IF_VLAN, /* VLAN sub-interface */ ZEBRA_IF_MACVLAN, /* MAC VLAN interface*/ ZEBRA_IF_VETH, /* VETH interface*/ + ZEBRA_IF_BOND, /* Bond */ + ZEBRA_IF_BOND_SLAVE, /* Bond */ } zebra_iftype_t; /* Zebra "slave" interface type */ @@ -199,6 +202,7 @@ typedef enum { ZEBRA_IF_SLAVE_NONE, /* Not a slave */ ZEBRA_IF_SLAVE_VRF, /* Member of a VRF */ ZEBRA_IF_SLAVE_BRIDGE, /* Member of a bridge */ + ZEBRA_IF_SLAVE_BOND, /* Bond member */ ZEBRA_IF_SLAVE_OTHER, /* Something else - e.g., bond slave */ } zebra_slave_iftype_t; @@ -268,6 +272,8 @@ struct zebra_if { */ struct zebra_l2info_brslave brslave_info; + struct zebra_l2info_bondslave bondslave_info; + /* Link fields - for sub-interfaces. */ ifindex_t link_ifindex; struct interface *link; @@ -324,6 +330,10 @@ static inline void zebra_if_set_ziftype(struct interface *ifp, #define IS_ZEBRA_IF_VRF_SLAVE(ifp) \ (((struct zebra_if *)(ifp->info))->zif_slave_type == ZEBRA_IF_SLAVE_VRF) +#define IS_ZEBRA_IF_BOND_SLAVE(ifp) \ + (((struct zebra_if *)(ifp->info))->zif_slave_type \ + == ZEBRA_IF_SLAVE_BOND) + extern void zebra_if_init(void); extern struct interface *if_lookup_by_index_per_ns(struct zebra_ns *, uint32_t); diff --git a/zebra/label_manager.c b/zebra/label_manager.c index 8afb1a0b79..bfad8ea643 100644 --- a/zebra/label_manager.c +++ b/zebra/label_manager.c @@ -318,7 +318,7 @@ static void lm_zclient_init(char *lm_zserv_path) lm_zserv_path); /* Set default values. */ - zclient = zclient_new_notify(zebrad.master, &zclient_options_default); + zclient = zclient_new(zebrad.master, &zclient_options_default); zclient->privs = &zserv_privs; zclient->sock = -1; zclient->t_connect = NULL; diff --git a/zebra/zebra_l2.c b/zebra/zebra_l2.c index 529fc48edf..f4b2fe4794 100644 --- a/zebra/zebra_l2.c +++ b/zebra/zebra_l2.c @@ -99,6 +99,23 @@ void zebra_l2_unmap_slave_from_bridge(struct zebra_l2info_brslave *br_slave) br_slave->br_if = NULL; } +void zebra_l2_map_slave_to_bond(struct zebra_l2info_bondslave *bond_slave) +{ + struct interface *bond_if; + + /* TODO: Handle change of master */ + bond_if = if_lookup_by_index_per_ns(zebra_ns_lookup(NS_DEFAULT), + bond_slave->bond_ifindex); + if (bond_if) + bond_slave->bond_if = bond_if; +} + +void zebra_l2_unmap_slave_from_bond(struct zebra_l2info_bondslave *bond_slave) +{ + if (bond_slave != NULL) + bond_slave->bond_if = NULL; +} + /* * Handle Bridge interface add or update. Update relevant info, * map slaves (if any) to the bridge. @@ -238,3 +255,24 @@ void zebra_l2if_update_bridge_slave(struct interface *ifp, zebra_l2_unmap_slave_from_bridge(&zif->brslave_info); } } + +void zebra_l2if_update_bond_slave(struct interface *ifp, ifindex_t bond_ifindex) +{ + struct zebra_if *zif; + ifindex_t old_bond_ifindex; + + zif = ifp->info; + assert(zif); + + old_bond_ifindex = zif->bondslave_info.bond_ifindex; + if (old_bond_ifindex == bond_ifindex) + return; + + zif->bondslave_info.bond_ifindex = bond_ifindex; + + /* Set up or remove link with master */ + if (bond_ifindex != IFINDEX_INTERNAL) + zebra_l2_map_slave_to_bond(&zif->bondslave_info); + else if (old_bond_ifindex != IFINDEX_INTERNAL) + zebra_l2_unmap_slave_from_bond(&zif->bondslave_info); +} diff --git a/zebra/zebra_l2.h b/zebra/zebra_l2.h index db6cb0e53a..68c9d4a7a1 100644 --- a/zebra/zebra_l2.h +++ b/zebra/zebra_l2.h @@ -52,6 +52,11 @@ struct zebra_l2info_vxlan { vlanid_t access_vlan; /* Access VLAN - for VLAN-aware bridge. */ }; +struct zebra_l2info_bondslave { + ifindex_t bond_ifindex; /* Bridge Master */ + struct interface *bond_if; /* Pointer to master */ +}; + union zebra_l2if_info { struct zebra_l2info_bridge br; struct zebra_l2info_vlan vl; @@ -70,6 +75,10 @@ union zebra_l2if_info { extern void zebra_l2_map_slave_to_bridge(struct zebra_l2info_brslave *br_slave); extern void zebra_l2_unmap_slave_from_bridge(struct zebra_l2info_brslave *br_slave); +extern void +zebra_l2_map_slave_to_bond(struct zebra_l2info_bondslave *bond_slave); +extern void +zebra_l2_unmap_slave_from_bond(struct zebra_l2info_bondslave *bond_slave); extern void zebra_l2_bridge_add_update(struct interface *ifp, struct zebra_l2info_bridge *bridge_info, int add); @@ -85,4 +94,6 @@ extern void zebra_l2_vxlanif_del(struct interface *ifp); extern void zebra_l2if_update_bridge_slave(struct interface *ifp, ifindex_t bridge_ifindex); +extern void zebra_l2if_update_bond_slave(struct interface *ifp, + ifindex_t bond_ifindex); #endif /* _ZEBRA_L2_H */ diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c index d55467c727..8285392527 100644 --- a/zebra/zebra_rib.c +++ b/zebra/zebra_rib.c @@ -358,8 +358,6 @@ static void nexthop_set_resolved(afi_t afi, const struct nexthop *newhop, if (newhop->ifindex) { resolved_hop->type = NEXTHOP_TYPE_IPV4_IFINDEX; resolved_hop->ifindex = newhop->ifindex; - if (newhop->flags & NEXTHOP_FLAG_ONLINK) - resolved_hop->flags |= NEXTHOP_FLAG_ONLINK; } break; case NEXTHOP_TYPE_IPV6: @@ -398,6 +396,9 @@ static void nexthop_set_resolved(afi_t afi, const struct nexthop *newhop, break; } + if (newhop->flags & NEXTHOP_FLAG_ONLINK) + resolved_hop->flags |= NEXTHOP_FLAG_ONLINK; + /* Copy labels of the resolved route */ if (newhop->nh_label) nexthop_add_labels(resolved_hop, newhop->nh_label_type, diff --git a/zebra/zebra_vty.c b/zebra/zebra_vty.c index 4fff376377..263cb3d22c 100644 --- a/zebra/zebra_vty.c +++ b/zebra/zebra_vty.c @@ -68,9 +68,6 @@ static void vty_show_ip_route_summary(struct vty *vty, static void vty_show_ip_route_summary_prefix(struct vty *vty, struct route_table *table); -/* VNI range as per RFC 7432 */ -#define CMD_VNI_RANGE "(1-16777215)" - DEFUN (ip_multicast_mode, ip_multicast_mode_cmd, "ip multicast rpf-lookup-mode <urib-only|mrib-only|mrib-then-urib|lower-distance|longer-prefix>", diff --git a/zebra/zebra_vxlan.c b/zebra/zebra_vxlan.c index 0bc1ea50bb..d372d3e832 100644 --- a/zebra/zebra_vxlan.c +++ b/zebra/zebra_vxlan.c @@ -148,8 +148,7 @@ static void zvni_mac_del_all(zebra_vni_t *zvni, int uninstall, int upd_client, static zebra_mac_t *zvni_mac_lookup(zebra_vni_t *zvni, struct ethaddr *macaddr); static int zvni_mac_send_add_to_client(vni_t vni, struct ethaddr *macaddr, uint8_t flags, uint32_t seq); -static int zvni_mac_send_del_to_client(vni_t vni, struct ethaddr *macaddr, - uint8_t flags); +static int zvni_mac_send_del_to_client(vni_t vni, struct ethaddr *macaddr); static zebra_vni_t *zvni_map_vlan(struct interface *ifp, struct interface *br_if, vlanid_t vid); static int zvni_mac_install(zebra_vni_t *zvni, zebra_mac_t *mac); @@ -2305,6 +2304,7 @@ static int zvni_remote_neigh_update(zebra_vni_t *zvni, UNSET_FLAG(n->flags, ZEBRA_NEIGH_LOCAL); SET_FLAG(n->flags, ZEBRA_NEIGH_REMOTE); + ZEBRA_NEIGH_SET_ACTIVE(n); n->r_vtep_ip = zmac->fwd_info.r_vtep_ip; } @@ -2407,7 +2407,7 @@ static void zvni_mac_del_hash_entry(struct hash_backet *backet, void *arg) &wctx->r_vtep_ip))) { if (wctx->upd_client && (mac->flags & ZEBRA_MAC_LOCAL)) { zvni_mac_send_del_to_client(wctx->zvni->vni, - &mac->macaddr, mac->flags); + &mac->macaddr); } if (wctx->uninstall) @@ -2494,18 +2494,10 @@ static int zvni_mac_send_add_to_client(vni_t vni, struct ethaddr *macaddr, /* * Inform BGP about local MAC deletion. */ -static int zvni_mac_send_del_to_client(vni_t vni, struct ethaddr *macaddr, - uint8_t mac_flags) +static int zvni_mac_send_del_to_client(vni_t vni, struct ethaddr *macaddr) { - uint8_t flags = 0; - - if (CHECK_FLAG(mac_flags, ZEBRA_MAC_STICKY)) - SET_FLAG(flags, ZEBRA_MACIP_TYPE_STICKY); - if (CHECK_FLAG(mac_flags, ZEBRA_MAC_DEF_GW)) - SET_FLAG(flags, ZEBRA_MACIP_TYPE_GW); - - return zvni_macip_send_msg_to_client(vni, macaddr, NULL, flags, - 0, ZEBRA_MACIP_DEL); + return zvni_macip_send_msg_to_client(vni, macaddr, NULL, 0 /* flags */, + 0 /* seq */, ZEBRA_MACIP_DEL); } /* @@ -4304,6 +4296,10 @@ static void process_remote_macip_add(vni_t vni, } } + /* Remove local MAC from BGP. */ + if (CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL)) + zvni_mac_send_del_to_client(zvni->vni, macaddr); + /* Set "auto" and "remote" forwarding info. */ UNSET_FLAG(mac->flags, ZEBRA_MAC_LOCAL); memset(&mac->fwd_info, 0, sizeof(mac->fwd_info)); @@ -4324,6 +4320,7 @@ static void process_remote_macip_add(vni_t vni, /* Install the entry. */ zvni_mac_install(zvni, mac); + } /* Update seq number. */ @@ -4522,6 +4519,13 @@ static void process_remote_macip_del(vni_t vni, } else { if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)) { zvni_process_neigh_on_remote_mac_del(zvni, mac); + /* + * the remote sequence number in the auto mac entry + * needs to be reset to 0 as the mac entry may have + * been removed on all VTEPs (including + * the originating one) + */ + mac->rem_seq = 0; /* If all remote neighbors referencing a remote MAC * go away, we need to uninstall the MAC. @@ -5730,7 +5734,7 @@ int zebra_vxlan_check_del_local_mac(struct interface *ifp, ifp->ifindex, vni); /* Remove MAC from BGP. */ - zvni_mac_send_del_to_client(zvni->vni, macaddr, mac->flags); + zvni_mac_send_del_to_client(zvni->vni, macaddr); /* * If there are no neigh associated with the mac delete the mac @@ -5841,7 +5845,7 @@ int zebra_vxlan_local_mac_del(struct interface *ifp, struct interface *br_if, zvni_process_neigh_on_local_mac_del(zvni, mac); /* Remove MAC from BGP. */ - zvni_mac_send_del_to_client(zvni->vni, macaddr, mac->flags); + zvni_mac_send_del_to_client(zvni->vni, macaddr); /* * If there are no neigh associated with the mac delete the mac |
