diff options
-rw-r--r-- | babeld/.gitignore | 1 | ||||
-rw-r--r-- | babeld/babel_interface.c | 209 | ||||
-rw-r--r-- | babeld/babeld.c | 38 | ||||
-rw-r--r-- | babeld/subdir.am | 4 | ||||
-rw-r--r-- | bgpd/bgp_attr.c | 21 | ||||
-rw-r--r-- | bgpd/bgp_attr.h | 2 | ||||
-rw-r--r-- | bgpd/bgp_damp.c | 3 | ||||
-rw-r--r-- | bgpd/bgp_evpn.c | 7 | ||||
-rw-r--r-- | bgpd/bgp_route.c | 8 | ||||
-rw-r--r-- | bgpd/bgp_routemap.c | 3 | ||||
-rw-r--r-- | bgpd/bgp_vty.c | 30 | ||||
-rw-r--r-- | eigrpd/eigrp_interface.c | 3 | ||||
-rw-r--r-- | isisd/isis_nb.c | 60 | ||||
-rw-r--r-- | isisd/isis_nb.h | 30 | ||||
-rw-r--r-- | isisd/isis_nb_state.c | 222 | ||||
-rw-r--r-- | isisd/isis_spf.c | 6 | ||||
-rw-r--r-- | ldpd/logmsg.c | 14 | ||||
-rw-r--r-- | lib/bfd.c | 95 | ||||
-rw-r--r-- | lib/bfd.h | 7 | ||||
-rw-r--r-- | lib/filter_cli.c | 64 | ||||
-rw-r--r-- | lib/network.c | 21 | ||||
-rw-r--r-- | lib/network.h | 18 | ||||
-rw-r--r-- | ospf6d/ospf6_message.c | 3 | ||||
-rw-r--r-- | ospfd/ospf_interface.c | 3 | ||||
-rw-r--r-- | ospfd/ospf_vty.c | 36 | ||||
-rw-r--r-- | pimd/mtracebis_netlink.c | 2 | ||||
-rw-r--r-- | staticd/static_zebra.c | 3 | ||||
-rw-r--r-- | vtysh/subdir.am | 1 | ||||
-rw-r--r-- | yang/frr-isisd.yang | 73 | ||||
-rw-r--r-- | zebra/rt_netlink.c | 2 | ||||
-rw-r--r-- | zebra/rt_netlink.h | 3 | ||||
-rw-r--r-- | zebra/zebra_fpm_netlink.c | 9 | ||||
-rw-r--r-- | zebra/zebra_netns_id.c | 3 |
33 files changed, 700 insertions, 304 deletions
diff --git a/babeld/.gitignore b/babeld/.gitignore index 71ef6786c..abb4d9321 100644 --- a/babeld/.gitignore +++ b/babeld/.gitignore @@ -5,3 +5,4 @@ !Makefile !subdir.am !.gitignore +*_clippy.c diff --git a/babeld/babel_interface.c b/babeld/babel_interface.c index 00fb58e57..cc5089801 100644 --- a/babeld/babel_interface.c +++ b/babeld/babel_interface.c @@ -42,6 +42,10 @@ THE SOFTWARE. #include "xroute.h" #include "babel_errors.h" +#ifndef VTYSH_EXTRACT_PL +#include "babeld/babel_interface_clippy.c" +#endif + DEFINE_MTYPE_STATIC(BABELD, BABEL_IF, "Babel Interface"); #define IS_ENABLE(ifp) (babel_enable_if_lookup(ifp->name) >= 0) @@ -307,9 +311,10 @@ babel_set_wired_internal(babel_interface_nfo *babel_ifp, int wired) } /* [Interface Command] Tell the interface is wire. */ -DEFUN (babel_set_wired, +DEFPY (babel_set_wired, babel_set_wired_cmd, - "babel wired", + "[no] babel wired", + NO_STR "Babel interface commands\n" "Enable wired optimizations\n") { @@ -319,14 +324,15 @@ DEFUN (babel_set_wired, babel_ifp = babel_get_if_nfo(ifp); assert (babel_ifp != NULL); - babel_set_wired_internal(babel_ifp, 1); + babel_set_wired_internal(babel_ifp, no ? 0 : 1); return CMD_SUCCESS; } /* [Interface Command] Tell the interface is wireless (default). */ -DEFUN (babel_set_wireless, +DEFPY (babel_set_wireless, babel_set_wireless_cmd, - "babel wireless", + "[no] babel wireless", + NO_STR "Babel interface commands\n" "Disable wired optimizations (assume wireless)\n") { @@ -336,34 +342,17 @@ DEFUN (babel_set_wireless, babel_ifp = babel_get_if_nfo(ifp); assert (babel_ifp != NULL); - babel_set_wired_internal(babel_ifp, 0); + babel_set_wired_internal(babel_ifp, no ? 1 : 0); return CMD_SUCCESS; } /* [Interface Command] Enable split horizon. */ -DEFUN (babel_split_horizon, +DEFPY (babel_split_horizon, babel_split_horizon_cmd, - "babel split-horizon", - "Babel interface commands\n" - "Enable split horizon processing\n") -{ - VTY_DECLVAR_CONTEXT(interface, ifp); - babel_interface_nfo *babel_ifp; - - babel_ifp = babel_get_if_nfo(ifp); - - assert (babel_ifp != NULL); - babel_ifp->flags |= BABEL_IF_SPLIT_HORIZON; - return CMD_SUCCESS; -} - -/* [Interface Command] Disable split horizon (default). */ -DEFUN (no_babel_split_horizon, - no_babel_split_horizon_cmd, - "no babel split-horizon", + "[no] babel split-horizon", NO_STR "Babel interface commands\n" - "Disable split horizon processing\n") + "Enable split horizon processing\n") { VTY_DECLVAR_CONTEXT(interface, ifp); babel_interface_nfo *babel_ifp; @@ -371,213 +360,180 @@ DEFUN (no_babel_split_horizon, babel_ifp = babel_get_if_nfo(ifp); assert (babel_ifp != NULL); - babel_ifp->flags &= ~BABEL_IF_SPLIT_HORIZON; + if (!no) + SET_FLAG(babel_ifp->flags, BABEL_IF_SPLIT_HORIZON); + else + UNSET_FLAG(babel_ifp->flags, BABEL_IF_SPLIT_HORIZON); return CMD_SUCCESS; } /* [Interface Command]. */ -DEFUN (babel_set_hello_interval, +DEFPY (babel_set_hello_interval, babel_set_hello_interval_cmd, - "babel hello-interval (20-655340)", + "[no] babel hello-interval (20-655340)", + NO_STR "Babel interface commands\n" "Time between scheduled hellos\n" "Milliseconds\n") { VTY_DECLVAR_CONTEXT(interface, ifp); babel_interface_nfo *babel_ifp; - int interval; - - interval = strtoul(argv[2]->arg, NULL, 10); babel_ifp = babel_get_if_nfo(ifp); assert (babel_ifp != NULL); - babel_ifp->hello_interval = interval; + babel_ifp->hello_interval = no ? + BABEL_DEFAULT_HELLO_INTERVAL : hello_interval; return CMD_SUCCESS; } /* [Interface Command]. */ -DEFUN (babel_set_update_interval, +DEFPY (babel_set_update_interval, babel_set_update_interval_cmd, - "babel update-interval (20-655340)", + "[no] babel update-interval (20-655340)", + NO_STR "Babel interface commands\n" "Time between scheduled updates\n" "Milliseconds\n") { VTY_DECLVAR_CONTEXT(interface, ifp); babel_interface_nfo *babel_ifp; - int interval; - - interval = strtoul(argv[2]->arg, NULL, 10); babel_ifp = babel_get_if_nfo(ifp); assert (babel_ifp != NULL); - babel_ifp->update_interval = interval; + babel_ifp->update_interval = no ? + BABEL_DEFAULT_UPDATE_INTERVAL : update_interval; return CMD_SUCCESS; } -DEFUN (babel_set_rxcost, +DEFPY (babel_set_rxcost, babel_set_rxcost_cmd, - "babel rxcost (1-65534)", + "[no] babel rxcost (1-65534)", + NO_STR "Babel interface commands\n" "Rxcost multiplier\n" "Units\n") { VTY_DECLVAR_CONTEXT(interface, ifp); babel_interface_nfo *babel_ifp; - int rxcost; - - rxcost = strtoul(argv[2]->arg, NULL, 10); babel_ifp = babel_get_if_nfo(ifp); assert (babel_ifp != NULL); + if (no) + rxcost = CHECK_FLAG(babel_ifp->flags, BABEL_IF_WIRED) ? + BABEL_DEFAULT_RXCOST_WIRED : BABEL_DEFAULT_RXCOST_WIRELESS; + babel_ifp->cost = rxcost; return CMD_SUCCESS; } -DEFUN (babel_set_rtt_decay, +DEFPY (babel_set_rtt_decay, babel_set_rtt_decay_cmd, - "babel rtt-decay (1-256)", + "[no] babel rtt-decay (1-256)", + NO_STR "Babel interface commands\n" "Decay factor for exponential moving average of RTT samples\n" "Units of 1/256\n") { VTY_DECLVAR_CONTEXT(interface, ifp); babel_interface_nfo *babel_ifp; - int decay; - - decay = strtoul(argv[2]->arg, NULL, 10); babel_ifp = babel_get_if_nfo(ifp); assert (babel_ifp != NULL); - babel_ifp->rtt_decay = decay; + babel_ifp->rtt_decay = no ? BABEL_DEFAULT_RTT_DECAY : rtt_decay; return CMD_SUCCESS; } -DEFUN (babel_set_rtt_min, +DEFPY (babel_set_rtt_min, babel_set_rtt_min_cmd, - "babel rtt-min (1-65535)", + "[no] babel rtt-min (1-65535)", + NO_STR "Babel interface commands\n" "Minimum RTT starting for increasing cost\n" "Milliseconds\n") { VTY_DECLVAR_CONTEXT(interface, ifp); babel_interface_nfo *babel_ifp; - int rtt; - - rtt = strtoul(argv[2]->arg, NULL, 10); babel_ifp = babel_get_if_nfo(ifp); assert (babel_ifp != NULL); /* The value is entered in milliseconds but stored as microseconds. */ - babel_ifp->rtt_min = rtt * 1000; + babel_ifp->rtt_min = no ? BABEL_DEFAULT_RTT_MIN : rtt_min * 1000; return CMD_SUCCESS; } -DEFUN (babel_set_rtt_max, +DEFPY (babel_set_rtt_max, babel_set_rtt_max_cmd, - "babel rtt-max (1-65535)", + "[no] babel rtt-max (1-65535)", + NO_STR "Babel interface commands\n" "Maximum RTT\n" "Milliseconds\n") { VTY_DECLVAR_CONTEXT(interface, ifp); babel_interface_nfo *babel_ifp; - int rtt; - - rtt = strtoul(argv[2]->arg, NULL, 10); babel_ifp = babel_get_if_nfo(ifp); assert (babel_ifp != NULL); /* The value is entered in milliseconds but stored as microseconds. */ - babel_ifp->rtt_max = rtt * 1000; + babel_ifp->rtt_max = no ? BABEL_DEFAULT_RTT_MAX : rtt_max * 1000; return CMD_SUCCESS; } -DEFUN (babel_set_max_rtt_penalty, +DEFPY (babel_set_max_rtt_penalty, babel_set_max_rtt_penalty_cmd, - "babel max-rtt-penalty (0-65535)", + "[no] babel max-rtt-penalty (0-65535)", + NO_STR "Babel interface commands\n" "Maximum additional cost due to RTT\n" "Milliseconds\n") { VTY_DECLVAR_CONTEXT(interface, ifp); babel_interface_nfo *babel_ifp; - int penalty; - - penalty = strtoul(argv[2]->arg, NULL, 10); babel_ifp = babel_get_if_nfo(ifp); assert (babel_ifp != NULL); - babel_ifp->max_rtt_penalty = penalty; + babel_ifp->max_rtt_penalty = no ? + BABEL_DEFAULT_MAX_RTT_PENALTY : max_rtt_penalty; return CMD_SUCCESS; } -DEFUN (babel_set_enable_timestamps, +DEFPY (babel_set_enable_timestamps, babel_set_enable_timestamps_cmd, - "babel enable-timestamps", - "Babel interface commands\n" - "Enable timestamps\n") -{ - VTY_DECLVAR_CONTEXT(interface, ifp); - babel_interface_nfo *babel_ifp; - - babel_ifp = babel_get_if_nfo(ifp); - assert (babel_ifp != NULL); - - babel_ifp->flags |= BABEL_IF_TIMESTAMPS; - return CMD_SUCCESS; -} - -DEFUN (no_babel_set_enable_timestamps, - no_babel_set_enable_timestamps_cmd, - "no babel enable-timestamps", + "[no] babel enable-timestamps", NO_STR "Babel interface commands\n" - "Disable timestamps\n") + "Enable timestamps\n") { VTY_DECLVAR_CONTEXT(interface, ifp); babel_interface_nfo *babel_ifp; babel_ifp = babel_get_if_nfo(ifp); assert (babel_ifp != NULL); - - babel_ifp->flags &= ~BABEL_IF_TIMESTAMPS; + if (!no) + SET_FLAG(babel_ifp->flags, BABEL_IF_TIMESTAMPS); + else + UNSET_FLAG(babel_ifp->flags, BABEL_IF_TIMESTAMPS); return CMD_SUCCESS; } -DEFUN (babel_set_channel, +DEFPY (babel_set_channel, babel_set_channel_cmd, - "babel channel (1-254)", - "Babel interface commands\n" - "Channel number for diversity routing\n" - "Number\n") -{ - VTY_DECLVAR_CONTEXT(interface, ifp); - babel_interface_nfo *babel_ifp; - int channel; - - channel = strtoul(argv[2]->arg, NULL, 10); - - babel_ifp = babel_get_if_nfo(ifp); - assert (babel_ifp != NULL); - - babel_ifp->channel = channel; - return CMD_SUCCESS; -} - -DEFUN (babel_set_channel_interfering, - babel_set_channel_interfering_cmd, - "babel channel interfering", + "[no] babel channel <(1-254)$ch|interfering$interfering|" + "noninterfering$noninterfering>", + NO_STR "Babel interface commands\n" "Channel number for diversity routing\n" - "Mark channel as interfering\n") + "Number\n" + "Mark channel as interfering\n" + "Mark channel as noninterfering\n" + ) { VTY_DECLVAR_CONTEXT(interface, ifp); babel_interface_nfo *babel_ifp; @@ -585,24 +541,15 @@ DEFUN (babel_set_channel_interfering, babel_ifp = babel_get_if_nfo(ifp); assert (babel_ifp != NULL); - babel_ifp->channel = BABEL_IF_CHANNEL_INTERFERING; - return CMD_SUCCESS; -} - -DEFUN (babel_set_channel_noninterfering, - babel_set_channel_noninterfering_cmd, - "babel channel noninterfering", - "Babel interface commands\n" - "Channel number for diversity routing\n" - "Mark channel as noninterfering\n") -{ - VTY_DECLVAR_CONTEXT(interface, ifp); - babel_interface_nfo *babel_ifp; - - babel_ifp = babel_get_if_nfo(ifp); - assert (babel_ifp != NULL); + if (no) + ch = CHECK_FLAG(babel_ifp->flags, BABEL_IF_WIRED) ? + BABEL_IF_CHANNEL_NONINTERFERING : BABEL_IF_CHANNEL_INTERFERING; + else if (interfering) + ch = BABEL_IF_CHANNEL_INTERFERING; + else if (noninterfering) + ch = BABEL_IF_CHANNEL_NONINTERFERING; - babel_ifp->channel = BABEL_IF_CHANNEL_NONINTERFERING; + babel_ifp->channel = ch; return CMD_SUCCESS; } @@ -1239,7 +1186,6 @@ babel_if_init(void) install_element(BABEL_NODE, &babel_network_cmd); install_element(BABEL_NODE, &no_babel_network_cmd); install_element(INTERFACE_NODE, &babel_split_horizon_cmd); - install_element(INTERFACE_NODE, &no_babel_split_horizon_cmd); install_element(INTERFACE_NODE, &babel_set_wired_cmd); install_element(INTERFACE_NODE, &babel_set_wireless_cmd); install_element(INTERFACE_NODE, &babel_set_hello_interval_cmd); @@ -1251,9 +1197,6 @@ babel_if_init(void) install_element(INTERFACE_NODE, &babel_set_rtt_max_cmd); install_element(INTERFACE_NODE, &babel_set_max_rtt_penalty_cmd); install_element(INTERFACE_NODE, &babel_set_enable_timestamps_cmd); - install_element(INTERFACE_NODE, &no_babel_set_enable_timestamps_cmd); - install_element(INTERFACE_NODE, &babel_set_channel_interfering_cmd); - install_element(INTERFACE_NODE, &babel_set_channel_noninterfering_cmd); /* "show babel ..." commands */ install_element(VIEW_NODE, &show_babel_interface_cmd); diff --git a/babeld/babeld.c b/babeld/babeld.c index dfdc924cb..34e1a4318 100644 --- a/babeld/babeld.c +++ b/babeld/babeld.c @@ -47,6 +47,10 @@ THE SOFTWARE. #include "babel_zebra.h" #include "babel_errors.h" +#ifndef VTYSH_EXTRACT_PL +#include "babeld/babeld_clippy.c" +#endif + DEFINE_MGROUP(BABELD, "babeld"); DEFINE_MTYPE_STATIC(BABELD, BABEL, "Babel Structure"); @@ -662,50 +666,42 @@ DEFUN (no_babel_diversity, } /* [Babel Command] */ -DEFUN (babel_diversity_factor, +DEFPY (babel_diversity_factor, babel_diversity_factor_cmd, - "babel diversity-factor (1-256)", + "[no] babel diversity-factor (1-256)$factor", + NO_STR "Babel commands\n" "Set the diversity factor.\n" "Factor in units of 1/256.\n") { - int factor; - - factor = strtoul(argv[2]->arg, NULL, 10); - - diversity_factor = factor; + diversity_factor = no ? BABEL_DEFAULT_DIVERSITY_FACTOR : factor; return CMD_SUCCESS; } /* [Babel Command] */ -DEFUN (babel_set_resend_delay, +DEFPY (babel_set_resend_delay, babel_set_resend_delay_cmd, - "babel resend-delay (20-655340)", + "[no] babel resend-delay (20-655340)$delay", + NO_STR "Babel commands\n" "Time before resending a message\n" "Milliseconds\n") { - int interval; - - interval = strtoul(argv[2]->arg, NULL, 10); - - resend_delay = interval; + resend_delay = no ? BABEL_DEFAULT_RESEND_DELAY : delay; return CMD_SUCCESS; } /* [Babel Command] */ -DEFUN (babel_set_smoothing_half_life, +DEFPY (babel_set_smoothing_half_life, babel_set_smoothing_half_life_cmd, - "babel smoothing-half-life (0-65534)", + "[no] babel smoothing-half-life (0-65534)$seconds", + NO_STR "Babel commands\n" "Smoothing half-life\n" "Seconds (0 to disable)\n") { - int seconds; - - seconds = strtoul(argv[2]->arg, NULL, 10); - - change_smoothing_half_life(seconds); + change_smoothing_half_life(no ? BABEL_DEFAULT_SMOOTHING_HALF_LIFE + : seconds); return CMD_SUCCESS; } diff --git a/babeld/subdir.am b/babeld/subdir.am index 4b9037283..d2d425218 100644 --- a/babeld/subdir.am +++ b/babeld/subdir.am @@ -43,4 +43,8 @@ noinst_HEADERS += \ babeld/xroute.h \ # end +clippy_scan += \ + babeld/babel_interface.c \ + babeld/babeld.c + babeld_babeld_LDADD = lib/libfrr.la $(LIBCAP) diff --git a/bgpd/bgp_attr.c b/bgpd/bgp_attr.c index e60c1bb8d..392b55880 100644 --- a/bgpd/bgp_attr.c +++ b/bgpd/bgp_attr.c @@ -5097,18 +5097,29 @@ void bgp_dump_routes_attr(struct stream *s, struct bgp_path_info *bpi, } void bgp_path_attribute_discard_vty(struct vty *vty, struct peer *peer, - const char *discard_attrs) + const char *discard_attrs, bool set) { int i, num_attributes; char **attributes; afi_t afi; safi_t safi; - if (discard_attrs) { - frrstr_split(discard_attrs, " ", &attributes, &num_attributes); + /* If `no` command specified without arbitrary attributes, + * then flush all. + */ + if (!discard_attrs) { for (i = 0; i < BGP_ATTR_MAX; i++) peer->discard_attrs[i] = false; + goto discard_soft_clear; + } + + if (discard_attrs) { + frrstr_split(discard_attrs, " ", &attributes, &num_attributes); + + if (set) + for (i = 0; i < BGP_ATTR_MAX; i++) + peer->discard_attrs[i] = false; for (i = 0; i < num_attributes; i++) { uint8_t attr_num = strtoul(attributes[i], NULL, 10); @@ -5142,10 +5153,10 @@ void bgp_path_attribute_discard_vty(struct vty *vty, struct peer *peer, continue; } - peer->discard_attrs[attr_num] = true; + peer->discard_attrs[attr_num] = set; } XFREE(MTYPE_TMP, attributes); - + discard_soft_clear: /* Configuring path attributes to be discarded will trigger * an inbound Route Refresh to ensure that the routing table * is up to date. diff --git a/bgpd/bgp_attr.h b/bgpd/bgp_attr.h index cb0bf4a43..33283f4bf 100644 --- a/bgpd/bgp_attr.h +++ b/bgpd/bgp_attr.h @@ -415,7 +415,7 @@ extern void attr_show_all(struct vty *vty); extern unsigned long int attr_count(void); extern unsigned long int attr_unknown_count(void); extern void bgp_path_attribute_discard_vty(struct vty *vty, struct peer *peer, - const char *discard_attrs); + const char *discard_attrs, bool set); /* Cluster list prototypes. */ extern bool cluster_loop_check(struct cluster_list *cluster, diff --git a/bgpd/bgp_damp.c b/bgpd/bgp_damp.c index 664619078..56bbaf419 100644 --- a/bgpd/bgp_damp.c +++ b/bgpd/bgp_damp.c @@ -327,7 +327,8 @@ void bgp_damp_info_free(struct bgp_damp_info *bdi, int withdraw, afi_t afi, XFREE(MTYPE_BGP_DAMP_INFO, bdi); } -static void bgp_damp_parameter_set(int hlife, int reuse, int sup, int maxsup, +static void bgp_damp_parameter_set(time_t hlife, unsigned int reuse, + unsigned int sup, time_t maxsup, struct bgp_damp_config *bdc) { double reuse_max_ratio; diff --git a/bgpd/bgp_evpn.c b/bgpd/bgp_evpn.c index 286f47b2b..c9e935668 100644 --- a/bgpd/bgp_evpn.c +++ b/bgpd/bgp_evpn.c @@ -2119,10 +2119,11 @@ static int update_evpn_route(struct bgp *bgp, struct bgpevpn *vpn, char buf3[ESI_STR_LEN]; zlog_debug( - "VRF %s vni %u type-2 route evp %pFX RMAC %pEA nexthop %pI4 esi %s", + "VRF %s vni %u type-%u route evp %pFX RMAC %pEA nexthop %pI4 esi %s", vpn->bgp_vrf ? vrf_id_to_name(vpn->bgp_vrf->vrf_id) - : " ", - vpn->vni, p, &attr.rmac, &attr.mp_nexthop_global_in, + : "None", + vpn->vni, p->prefix.route_type, p, &attr.rmac, + &attr.mp_nexthop_global_in, esi_to_str(esi, buf3, sizeof(buf3))); } diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index 59d854495..3f07e53bb 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -2273,8 +2273,12 @@ bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi, && peer->shared_network && (from == bgp->peer_self || peer->sort == BGP_PEER_EBGP))) { - attr->mp_nexthop_len = - BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL; + if (safi == SAFI_MPLS_VPN) + attr->mp_nexthop_len = + BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL; + else + attr->mp_nexthop_len = + BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL; } /* Clear off link-local nexthop in source, whenever it is not diff --git a/bgpd/bgp_routemap.c b/bgpd/bgp_routemap.c index 1ce2eb435..d00bdd257 100644 --- a/bgpd/bgp_routemap.c +++ b/bgpd/bgp_routemap.c @@ -3585,7 +3585,8 @@ route_set_ipv6_nexthop_local(void *rule, const struct prefix *p, void *object) path->attr->mp_nexthop_local = *address; /* Set nexthop length. */ - if (path->attr->mp_nexthop_len != BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) + if (path->attr->mp_nexthop_len != BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL && + path->attr->mp_nexthop_len != BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL) path->attr->mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL; SET_FLAG(path->attr->rmap_change_flags, diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index 5772900ce..5738d9ef6 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -8787,7 +8787,34 @@ DEFPY(neighbor_path_attribute_discard, if (idx) discard_attrs = argv_concat(argv, argc, idx); - bgp_path_attribute_discard_vty(vty, peer, discard_attrs); + bgp_path_attribute_discard_vty(vty, peer, discard_attrs, true); + + return CMD_SUCCESS; +} + +DEFPY(no_neighbor_path_attribute_discard, + no_neighbor_path_attribute_discard_cmd, + "no neighbor <A.B.C.D|X:X::X:X|WORD>$neighbor path-attribute discard [(1-255)]", + NO_STR + NEIGHBOR_STR + NEIGHBOR_ADDR_STR2 + "Manipulate path attributes from incoming UPDATE messages\n" + "Drop specified attributes from incoming UPDATE messages\n" + "Attribute number\n") +{ + struct peer *peer; + int idx = 0; + const char *discard_attrs = NULL; + + peer = peer_and_group_lookup_vty(vty, neighbor); + if (!peer) + return CMD_WARNING_CONFIG_FAILED; + + argv_find(argv, argc, "(1-255)", &idx); + if (idx) + discard_attrs = argv[idx]->arg; + + bgp_path_attribute_discard_vty(vty, peer, discard_attrs, false); return CMD_SUCCESS; } @@ -19541,6 +19568,7 @@ void bgp_vty_init(void) /* "neighbor path-attribute discard" commands. */ install_element(BGP_NODE, &neighbor_path_attribute_discard_cmd); + install_element(BGP_NODE, &no_neighbor_path_attribute_discard_cmd); /* "neighbor passive" commands. */ install_element(BGP_NODE, &neighbor_passive_cmd); diff --git a/eigrpd/eigrp_interface.c b/eigrpd/eigrp_interface.c index 28987b4af..891d28230 100644 --- a/eigrpd/eigrp_interface.c +++ b/eigrpd/eigrp_interface.c @@ -37,6 +37,7 @@ #include "if.h" #include "table.h" #include "memory.h" +#include "network.h" #include "command.h" #include "stream.h" #include "log.h" @@ -83,7 +84,7 @@ struct eigrp_interface *eigrp_if_new(struct eigrp *eigrp, struct interface *ifp, /* Initialize neighbor list. */ ei->nbrs = list_new(); - ei->crypt_seqnum = time(NULL); + ei->crypt_seqnum = frr_sequence32_next(); /* Initialize lists */ for (i = 0; i < EIGRP_FILTER_MAX; i++) { diff --git a/isisd/isis_nb.c b/isisd/isis_nb.c index 4f4e6dc73..c5653d034 100644 --- a/isisd/isis_nb.c +++ b/isisd/isis_nb.c @@ -1107,6 +1107,66 @@ const struct frr_yang_module_info frr_isisd_info = { } }, { + .xpath = "/frr-interface:lib/interface/state/frr-isisd:isis/adjacencies/adjacency/adjacency-sids/adjacency-sid", + .cbs = { + .get_next = lib_interface_state_isis_adjacencies_adjacency_adjacency_sids_adjacency_sid_get_next, + } + }, + { + .xpath = "/frr-interface:lib/interface/state/frr-isisd:isis/adjacencies/adjacency/adjacency-sids/adjacency-sid/af", + .cbs = { + .get_elem = lib_interface_state_isis_adjacencies_adjacency_adjacency_sids_adjacency_sid_af_get_elem, + } + }, + { + .xpath = "/frr-interface:lib/interface/state/frr-isisd:isis/adjacencies/adjacency/adjacency-sids/adjacency-sid/value", + .cbs = { + .get_elem = lib_interface_state_isis_adjacencies_adjacency_adjacency_sids_adjacency_sid_value_get_elem, + } + }, + { + .xpath = "/frr-interface:lib/interface/state/frr-isisd:isis/adjacencies/adjacency/adjacency-sids/adjacency-sid/weight", + .cbs = { + .get_elem = lib_interface_state_isis_adjacencies_adjacency_adjacency_sids_adjacency_sid_weight_get_elem, + } + }, + { + .xpath = "/frr-interface:lib/interface/state/frr-isisd:isis/adjacencies/adjacency/adjacency-sids/adjacency-sid/protection-requested", + .cbs = { + .get_elem = lib_interface_state_isis_adjacencies_adjacency_adjacency_sids_adjacency_sid_protection_requested_get_elem, + } + }, + { + .xpath = "/frr-interface:lib/interface/state/frr-isisd:isis/adjacencies/adjacency/lan-adjacency-sids/lan-adjacency-sid", + .cbs = { + .get_next = lib_interface_state_isis_adjacencies_adjacency_lan_adjacency_sids_lan_adjacency_sid_get_next, + } + }, + { + .xpath = "/frr-interface:lib/interface/state/frr-isisd:isis/adjacencies/adjacency/lan-adjacency-sids/lan-adjacency-sid/af", + .cbs = { + .get_elem = lib_interface_state_isis_adjacencies_adjacency_lan_adjacency_sids_lan_adjacency_sid_af_get_elem, + } + }, + { + .xpath = "/frr-interface:lib/interface/state/frr-isisd:isis/adjacencies/adjacency/lan-adjacency-sids/lan-adjacency-sid/value", + .cbs = { + .get_elem = lib_interface_state_isis_adjacencies_adjacency_lan_adjacency_sids_lan_adjacency_sid_value_get_elem, + } + }, + { + .xpath = "/frr-interface:lib/interface/state/frr-isisd:isis/adjacencies/adjacency/lan-adjacency-sids/lan-adjacency-sid/weight", + .cbs = { + .get_elem = lib_interface_state_isis_adjacencies_adjacency_lan_adjacency_sids_lan_adjacency_sid_weight_get_elem, + } + }, + { + .xpath = "/frr-interface:lib/interface/state/frr-isisd:isis/adjacencies/adjacency/lan-adjacency-sids/lan-adjacency-sid/protection-requested", + .cbs = { + .get_elem = lib_interface_state_isis_adjacencies_adjacency_lan_adjacency_sids_lan_adjacency_sid_protection_requested_get_elem, + } + }, + { .xpath = "/frr-interface:lib/interface/state/frr-isisd:isis/event-counters/adjacency-changes", .cbs = { .get_elem = lib_interface_state_isis_event_counters_adjacency_changes_get_elem, diff --git a/isisd/isis_nb.h b/isisd/isis_nb.h index a9f2eaea9..380ce4f25 100644 --- a/isisd/isis_nb.h +++ b/isisd/isis_nb.h @@ -369,6 +369,36 @@ lib_interface_state_isis_adjacencies_adjacency_neighbor_priority_get_elem( struct nb_cb_get_elem_args *args); struct yang_data *lib_interface_state_isis_adjacencies_adjacency_state_get_elem( struct nb_cb_get_elem_args *args); +const void * +lib_interface_state_isis_adjacencies_adjacency_adjacency_sids_adjacency_sid_get_next( + struct nb_cb_get_next_args *args); +struct yang_data * +lib_interface_state_isis_adjacencies_adjacency_adjacency_sids_adjacency_sid_af_get_elem( + struct nb_cb_get_elem_args *args); +struct yang_data * +lib_interface_state_isis_adjacencies_adjacency_adjacency_sids_adjacency_sid_value_get_elem( + struct nb_cb_get_elem_args *args); +struct yang_data * +lib_interface_state_isis_adjacencies_adjacency_adjacency_sids_adjacency_sid_weight_get_elem( + struct nb_cb_get_elem_args *args); +struct yang_data * +lib_interface_state_isis_adjacencies_adjacency_adjacency_sids_adjacency_sid_protection_requested_get_elem( + struct nb_cb_get_elem_args *args); +const void * +lib_interface_state_isis_adjacencies_adjacency_lan_adjacency_sids_lan_adjacency_sid_get_next( + struct nb_cb_get_next_args *args); +struct yang_data * +lib_interface_state_isis_adjacencies_adjacency_lan_adjacency_sids_lan_adjacency_sid_af_get_elem( + struct nb_cb_get_elem_args *args); +struct yang_data * +lib_interface_state_isis_adjacencies_adjacency_lan_adjacency_sids_lan_adjacency_sid_value_get_elem( + struct nb_cb_get_elem_args *args); +struct yang_data * +lib_interface_state_isis_adjacencies_adjacency_lan_adjacency_sids_lan_adjacency_sid_weight_get_elem( + struct nb_cb_get_elem_args *args); +struct yang_data * +lib_interface_state_isis_adjacencies_adjacency_lan_adjacency_sids_lan_adjacency_sid_protection_requested_get_elem( + struct nb_cb_get_elem_args *args); struct yang_data * lib_interface_state_isis_event_counters_adjacency_changes_get_elem( struct nb_cb_get_elem_args *args); diff --git a/isisd/isis_nb_state.c b/isisd/isis_nb_state.c index 4e325ed8d..5b1fc6e1d 100644 --- a/isisd/isis_nb_state.c +++ b/isisd/isis_nb_state.c @@ -216,6 +216,228 @@ struct yang_data *lib_interface_state_isis_adjacencies_adjacency_state_get_elem( /* * XPath: + * /frr-interface:lib/interface/state/frr-isisd:isis/adjacencies/adjacency/adjacency-sids/adjacency-sid + */ +const void * +lib_interface_state_isis_adjacencies_adjacency_adjacency_sids_adjacency_sid_get_next( + struct nb_cb_get_next_args *args) +{ + const struct isis_adjacency *adj = args->parent_list_entry; + const struct sr_adjacency *sra = args->list_entry, *sra_next = NULL; + struct listnode *node, *node_next; + + if (args->list_entry == NULL) + sra_next = listnode_head(adj->adj_sids); + else { + node = listnode_lookup(adj->adj_sids, sra); + node_next = listnextnode(node); + if (node_next) + sra_next = listgetdata(node_next); + } + + return sra_next; +} + +/* + * XPath: + * /frr-interface:lib/interface/state/frr-isisd:isis/adjacencies/adjacency/adjacency-sids/adjacency-sid/af + */ +struct yang_data * +lib_interface_state_isis_adjacencies_adjacency_adjacency_sids_adjacency_sid_af_get_elem( + struct nb_cb_get_elem_args *args) +{ + const struct sr_adjacency *sra = args->list_entry; + + switch (sra->adj->circuit->circ_type) { + case CIRCUIT_T_BROADCAST: + /* Adjacency SID is not published with circuit type Broadcast */ + return NULL; + case CIRCUIT_T_P2P: + return yang_data_new_uint8(args->xpath, sra->u.adj_sid->family); + } + + return NULL; +} + +/* + * XPath: + * /frr-interface:lib/interface/state/frr-isisd:isis/adjacencies/adjacency/adjacency-sids/adjacency-sid/value + */ +struct yang_data * +lib_interface_state_isis_adjacencies_adjacency_adjacency_sids_adjacency_sid_value_get_elem( + struct nb_cb_get_elem_args *args) +{ + const struct sr_adjacency *sra = args->list_entry; + + switch (sra->adj->circuit->circ_type) { + case CIRCUIT_T_BROADCAST: + /* Adjacency SID is not published with circuit type Broadcast */ + return NULL; + case CIRCUIT_T_P2P: + return yang_data_new_uint32(args->xpath, sra->u.adj_sid->sid); + } + + return NULL; +} + +/* + * XPath: + * /frr-interface:lib/interface/state/frr-isisd:isis/adjacencies/adjacency/adjacency-sids/adjacency-sid/weight + */ +struct yang_data * +lib_interface_state_isis_adjacencies_adjacency_adjacency_sids_adjacency_sid_weight_get_elem( + struct nb_cb_get_elem_args *args) +{ + const struct sr_adjacency *sra = args->list_entry; + + switch (sra->adj->circuit->circ_type) { + case CIRCUIT_T_BROADCAST: + /* Adjacency SID is not published with circuit type Broadcast */ + return NULL; + case CIRCUIT_T_P2P: + return yang_data_new_uint8(args->xpath, sra->u.adj_sid->weight); + } + + return NULL; +} + +/* + * XPath: + * /frr-interface:lib/interface/state/frr-isisd:isis/adjacencies/adjacency/adjacency-sids/adjacency-sid/protection-requested + */ +struct yang_data * +lib_interface_state_isis_adjacencies_adjacency_adjacency_sids_adjacency_sid_protection_requested_get_elem( + struct nb_cb_get_elem_args *args) +{ + const struct sr_adjacency *sra = args->list_entry; + + switch (sra->adj->circuit->circ_type) { + case CIRCUIT_T_BROADCAST: + /* Adjacency SID is not published with circuit type Broadcast */ + return NULL; + case CIRCUIT_T_P2P: + return yang_data_new_bool(args->xpath, + sra->u.adj_sid->flags & + EXT_SUBTLV_LINK_ADJ_SID_BFLG); + } + + return NULL; +} + +/* + * XPath: + * /frr-interface:lib/interface/state/frr-isisd:isis/adjacencies/adjacency/lan-adjacency-sids/lan-adjacency-sid + */ +const void * +lib_interface_state_isis_adjacencies_adjacency_lan_adjacency_sids_lan_adjacency_sid_get_next( + struct nb_cb_get_next_args *args) +{ + const struct isis_adjacency *adj = args->parent_list_entry; + const struct sr_adjacency *sra = args->list_entry, *sra_next = NULL; + struct listnode *node, *node_next; + + if (args->list_entry == NULL) + sra_next = listnode_head(adj->adj_sids); + else { + node = listnode_lookup(adj->adj_sids, sra); + node_next = listnextnode(node); + if (node_next) + sra_next = listgetdata(node_next); + } + + return sra_next; +} + +/* + * XPath: + * /frr-interface:lib/interface/state/frr-isisd:isis/adjacencies/adjacency/lan-adjacency-sids/lan-adjacency-sid/af + */ +struct yang_data * +lib_interface_state_isis_adjacencies_adjacency_lan_adjacency_sids_lan_adjacency_sid_af_get_elem( + struct nb_cb_get_elem_args *args) +{ + const struct sr_adjacency *sra = args->list_entry; + + switch (sra->adj->circuit->circ_type) { + case CIRCUIT_T_BROADCAST: + return yang_data_new_uint8(args->xpath, + sra->u.ladj_sid->family); + case CIRCUIT_T_P2P: + /* LAN adjacency SID is not published with circuit type P2P */ + return NULL; + } + + return NULL; +} + +/* + * XPath: + * /frr-interface:lib/interface/state/frr-isisd:isis/adjacencies/adjacency/lan-adjacency-sids/lan-adjacency-sid/value + */ +struct yang_data * +lib_interface_state_isis_adjacencies_adjacency_lan_adjacency_sids_lan_adjacency_sid_value_get_elem( + struct nb_cb_get_elem_args *args) +{ + const struct sr_adjacency *sra = args->list_entry; + + switch (sra->adj->circuit->circ_type) { + case CIRCUIT_T_BROADCAST: + return yang_data_new_uint32(args->xpath, sra->u.ladj_sid->sid); + case CIRCUIT_T_P2P: + /* LAN adjacency SID is not published with circuit type P2P */ + return NULL; + } + + return NULL; +} + +/* + * XPath: + * /frr-interface:lib/interface/state/frr-isisd:isis/adjacencies/adjacency/lan-adjacency-sids/lan-adjacency-sid/weight + */ +struct yang_data * +lib_interface_state_isis_adjacencies_adjacency_lan_adjacency_sids_lan_adjacency_sid_weight_get_elem( + struct nb_cb_get_elem_args *args) +{ + const struct sr_adjacency *sra = args->list_entry; + + switch (sra->adj->circuit->circ_type) { + case CIRCUIT_T_BROADCAST: + return yang_data_new_uint8(args->xpath, + sra->u.ladj_sid->weight); + case CIRCUIT_T_P2P: + /* LAN adjacency SID is not published with circuit type P2P */ + return NULL; + } + + return NULL; +} + +/* + * XPath: + * /frr-interface:lib/interface/state/frr-isisd:isis/adjacencies/adjacency/lan-adjacency-sids/lan-adjacency-sid/protection-requested + */ +struct yang_data * +lib_interface_state_isis_adjacencies_adjacency_lan_adjacency_sids_lan_adjacency_sid_protection_requested_get_elem( + struct nb_cb_get_elem_args *args) +{ + const struct sr_adjacency *sra = args->list_entry; + + switch (sra->adj->circuit->circ_type) { + case CIRCUIT_T_BROADCAST: + return yang_data_new_bool(args->xpath, + sra->u.ladj_sid->flags & + EXT_SUBTLV_LINK_ADJ_SID_BFLG); + case CIRCUIT_T_P2P: + /* LAN adjacency SID is not published with circuit type P2P */ + return NULL; + } + + return NULL; +} + +/* + * XPath: * /frr-interface:lib/interface/state/frr-isisd:isis/event-counters/adjacency-changes */ struct yang_data * diff --git a/isisd/isis_spf.c b/isisd/isis_spf.c index 89e751b4e..a6eef75e7 100644 --- a/isisd/isis_spf.c +++ b/isisd/isis_spf.c @@ -2714,12 +2714,14 @@ void isis_spf_init(void) void isis_spf_print(struct isis_spftree *spftree, struct vty *vty) { + uint64_t last_run_duration = spftree->last_run_duration; + vty_out(vty, " last run elapsed : "); vty_out_timestr(vty, spftree->last_run_timestamp); vty_out(vty, "\n"); - vty_out(vty, " last run duration : %u usec\n", - (uint32_t)spftree->last_run_duration); + vty_out(vty, " last run duration : %" PRIu64 " usec\n", + last_run_duration); vty_out(vty, " run count : %u\n", spftree->runcount); } diff --git a/ldpd/logmsg.c b/ldpd/logmsg.c index ff9294f9d..e16006b89 100644 --- a/ldpd/logmsg.c +++ b/ldpd/logmsg.c @@ -137,7 +137,7 @@ log_time(time_t t) char *buf; static char tfbuf[TF_BUFS][TF_LEN]; /* ring buffer */ static int idx = 0; - unsigned int sec, min, hrs, day, week; + uint64_t sec, min, hrs, day, week; buf = tfbuf[idx++]; if (idx == TF_BUFS) @@ -155,11 +155,17 @@ log_time(time_t t) week /= 7; if (week > 0) - snprintf(buf, TF_LEN, "%02uw%01ud%02uh", week, day, hrs); + snprintfrr(buf, TF_LEN, + "%02" PRIu64 "w%01" PRIu64 "d%02" PRIu64 "h", week, + day, hrs); else if (day > 0) - snprintf(buf, TF_LEN, "%01ud%02uh%02um", day, hrs, min); + snprintfrr(buf, TF_LEN, + "%01" PRIu64 "d%02" PRIu64 "h%02" PRIu64 "m", day, + hrs, min); else - snprintf(buf, TF_LEN, "%02u:%02u:%02u", hrs, min, sec); + snprintfrr(buf, TF_LEN, + "%02" PRIu64 ":%02" PRIu64 ":%02" PRIu64, hrs, min, + sec); return (buf); } @@ -129,8 +129,6 @@ struct bfd_sessions_global { struct thread_master *tm; /** Pointer to zebra client data structure. */ struct zclient *zc; - /** Zebra next hop tracking (NHT) client. */ - struct zclient *nht_zclient; /** Debugging state. */ bool debugging; @@ -147,31 +145,10 @@ static const struct in6_addr i6a_zero; /* * Prototypes */ -static void bfd_nht_zclient_connect(struct thread *thread); - -static void bfd_nht_zclient_connected(struct zclient *zclient); -static int bfd_nht_update(ZAPI_CALLBACK_ARGS); static void bfd_source_cache_get(struct bfd_session_params *session); static void bfd_source_cache_put(struct bfd_session_params *session); -static inline void -bfd_source_cache_register(const struct bfd_source_cache *source) -{ - zclient_send_rnh(bsglobal.nht_zclient, ZEBRA_NEXTHOP_REGISTER, - &source->address, SAFI_UNICAST, false, false, - source->vrf_id); -} - -static inline void -bfd_source_cache_unregister(const struct bfd_source_cache *source) -{ - zclient_send_rnh(bsglobal.nht_zclient, ZEBRA_NEXTHOP_UNREGISTER, - &source->address, SAFI_UNICAST, false, false, - source->vrf_id); -} - - /* * bfd_get_peer_info - Extract the Peer information for which the BFD session * went down from the message sent from Zebra to clients. @@ -1074,20 +1051,11 @@ static int bfd_protocol_integration_finish(void) if (!SLIST_EMPTY(&bsglobal.source_list)) zlog_warn("BFD integration source cache not empty"); - zclient_stop(bsglobal.nht_zclient); - zclient_free(bsglobal.nht_zclient); - return 0; } -static zclient_handler *const bfd_nht_handlers[] = { - [ZEBRA_NEXTHOP_UPDATE] = bfd_nht_update, -}; - void bfd_protocol_integration_init(struct zclient *zc, struct thread_master *tm) { - struct zclient_options bfd_nht_options = zclient_options_default; - /* Initialize data structure. */ TAILQ_INIT(&bsglobal.bsplist); SLIST_INIT(&bsglobal.source_list); @@ -1102,16 +1070,6 @@ void bfd_protocol_integration_init(struct zclient *zc, struct thread_master *tm) /* Send the client registration */ bfd_client_sendmsg(zc, ZEBRA_BFD_CLIENT_REGISTER, VRF_DEFAULT); - /* Start NHT client (for automatic source decisions). */ - bsglobal.nht_zclient = - zclient_new(tm, &bfd_nht_options, bfd_nht_handlers, - array_size(bfd_nht_handlers)); - bsglobal.nht_zclient->sock = -1; - bsglobal.nht_zclient->privs = zc->privs; - bsglobal.nht_zclient->zebra_connected = bfd_nht_zclient_connected; - thread_add_timer(tm, bfd_nht_zclient_connect, bsglobal.nht_zclient, 1, - &bsglobal.nht_zclient->t_connect); - hook_register(frr_fini, bfd_protocol_integration_finish); } @@ -1252,8 +1210,6 @@ static void bfd_source_cache_get(struct bfd_session_params *session) session->source_cache = source; source->refcount = 1; - bfd_source_cache_register(source); - return; } @@ -1268,7 +1224,6 @@ static void bfd_source_cache_put(struct bfd_session_params *session) return; } - bfd_source_cache_unregister(session->source_cache); SLIST_REMOVE(&bsglobal.source_list, session->source_cache, bfd_source_cache, entry); XFREE(MTYPE_BFD_SOURCE, session->source_cache); @@ -1378,59 +1333,19 @@ static bool bfd_source_cache_update(struct bfd_source_cache *source, return false; } -static void bfd_nht_zclient_connect(struct thread *thread) -{ - struct zclient *zclient = THREAD_ARG(thread); - - if (bsglobal.debugging) - zlog_debug("BFD NHT zclient connection attempt"); - - if (zclient_start(zclient) == -1) { - if (bsglobal.debugging) - zlog_debug("BFD NHT zclient connection failed"); - - thread_add_timer(bsglobal.tm, bfd_nht_zclient_connect, zclient, - 3, &zclient->t_connect); - return; - } - - if (bsglobal.debugging) - zlog_debug("BFD NHT zclient connection succeeded"); -} - -static void bfd_nht_zclient_connected(struct zclient *zclient) -{ - struct bfd_source_cache *source; - - if (bsglobal.debugging) - zlog_debug("BFD NHT zclient connected"); - - SLIST_FOREACH (source, &bsglobal.source_list, entry) - bfd_source_cache_register(source); -} - -static int bfd_nht_update(ZAPI_CALLBACK_ARGS) +int bfd_nht_update(const struct prefix *match, const struct zapi_route *route) { struct bfd_source_cache *source; - struct zapi_route route; - struct prefix match; - - if (!zapi_nexthop_update_decode(zclient->ibuf, &match, &route)) { - zlog_warn("BFD NHT update decode failure"); - return 0; - } - if (cmd != ZEBRA_NEXTHOP_UPDATE) - return 0; if (bsglobal.debugging) - zlog_debug("BFD NHT update for %pFX", &route.prefix); + zlog_debug("BFD NHT update for %pFX", &route->prefix); SLIST_FOREACH (source, &bsglobal.source_list, entry) { - if (source->vrf_id != route.vrf_id) + if (source->vrf_id != route->vrf_id) continue; - if (!prefix_same(&match, &source->address)) + if (!prefix_same(match, &source->address)) continue; - if (bfd_source_cache_update(source, &route)) + if (bfd_source_cache_update(source, route)) bfd_source_cache_update_sessions(source); } @@ -473,6 +473,13 @@ extern bool bfd_protocol_integration_debug(void); */ extern bool bfd_protocol_integration_shutting_down(void); +/* Update nexthop-tracking (nht) information for BFD auto source selection. + * The function must be called from the daemon callback function + * that deals with the ZEBRA_NEXTHOP_UPDATE zclient command + */ +extern int bfd_nht_update(const struct prefix *match, + const struct zapi_route *route); + #ifdef __cplusplus } #endif diff --git a/lib/filter_cli.c b/lib/filter_cli.c index e0f0f177e..296c05b9f 100644 --- a/lib/filter_cli.c +++ b/lib/filter_cli.c @@ -66,16 +66,21 @@ static int acl_get_seq_cb(const struct lyd_node *dnode, void *arg) * * \param[in] vty shell context with the candidate configuration. * \param[in] xpath the XPath to look for the sequence leaf. - * \returns next unused sequence number. + * \returns next unused sequence number, -1 if out of range when adding. */ -static long acl_get_seq(struct vty *vty, const char *xpath) +static int64_t acl_get_seq(struct vty *vty, const char *xpath, bool is_remove) { int64_t seq = 0; yang_dnode_iterate(acl_get_seq_cb, &seq, vty->candidate_config->dnode, "%s/entry", xpath); - return seq + 5; + seq += 5; + if (!is_remove && seq > UINT32_MAX) { + vty_out(vty, "%% Malformed sequence value\n"); + return -1; + } + return seq; } static int acl_remove_if_empty(struct vty *vty, const char *iptype, @@ -98,7 +103,7 @@ static int acl_remove_if_empty(struct vty *vty, const char *iptype, * NOTE: if the list is empty it will return the first sequence * number: 5. */ - if (acl_get_seq(vty, xpath) != 5) + if (acl_get_seq(vty, xpath, true) != 5) return CMD_SUCCESS; /* Nobody is using this list, lets remove it. */ @@ -174,16 +179,19 @@ DEFPY_YANG( */ snprintf(xpath, sizeof(xpath), "/frr-filter:lib/access-list[type='ipv4'][name='%s']", name); - nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL); if (seq_str == NULL) { /* Use XPath to find the next sequence number. */ - sseq = acl_get_seq(vty, xpath); + sseq = acl_get_seq(vty, xpath, false); + if (sseq < 0) + return CMD_WARNING_CONFIG_FAILED; + snprintfrr(xpath_entry, sizeof(xpath_entry), "%s/entry[sequence='%" PRId64 "']", xpath, sseq); } else snprintfrr(xpath_entry, sizeof(xpath_entry), "%s/entry[sequence='%s']", xpath, seq_str); + nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL); nb_cli_enqueue_change(vty, xpath_entry, NB_OP_CREATE, NULL); nb_cli_enqueue_change(vty, "./action", NB_OP_MODIFY, action); @@ -321,16 +329,19 @@ DEFPY_YANG( */ snprintf(xpath, sizeof(xpath), "/frr-filter:lib/access-list[type='ipv4'][name='%s']", name); - nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL); if (seq_str == NULL) { /* Use XPath to find the next sequence number. */ - sseq = acl_get_seq(vty, xpath); + sseq = acl_get_seq(vty, xpath, false); + if (sseq < 0) + return CMD_WARNING_CONFIG_FAILED; + snprintfrr(xpath_entry, sizeof(xpath_entry), "%s/entry[sequence='%" PRId64 "']", xpath, sseq); } else snprintfrr(xpath_entry, sizeof(xpath_entry), "%s/entry[sequence='%s']", xpath, seq_str); + nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL); nb_cli_enqueue_change(vty, xpath_entry, NB_OP_CREATE, NULL); nb_cli_enqueue_change(vty, "./action", NB_OP_MODIFY, action); @@ -483,16 +494,19 @@ DEFPY_YANG( */ snprintf(xpath, sizeof(xpath), "/frr-filter:lib/access-list[type='ipv4'][name='%s']", name); - nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL); if (seq_str == NULL) { /* Use XPath to find the next sequence number. */ - sseq = acl_get_seq(vty, xpath); + sseq = acl_get_seq(vty, xpath, false); + if (sseq < 0) + return CMD_WARNING_CONFIG_FAILED; + snprintfrr(xpath_entry, sizeof(xpath_entry), "%s/entry[sequence='%" PRId64 "']", xpath, sseq); } else snprintfrr(xpath_entry, sizeof(xpath_entry), "%s/entry[sequence='%s']", xpath, seq_str); + nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL); nb_cli_enqueue_change(vty, xpath_entry, NB_OP_CREATE, NULL); nb_cli_enqueue_change(vty, "./action", NB_OP_MODIFY, action); @@ -670,16 +684,19 @@ DEFPY_YANG( */ snprintf(xpath, sizeof(xpath), "/frr-filter:lib/access-list[type='ipv6'][name='%s']", name); - nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL); if (seq_str == NULL) { /* Use XPath to find the next sequence number. */ - sseq = acl_get_seq(vty, xpath); + sseq = acl_get_seq(vty, xpath, false); + if (sseq < 0) + return CMD_WARNING_CONFIG_FAILED; + snprintfrr(xpath_entry, sizeof(xpath_entry), "%s/entry[sequence='%" PRId64 "']", xpath, sseq); } else snprintfrr(xpath_entry, sizeof(xpath_entry), "%s/entry[sequence='%s']", xpath, seq_str); + nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL); nb_cli_enqueue_change(vty, xpath_entry, NB_OP_CREATE, NULL); nb_cli_enqueue_change(vty, "./action", NB_OP_MODIFY, action); @@ -857,16 +874,19 @@ DEFPY_YANG( */ snprintf(xpath, sizeof(xpath), "/frr-filter:lib/access-list[type='mac'][name='%s']", name); - nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL); if (seq_str == NULL) { /* Use XPath to find the next sequence number. */ - sseq = acl_get_seq(vty, xpath); + sseq = acl_get_seq(vty, xpath, false); + if (sseq < 0) + return CMD_WARNING_CONFIG_FAILED; + snprintfrr(xpath_entry, sizeof(xpath_entry), "%s/entry[sequence='%" PRId64 "']", xpath, sseq); } else snprintfrr(xpath_entry, sizeof(xpath_entry), "%s/entry[sequence='%s']", xpath, seq_str); + nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL); nb_cli_enqueue_change(vty, xpath_entry, NB_OP_CREATE, NULL); nb_cli_enqueue_change(vty, "./action", NB_OP_MODIFY, action); @@ -1167,7 +1187,7 @@ static int plist_remove_if_empty(struct vty *vty, const char *iptype, * NOTE: if the list is empty it will return the first sequence * number: 5. */ - if (acl_get_seq(vty, xpath) != 5) + if (acl_get_seq(vty, xpath, true) != 5) return CMD_SUCCESS; /* Nobody is using this list, lets remove it. */ @@ -1275,16 +1295,19 @@ DEFPY_YANG( */ snprintf(xpath, sizeof(xpath), "/frr-filter:lib/prefix-list[type='ipv4'][name='%s']", name); - nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL); if (seq_str == NULL) { /* Use XPath to find the next sequence number. */ - sseq = acl_get_seq(vty, xpath); + sseq = acl_get_seq(vty, xpath, false); + if (sseq < 0) + return CMD_WARNING_CONFIG_FAILED; + snprintfrr(xpath_entry, sizeof(xpath_entry), "%s/entry[sequence='%" PRId64 "']", xpath, sseq); } else snprintfrr(xpath_entry, sizeof(xpath_entry), "%s/entry[sequence='%s']", xpath, seq_str); + nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL); nb_cli_enqueue_change(vty, xpath_entry, NB_OP_CREATE, NULL); nb_cli_enqueue_change(vty, "./action", NB_OP_MODIFY, action); @@ -1476,16 +1499,19 @@ DEFPY_YANG( */ snprintf(xpath, sizeof(xpath), "/frr-filter:lib/prefix-list[type='ipv6'][name='%s']", name); - nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL); if (seq_str == NULL) { /* Use XPath to find the next sequence number. */ - sseq = acl_get_seq(vty, xpath); + sseq = acl_get_seq(vty, xpath, false); + if (sseq < 0) + return CMD_WARNING_CONFIG_FAILED; + snprintfrr(xpath_entry, sizeof(xpath_entry), "%s/entry[sequence='%" PRId64 "']", xpath, sseq); } else snprintfrr(xpath_entry, sizeof(xpath_entry), "%s/entry[sequence='%s']", xpath, seq_str); + nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL); nb_cli_enqueue_change(vty, xpath_entry, NB_OP_CREATE, NULL); nb_cli_enqueue_change(vty, "./action", NB_OP_MODIFY, action); diff --git a/lib/network.c b/lib/network.c index b60ad9a57..cd62b8b59 100644 --- a/lib/network.c +++ b/lib/network.c @@ -122,3 +122,24 @@ float ntohf(float net) { return htonf(net); } + +uint64_t frr_sequence_next(void) +{ + static uint64_t last_sequence; + struct timespec ts; + + (void)clock_gettime(CLOCK_MONOTONIC, &ts); + if (last_sequence == (uint64_t)ts.tv_sec) { + last_sequence++; + return last_sequence; + } + + last_sequence = ts.tv_sec; + return last_sequence; +} + +uint32_t frr_sequence32_next(void) +{ + /* coverity[Y2K38_SAFETY] */ + return (uint32_t)frr_sequence_next(); +} diff --git a/lib/network.h b/lib/network.h index 10ed91757..c163eab8f 100644 --- a/lib/network.h +++ b/lib/network.h @@ -82,6 +82,24 @@ extern float ntohf(float); #endif /** + * Generate a sequence number using monotonic clock with a same second call + * protection to help guarantee a unique incremental sequence number that never + * goes back (except when wrapping/overflow). + * + * **NOTE** this function is not thread safe since it uses `static` variable. + * + * This function and `frr_sequence32_next` should be used to initialize + * sequence numbers without directly calling other `time_t` returning + * functions because of `time_t` truncation warnings. + * + * \returns `uint64_t` number based on the monotonic clock. + */ +extern uint64_t frr_sequence_next(void); + +/** Same as `frr_sequence_next` but returns truncated number. */ +extern uint32_t frr_sequence32_next(void); + +/** * Helper function that returns a random long value. The main purpose of * this function is to hide a `random()` call that gets flagged by coverity * scan and put it into one place. diff --git a/ospf6d/ospf6_message.c b/ospf6d/ospf6_message.c index fb54ebab1..3d29a65d1 100644 --- a/ospf6d/ospf6_message.c +++ b/ospf6d/ospf6_message.c @@ -28,6 +28,7 @@ #include "linklist.h" #include "lib_errors.h" #include "checksum.h" +#include "network.h" #include "ospf6_proto.h" #include "ospf6_lsa.h" @@ -2300,7 +2301,7 @@ static uint16_t ospf6_make_dbdesc(struct ospf6_neighbor *on, struct stream *s) /* if this is initial one, initialize sequence number for DbDesc */ if (CHECK_FLAG(on->dbdesc_bits, OSPF6_DBDESC_IBIT) && (on->dbdesc_seqnum == 0)) { - on->dbdesc_seqnum = monotime(NULL); + on->dbdesc_seqnum = frr_sequence32_next(); } /* reserved */ diff --git a/ospfd/ospf_interface.c b/ospfd/ospf_interface.c index a0b14e73e..831906b90 100644 --- a/ospfd/ospf_interface.c +++ b/ospfd/ospf_interface.c @@ -30,6 +30,7 @@ #include "command.h" #include "stream.h" #include "log.h" +#include "network.h" #include "zclient.h" #include "bfd.h" #include "ldp_sync.h" @@ -274,7 +275,7 @@ struct ospf_interface *ospf_if_new(struct ospf *ospf, struct interface *ifp, oi->t_ls_upd_event = NULL; oi->t_ls_ack_direct = NULL; - oi->crypt_seqnum = time(NULL); + oi->crypt_seqnum = frr_sequence32_next(); ospf_opaque_type9_lsa_init(oi); diff --git a/ospfd/ospf_vty.c b/ospfd/ospf_vty.c index f22c1e7e4..0b0b9d81e 100644 --- a/ospfd/ospf_vty.c +++ b/ospfd/ospf_vty.c @@ -7314,16 +7314,26 @@ static int show_ip_ospf_database_type_adv_router_common(struct vty *vty, type = OSPF_OPAQUE_AREA_LSA; else if (strncmp(argv[arg_base + idx_type]->text, "opaque-as", 9) == 0) type = OSPF_OPAQUE_AS_LSA; - else + else { + if (uj) { + if (use_vrf) + json_object_free(json_vrf); + } return CMD_WARNING; + } /* `show ip ospf database LSA adv-router ADV_ROUTER'. */ if (strncmp(argv[arg_base + 5]->text, "s", 1) == 0) adv_router = ospf->router_id; else { ret = inet_aton(argv[arg_base + 6]->arg, &adv_router); - if (!ret) + if (!ret) { + if (uj) { + if (use_vrf) + json_object_free(json_vrf); + } return CMD_WARNING; + } } show_lsa_detail_adv_router(vty, ospf, type, &adv_router, json_vrf); @@ -7387,9 +7397,12 @@ DEFUN (show_ip_ospf_database_type_adv_router, } else { ospf = ospf_lookup_by_inst_name(inst, vrf_name); if ((ospf == NULL) || !ospf->oi_running) { - vty_out(vty, - "%% OSPF is not enabled in vrf %s\n", - vrf_name); + if (uj) + vty_json(vty, json); + else + vty_out(vty, + "%% OSPF is not enabled in vrf %s\n", + vrf_name); return CMD_SUCCESS; } @@ -7400,7 +7413,11 @@ DEFUN (show_ip_ospf_database_type_adv_router, /* Display default ospf (instance 0) info */ ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT); if (ospf == NULL || !ospf->oi_running) { - vty_out(vty, "%% OSPF is not enabled on vrf default\n"); + if (uj) + vty_json(vty, json); + else + vty_out(vty, + "%% OSPF is not enabled on vrf default\n"); return CMD_SUCCESS; } @@ -11274,7 +11291,12 @@ static int show_ip_ospf_route_common(struct vty *vty, struct ospf *ospf, ospf_show_vrf_name(ospf, vty, json_vrf, use_vrf); if (ospf->new_table == NULL) { - vty_out(vty, "No OSPF routing information exist\n"); + if (json) { + if (use_vrf) + json_object_free(json_vrf); + } else { + vty_out(vty, "No OSPF routing information exist\n"); + } return CMD_SUCCESS; } diff --git a/pimd/mtracebis_netlink.c b/pimd/mtracebis_netlink.c index 81e28f240..9bdf94900 100644 --- a/pimd/mtracebis_netlink.c +++ b/pimd/mtracebis_netlink.c @@ -92,7 +92,7 @@ int rtnl_open_byproto(struct rtnl_handle *rth, unsigned subscriptions, rth->local.nl_family); return -1; } - rth->seq = (uint32_t)time(NULL); + rth->seq = getpid(); return 0; } diff --git a/staticd/static_zebra.c b/staticd/static_zebra.c index 316247adb..85e4b1c03 100644 --- a/staticd/static_zebra.c +++ b/staticd/static_zebra.c @@ -211,6 +211,9 @@ static int static_zebra_nexthop_update(ZAPI_CALLBACK_ARGS) return 1; } + if (zclient->bfd_integration) + bfd_nht_update(&matched, &nhr); + if (matched.family == AF_INET6) afi = AFI_IP6; diff --git a/vtysh/subdir.am b/vtysh/subdir.am index cc2a70ade..72204201d 100644 --- a/vtysh/subdir.am +++ b/vtysh/subdir.am @@ -37,4 +37,5 @@ $(vtysh_vtysh_OBJECTS): vtysh/vtysh_daemons.h CLEANFILES += vtysh/vtysh_daemons.h vtysh/vtysh_daemons.h: + mkdir -p vtysh $(PERL) $(top_srcdir)/vtysh/daemons.pl $(vtysh_daemons) > vtysh/vtysh_daemons.h diff --git a/yang/frr-isisd.yang b/yang/frr-isisd.yang index 380fce385..5483410d0 100644 --- a/yang/frr-isisd.yang +++ b/yang/frr-isisd.yang @@ -881,6 +881,9 @@ module frr-isisd { description "This leaf describes the state of the interface."; } + + uses adjacency-sids; + uses lan-adjacency-sids; } } } @@ -1004,6 +1007,76 @@ module frr-isisd { } } + grouping adjacency-sids { + description + "IS-IS segment routing adjacency SID grouping."; + container adjacency-sids { + description + "This container lists the information of adjacency SID."; + list adjacency-sid { + leaf af { + type uint8; + description + "This leaf describes the protocol-family associated with the + adjacency SID."; + } + + leaf value { + type uint32; + description + "This leaf describes the value of adjacency SID."; + } + + leaf weight { + type uint8; + description + "This leaf describes the weight of the adjacency SID."; + } + + leaf protection-requested { + type boolean; + description + "This leaf describes if the adjacency SID must be protected."; + } + } + } + } + + grouping lan-adjacency-sids { + description + "IS-IS segment routing LAN adjacency SID grouping."; + container lan-adjacency-sids { + description + "This container lists the information of LAN adjacency SID."; + list lan-adjacency-sid { + leaf af { + type uint8; + description + "This leaf describes the protocol-family associated with the + LAN adjacency SID."; + } + + leaf value { + type uint32; + description + "This leaf describes the value of LAN adjacency SID."; + } + + leaf weight { + type uint8; + description + "This leaf describes the weight of the LAN adjacency SID."; + } + + leaf protection-requested { + type boolean; + description + "This leaf describes if the LAN adjacency SID must be protected."; + } + } + } + } + container isis { description "Configuration of the IS-IS routing daemon."; diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c index 1a090c78e..79d79d74b 100644 --- a/zebra/rt_netlink.c +++ b/zebra/rt_netlink.c @@ -223,7 +223,7 @@ static inline bool is_selfroute(int proto) return false; } -static inline int zebra2proto(int proto) +int zebra2proto(int proto) { switch (proto) { case ZEBRA_ROUTE_BABEL: diff --git a/zebra/rt_netlink.h b/zebra/rt_netlink.h index 351f98a2c..8506367ae 100644 --- a/zebra/rt_netlink.h +++ b/zebra/rt_netlink.h @@ -150,6 +150,9 @@ const char *ifa_flags2str(uint32_t flags, char *buf, size_t buflen); const char *nh_flags2str(uint32_t flags, char *buf, size_t buflen); void nl_dump(void *msg, size_t msglen); + +extern int zebra2proto(int proto); + #endif /* NETLINK_DEBUG */ #ifdef __cplusplus diff --git a/zebra/zebra_fpm_netlink.c b/zebra/zebra_fpm_netlink.c index 628d4a2a8..06c45578a 100644 --- a/zebra/zebra_fpm_netlink.c +++ b/zebra/zebra_fpm_netlink.c @@ -253,14 +253,7 @@ static int netlink_route_info_add_nh(struct netlink_route_info *ri, */ static uint8_t netlink_proto_from_route_type(int type) { - switch (type) { - case ZEBRA_ROUTE_KERNEL: - case ZEBRA_ROUTE_CONNECT: - return RTPROT_KERNEL; - - default: - return RTPROT_ZEBRA; - } + return zebra2proto(type); } /* diff --git a/zebra/zebra_netns_id.c b/zebra/zebra_netns_id.c index 73d585c1a..8905b72ec 100644 --- a/zebra/zebra_netns_id.c +++ b/zebra/zebra_netns_id.c @@ -23,6 +23,7 @@ #include "vrf.h" #include "log.h" #include "lib_errors.h" +#include "network.h" #include "zebra/rib.h" #include "zebra/zebra_dplane.h" @@ -73,7 +74,7 @@ static struct nlmsghdr *initiate_nlh(char *buf, unsigned int *seq, int type) nlh->nlmsg_flags = NLM_F_REQUEST; if (type == RTM_NEWNSID) nlh->nlmsg_flags |= NLM_F_ACK; - nlh->nlmsg_seq = *seq = time(NULL); + nlh->nlmsg_seq = *seq = frr_sequence32_next(); return nlh; } |