diff options
54 files changed, 853 insertions, 604 deletions
diff --git a/babeld/babel_zebra.c b/babeld/babel_zebra.c index 8dea1431e..e909f8ea7 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 a5fae3383..f9c7c16fb 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 c91a2ab6b..cff050a9e 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 29f9f64cc..aa5eabead 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 8aa35eddf..1f0cfd6e2 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 385716970..d4204126e 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 2ef792e12..1cb7e4c5e 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 a407ffba4..8ae74a008 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 60a4e994c..f7c417538 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 45136cf45..c57cd3815 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 50b790eb1..62f977eee 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 c04fe6903..e14b0f39e 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 97d520eda..a43cf1f6a 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 6782c539e..3a6e7883f 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-libyang.rst b/doc/developer/building-libyang.rst index 9757ad454..005b6ba78 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/user/installation.rst b/doc/user/installation.rst index b7f0712a1..0a8cef53e 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 diff --git a/doc/user/ospfd.rst b/doc/user/ospfd.rst index e84313639..b6a7cd5de 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/eigrpd/eigrp_zebra.c b/eigrpd/eigrp_zebra.c index 3a3d6aae1..29bd23b51 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 bb090f42e..f71973afe 100644 --- a/isisd/isis_lsp.c +++ b/isisd/isis_lsp.c @@ -578,29 +578,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; + for (dnode_t *curr = dict_lower_bound(lspdb, start_id); + curr; curr = dict_next(lspdb, curr)) { + struct isis_lsp *lsp = curr->dict_data; - first = dict_lower_bound(lspdb, start_id); - if (!first) - return; - - last = dict_upper_bound(lspdb, stop_id); - - 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) @@ -1361,7 +1349,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 +1987,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 33d8a0f77..101bd57cc 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 54bdbf3eb..ce45ba65e 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 51b359aad..fe9abff93 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 4f74d9304..2aa96546e 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 c8b775cb8..9dc567735 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 873ecdda9..11514fd5e 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 45a9f7be9..b879326d7 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 97ebb0811..07fe512a3 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 e7b187f3b..dae00bbce 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_zebra.c b/ospf6d/ospf6_zebra.c index c968b35d9..5db9b529e 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 1332104b0..c4dc0136e 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 50c6f33ec..861de64c2 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 bef16761f..72f6dbe08 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 26bcc1b62..84511ac5e 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 02698d770..16347f1c5 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 ed19ae4f3..c7bde55cd 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 b7391a171..9db3edacb 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 23001031e..3dfc36a0c 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 0e7486611..6b4531308 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 2a56cd7b1..20f543a25 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 a8cc9ee12..f2b69c85a 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 286f32087..12bab73c5 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 4e168e142..fd4201e56 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 37cd245de..49a4b6e47 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 f0797827c..04fbda42e 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 000000000..b9c6f2bbb --- /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 000000000..cd0b5345c --- /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 a4a754b08..7a693ac0f 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 9d1c05436..e71e680fa 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 bd0e370d1..94221301e 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 ee8dc883d..ec383bc5a 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 35f719fa5..cd78551cb 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/label_manager.c b/zebra/label_manager.c index 8afb1a0b7..bfad8ea64 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_vty.c b/zebra/zebra_vty.c index 4fff37637..263cb3d22 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 0bc1ea50b..d372d3e83 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 |