diff --git a/Makefile.am b/Makefile.am index 494fcd4d56..f204f8a724 100644 --- a/Makefile.am +++ b/Makefile.am @@ -5,7 +5,7 @@ include common.am AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/lib -I$(top_builddir) -I$(top_builddir)/lib AM_CFLAGS = $(WERROR) -DEFS = @DEFS@ -DSYSCONFDIR=\"$(sysconfdir)/\" +DEFS = @DEFS@ -DSYSCONFDIR=\"$(sysconfdir)/\" -DCONFDATE=$(CONFDATE) LIBCAP = @LIBCAP@ EXTRA_DIST = @@ -25,6 +25,14 @@ pkginclude_HEADERS = nodist_pkginclude_HEADERS = dist_examples_DATA = +## libtool, the self-made GNU scourge +## ... this should fix relinking +## ... and AUTOMAKE_DUMMY is needed to prevent automake from treating this +## as overriding the normal targets... +$(AUTOMAKE_DUMMY)install-moduleLTLIBRARIES: install-libLTLIBRARIES +$(AUTOMAKE_DUMMY)install-binPROGRAMS: install-libLTLIBRARIES +$(AUTOMAKE_DUMMY)install-sbinPROGRAMS: install-libLTLIBRARIES + include lib/subdir.am include zebra/subdir.am include qpb/subdir.am diff --git a/babeld/babel_zebra.c b/babeld/babel_zebra.c index 2ec5c3d7c3..337b7b3927 100644 --- a/babeld/babel_zebra.c +++ b/babeld/babel_zebra.c @@ -37,7 +37,6 @@ void babelz_zebra_init(void); /* we must use a pointer because of zclient.c's functions (new, free). */ struct zclient *zclient; -static int zebra_config_write (struct vty *vty); /* Debug types */ static struct { @@ -55,118 +54,24 @@ static struct { {0, 0, NULL} }; -/* Zebra node structure. */ -struct cmd_node zebra_node = -{ - ZEBRA_NODE, - "%s(config-router)# ", - 1 /* vtysh? yes */ -}; - - -/* Zebra route add and delete treatment (ipv6). */ +/* Zebra route add and delete treatment. */ static int -babel_zebra_read_ipv6 (int command, struct zclient *zclient, - zebra_size_t length, vrf_id_t vrf) +babel_zebra_read_route (int command, struct zclient *zclient, + zebra_size_t length, vrf_id_t vrf) { - struct stream *s; - struct zapi_ipv6 api; - unsigned long ifindex = -1; - struct in6_addr nexthop; - struct prefix_ipv6 prefix; + struct zapi_route api; - s = zclient->ibuf; - ifindex = 0; - memset (&nexthop, 0, sizeof (struct in6_addr)); - memset (&api, 0, sizeof(struct zapi_ipv6)); - memset (&prefix, 0, sizeof (struct prefix_ipv6)); + if (zapi_route_decode(zclient->ibuf, &api) < 0) + return -1; - /* Type, flags, message. */ - api.type = stream_getc (s); - api.instance = stream_getw (s); - api.flags = stream_getl (s); - api.message = stream_getc (s); + /* we completely ignore srcdest routes for now. */ + if (CHECK_FLAG(api.message, ZAPI_MESSAGE_SRCPFX)) + return 0; - /* IPv6 prefix. */ - prefix.family = AF_INET6; - prefix.prefixlen = stream_getc (s); - stream_get (&prefix.prefix, s, PSIZE (prefix.prefixlen)); - - /* Nexthop, ifindex, distance, metric. */ - if (CHECK_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP)) { - api.nexthop_num = stream_getc (s); - stream_get (&nexthop, s, sizeof(nexthop)); - } - if (CHECK_FLAG (api.message, ZAPI_MESSAGE_IFINDEX)) { - api.ifindex_num = stream_getc (s); - ifindex = stream_getl (s); - } - if (CHECK_FLAG (api.message, ZAPI_MESSAGE_DISTANCE)) - api.distance = stream_getc (s); - else - api.distance = 0; - if (CHECK_FLAG (api.message, ZAPI_MESSAGE_METRIC)) - api.metric = stream_getl (s); - else - api.metric = 0; - - if (command == ZEBRA_REDISTRIBUTE_IPV6_ADD) - babel_ipv6_route_add(&api, &prefix, ifindex, &nexthop); - else - babel_ipv6_route_delete(&api, &prefix, ifindex); - - return 0; -} - -static int -babel_zebra_read_ipv4 (int command, struct zclient *zclient, - zebra_size_t length, vrf_id_t vrf) -{ - struct stream *s; - struct zapi_ipv4 api; - unsigned long ifindex = -1; - struct in_addr nexthop; - struct prefix_ipv4 prefix; - - s = zclient->ibuf; - ifindex = 0; - memset (&nexthop, 0, sizeof (struct in_addr)); - memset (&api, 0, sizeof(struct zapi_ipv4)); - memset (&prefix, 0, sizeof (struct prefix_ipv4)); - - /* Type, flags, message. */ - api.type = stream_getc (s); - api.instance = stream_getw (s); - api.flags = stream_getl (s); - api.message = stream_getc (s); - - /* IPv6 prefix. */ - prefix.family = AF_INET; - prefix.prefixlen = stream_getc (s); - stream_get (&prefix.prefix, s, PSIZE (prefix.prefixlen)); - - /* Nexthop, ifindex, distance, metric. */ - if (CHECK_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP)) { - api.nexthop_num = stream_getc (s); - stream_get (&nexthop, s, sizeof(nexthop)); - } - if (CHECK_FLAG (api.message, ZAPI_MESSAGE_IFINDEX)) { - api.ifindex_num = stream_getc (s); - ifindex = stream_getl (s); - } - if (CHECK_FLAG (api.message, ZAPI_MESSAGE_DISTANCE)) - api.distance = stream_getc (s); - else - api.distance = 0; - if (CHECK_FLAG (api.message, ZAPI_MESSAGE_METRIC)) - api.metric = stream_getl (s); - else - api.metric = 0; - - if (command == ZEBRA_REDISTRIBUTE_IPV4_ADD) { - babel_ipv4_route_add(&api, &prefix, ifindex, &nexthop); + if (command == ZEBRA_REDISTRIBUTE_ROUTE_ADD) { + babel_route_add(&api); } else { - babel_ipv4_route_delete(&api, &prefix, ifindex); + babel_route_delete(&api); } return 0; @@ -342,12 +247,9 @@ void babelz_zebra_init(void) zclient->interface_down = babel_interface_down; zclient->interface_address_add = babel_interface_address_add; zclient->interface_address_delete = babel_interface_address_delete; - zclient->redistribute_route_ipv4_add = babel_zebra_read_ipv4; - zclient->redistribute_route_ipv4_del = babel_zebra_read_ipv4; - zclient->redistribute_route_ipv6_add = babel_zebra_read_ipv6; - zclient->redistribute_route_ipv6_del = babel_zebra_read_ipv6; + zclient->redistribute_route_add = babel_zebra_read_route; + zclient->redistribute_route_del = babel_zebra_read_route; - install_node (&zebra_node, zebra_config_write); install_element(BABEL_NODE, &babel_redistribute_type_cmd); install_element(ENABLE_NODE, &debug_babel_cmd); install_element(ENABLE_NODE, &no_debug_babel_cmd); @@ -357,23 +259,6 @@ void babelz_zebra_init(void) install_element(VIEW_NODE, &show_debugging_babel_cmd); } -static int -zebra_config_write (struct vty *vty) -{ - if (! zclient->enable) - { - vty_out (vty, "no router zebra\n"); - return 1; - } - else if (! vrf_bitmap_check (zclient->redist[AFI_IP][ZEBRA_ROUTE_BABEL], VRF_DEFAULT)) - { - vty_out (vty, "router zebra\n"); - vty_out (vty, " no redistribute babel\n"); - return 1; - } - return 0; -} - void babel_zebra_close_connexion(void) { diff --git a/babeld/babeld.c b/babeld/babeld.c index f995745e41..207c37d9b1 100644 --- a/babeld/babeld.c +++ b/babeld/babeld.c @@ -331,8 +331,8 @@ babel_main_loop(struct thread *thread) /* if there is no timeout, we must wait. */ if(timeval_compare(&tv, &babel_now) > 0) { timeval_minus(&tv, &tv, &babel_now); - debugf(BABEL_DEBUG_TIMEOUT, "babel main loop : timeout: %ld msecs", - tv.tv_sec * 1000 + tv.tv_usec / 1000); + debugf(BABEL_DEBUG_TIMEOUT, "babel main loop : timeout: %lld msecs", + (long long)tv.tv_sec * 1000 + tv.tv_usec / 1000); /* it happens often to have less than 1 ms, it's bad. */ timeval_add_msec(&tv, &tv, 300); babel_set_timer(&tv); diff --git a/babeld/kernel.c b/babeld/kernel.c index 26860f3bae..394d7b1e81 100644 --- a/babeld/kernel.c +++ b/babeld/kernel.c @@ -51,13 +51,8 @@ THE SOFTWARE. static int -kernel_route_v4(int add, const unsigned char *pref, unsigned short plen, - const unsigned char *gate, int ifindex, - unsigned int metric); -static int -kernel_route_v6(int add, const unsigned char *pref, unsigned short plen, - const unsigned char *gate, int ifindex, - unsigned int metric); +zebra_route(int add, int familt, const unsigned char *pref, unsigned short plen, + const unsigned char *gate, int ifindex, unsigned int metric); int kernel_interface_operational(struct interface *interface) @@ -84,7 +79,7 @@ kernel_route(int operation, const unsigned char *pref, unsigned short plen, unsigned int newmetric) { int rc; - int ipv4; + int family; /* Check that the protocol family is consistent. */ if(plen >= 96 && v4mapped(pref)) { @@ -92,46 +87,37 @@ kernel_route(int operation, const unsigned char *pref, unsigned short plen, errno = EINVAL; return -1; } - ipv4 = 1; + family = AF_INET; } else { if(v4mapped(gate)) { errno = EINVAL; return -1; } - ipv4 = 0; + family = AF_INET6; } switch (operation) { case ROUTE_ADD: - return ipv4 ? - kernel_route_v4(1, pref, plen, gate, ifindex, metric): - kernel_route_v6(1, pref, plen, gate, ifindex, metric); + return zebra_route(1, family, pref, plen, gate, ifindex, metric); break; case ROUTE_FLUSH: - return ipv4 ? - kernel_route_v4(0, pref, plen, gate, ifindex, metric): - kernel_route_v6(0, pref, plen, gate, ifindex, metric); + return zebra_route(0, family, pref, plen, gate, ifindex, metric); break; case ROUTE_MODIFY: if(newmetric == metric && memcmp(newgate, gate, 16) == 0 && newifindex == ifindex) return 0; debugf(BABEL_DEBUG_ROUTE, "Modify route: delete old; add new."); - rc = ipv4 ? - kernel_route_v4(0, pref, plen, gate, ifindex, metric): - kernel_route_v6(0, pref, plen, gate, ifindex, metric); - + rc = zebra_route(0, family, pref, plen, gate, ifindex, metric); if (rc < 0) return -1; - rc = ipv4 ? - kernel_route_v4(1, pref, plen, newgate, newifindex, newmetric): - kernel_route_v6(1, pref, plen, newgate, newifindex, newmetric); - + rc = zebra_route(1, family, pref, plen, newgate, newifindex, + newmetric); return rc; break; default: - zlog_err("this should never appens (false value - kernel_route)"); + zlog_err("this should never happen (false value - kernel_route)"); assert(0); exit(1); break; @@ -139,110 +125,81 @@ kernel_route(int operation, const unsigned char *pref, unsigned short plen, } static int -kernel_route_v4(int add, - const unsigned char *pref, unsigned short plen, - const unsigned char *gate, int ifindex, unsigned int metric) +zebra_route(int add, int family, const unsigned char *pref, unsigned short plen, + const unsigned char *gate, int ifindex, unsigned int metric) { struct zapi_route api; /* quagga's communication system */ struct prefix quagga_prefix; /* quagga's prefix */ - struct in_addr babel_prefix_addr; /* babeld's prefix addr */ - struct nexthop nexthop; /* next router to go */ - struct nexthop *nexthop_pointer = &nexthop; /* it's an array! */ + union g_addr babel_prefix_addr; /* babeld's prefix addr */ + struct zapi_nexthop *api_nh; /* next router to go - no ECMP */ + + api_nh = &api.nexthops[0]; /* convert to be understandable by quagga */ /* convert given addresses */ - uchar_to_inaddr(&babel_prefix_addr, pref); - uchar_to_inaddr(&nexthop.gate.ipv4, gate); + switch (family) { + case AF_INET: + uchar_to_inaddr(&babel_prefix_addr.ipv4, pref); + break; + case AF_INET6: + uchar_to_in6addr(&babel_prefix_addr.ipv6, pref); + break; + } /* make prefix structure */ memset (&quagga_prefix, 0, sizeof(quagga_prefix)); - quagga_prefix.family = AF_INET; - IPV4_ADDR_COPY (&quagga_prefix.u.prefix4, &babel_prefix_addr); - quagga_prefix.prefixlen = plen - 96; /* our plen is for v4mapped's addr */ + quagga_prefix.family = family; + switch (family) { + case AF_INET: + IPV4_ADDR_COPY (&quagga_prefix.u.prefix4, &babel_prefix_addr.ipv4); + /* our plen is for v4mapped's addr */ + quagga_prefix.prefixlen = plen - 96; + break; + case AF_INET6: + IPV6_ADDR_COPY (&quagga_prefix.u.prefix6, &babel_prefix_addr.ipv6); + quagga_prefix.prefixlen = plen; + break; + } apply_mask(&quagga_prefix); memset(&api, 0, sizeof(api)); api.type = ZEBRA_ROUTE_BABEL; - api.flags = 0; - api.message = 0; - api.instance = 0; api.safi = SAFI_UNICAST; api.vrf_id = VRF_DEFAULT; + api.prefix = quagga_prefix; - SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP); if(metric >= KERNEL_INFINITY) { api.flags = ZEBRA_FLAG_REJECT; - api.nexthop_num = 0; } else { + SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP); api.nexthop_num = 1; - api.nexthop = &nexthop_pointer; - nexthop.ifindex = ifindex; - if (IPV4_ADDR_SAME (&nexthop.gate.ipv4, &quagga_prefix.u.prefix4) && - quagga_prefix.prefixlen == 32) { - nexthop.type = NEXTHOP_TYPE_IFINDEX; - } else { - nexthop.type = NEXTHOP_TYPE_IPV4_IFINDEX; + api_nh->ifindex = ifindex; + + switch (family) { + case AF_INET: + uchar_to_inaddr(&api_nh->gate.ipv4, gate); + if (IPV4_ADDR_SAME (&api_nh->gate.ipv4, &quagga_prefix.u.prefix4) && + quagga_prefix.prefixlen == 32) { + api_nh->type = NEXTHOP_TYPE_IFINDEX; + } else { + api_nh->type = NEXTHOP_TYPE_IPV4_IFINDEX; + } + break; + case AF_INET6: + uchar_to_in6addr(&api_nh->gate.ipv6, gate); + /* difference to IPv4: always leave the linklocal as nexthop */ + api_nh->type = NEXTHOP_TYPE_IPV6_IFINDEX; + break; } SET_FLAG(api.message, ZAPI_MESSAGE_METRIC); api.metric = metric; } - debugf(BABEL_DEBUG_ROUTE, "%s route (ipv4) to zebra", - add ? "adding" : "removing" ); - return zapi_route (add ? ZEBRA_IPV4_ROUTE_ADD : - ZEBRA_IPV4_ROUTE_DELETE, - zclient, &quagga_prefix, NULL, &api); -} - -static int -kernel_route_v6(int add, const unsigned char *pref, unsigned short plen, - const unsigned char *gate, int ifindex, unsigned int metric) -{ - struct zapi_route api; /* quagga's communication system */ - struct prefix quagga_prefix; /* quagga's prefix */ - struct in6_addr babel_prefix_addr; /* babeld's prefix addr */ - struct nexthop nexthop; /* next router to go */ - struct nexthop *nexthop_pointer = &nexthop; - - /* convert to be understandable by quagga */ - /* convert given addresses */ - uchar_to_in6addr(&babel_prefix_addr, pref); - uchar_to_in6addr(&nexthop.gate.ipv6, gate); - - /* make prefix structure */ - memset (&quagga_prefix, 0, sizeof(quagga_prefix)); - quagga_prefix.family = AF_INET6; - IPV6_ADDR_COPY (&quagga_prefix.u.prefix6, &babel_prefix_addr); - quagga_prefix.prefixlen = plen; - apply_mask(&quagga_prefix); - - memset(&api, 0, sizeof(api)); - api.type = ZEBRA_ROUTE_BABEL; - api.flags = 0; - api.message = 0; - api.instance = 0; - api.safi = SAFI_UNICAST; - api.vrf_id = VRF_DEFAULT; - - if(metric >= KERNEL_INFINITY) { - api.flags = ZEBRA_FLAG_REJECT; - api.nexthop_num = 0; - } else { - SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP); - api.nexthop_num = 1; - api.nexthop = &nexthop_pointer; - nexthop.ifindex = ifindex; - /* difference to IPv4: always leave the linklocal as nexthop */ - nexthop.type = NEXTHOP_TYPE_IPV6_IFINDEX; - SET_FLAG(api.message, ZAPI_MESSAGE_METRIC); - api.metric = metric; - } - - debugf(BABEL_DEBUG_ROUTE, "%s route (ipv6) to zebra", - add ? "adding" : "removing" ); - return zapi_route (add ? ZEBRA_IPV6_ROUTE_ADD : - ZEBRA_IPV6_ROUTE_DELETE, - zclient, &quagga_prefix, NULL, &api); + debugf(BABEL_DEBUG_ROUTE, "%s route (%s) to zebra", + add ? "adding" : "removing", + (family == AF_INET) ? "ipv4" : "ipv6"); + return zclient_route_send (add ? ZEBRA_ROUTE_ADD : ZEBRA_ROUTE_DELETE, + zclient, &api); } int diff --git a/babeld/message.c b/babeld/message.c index 5990373b69..e31d5de5df 100644 --- a/babeld/message.c +++ b/babeld/message.c @@ -391,7 +391,7 @@ parse_packet(const unsigned char *from, struct interface *ifp, } else if(type == MESSAGE_HELLO) { unsigned short seqno, interval; int changed; - unsigned int timestamp; + unsigned int timestamp = 0; DO_NTOHS(seqno, message + 4); DO_NTOHS(interval, message + 6); debugf(BABEL_DEBUG_COMMON,"Received hello %d (%d) from %s on %s.", diff --git a/babeld/xroute.c b/babeld/xroute.c index 2e123564ea..88e9479e4b 100644 --- a/babeld/xroute.c +++ b/babeld/xroute.c @@ -43,63 +43,54 @@ static int numxroutes = 0, maxxroutes = 0; /* Add redistributed route to Babel table. */ int -babel_ipv4_route_add (struct zapi_ipv4 *api, struct prefix_ipv4 *prefix, - unsigned int ifindex, struct in_addr *nexthop) +babel_route_add (struct zapi_route *api) { unsigned char uchar_prefix[16]; - inaddr_to_uchar(uchar_prefix, &prefix->prefix); - debugf(BABEL_DEBUG_ROUTE, "Adding new ipv4 route coming from Zebra."); - xroute_add_new_route(uchar_prefix, prefix->prefixlen + 96, - api->metric, ifindex, 0, 1); + switch (api->prefix.family) { + case AF_INET: + inaddr_to_uchar(uchar_prefix, &api->prefix.u.prefix4); + debugf(BABEL_DEBUG_ROUTE, "Adding new ipv4 route coming from Zebra."); + xroute_add_new_route(uchar_prefix, api->prefix.prefixlen + 96, + api->metric, api->nexthops[0].ifindex, 0, 1); + break; + case AF_INET6: + in6addr_to_uchar(uchar_prefix, &api->prefix.u.prefix6); + debugf(BABEL_DEBUG_ROUTE, "Adding new ipv6 route coming from Zebra."); + xroute_add_new_route(uchar_prefix, api->prefix.prefixlen, + api->metric, api->nexthops[0].ifindex, 0, 1); + break; + } + return 0; } /* Remove redistributed route from Babel table. */ int -babel_ipv4_route_delete (struct zapi_ipv4 *api, struct prefix_ipv4 *prefix, - unsigned int ifindex) +babel_route_delete (struct zapi_route *api) { unsigned char uchar_prefix[16]; struct xroute *xroute = NULL; - inaddr_to_uchar(uchar_prefix, &prefix->prefix); - xroute = find_xroute(uchar_prefix, prefix->prefixlen + 96); - if (xroute != NULL) { - debugf(BABEL_DEBUG_ROUTE, "Removing ipv4 route (from zebra)."); - flush_xroute(xroute); + switch (api->prefix.family) { + case AF_INET: + inaddr_to_uchar(uchar_prefix, &api->prefix.u.prefix4); + xroute = find_xroute(uchar_prefix, api->prefix.prefixlen + 96); + if (xroute != NULL) { + debugf(BABEL_DEBUG_ROUTE, "Removing ipv4 route (from zebra)."); + flush_xroute(xroute); + } + break; + case AF_INET6: + in6addr_to_uchar(uchar_prefix, &api->prefix.u.prefix6); + xroute = find_xroute(uchar_prefix, api->prefix.prefixlen); + if (xroute != NULL) { + debugf(BABEL_DEBUG_ROUTE, "Removing ipv6 route (from zebra)."); + flush_xroute(xroute); + } + break; } - return 0; -} -/* Add redistributed route to Babel table. */ -int -babel_ipv6_route_add (struct zapi_ipv6 *api, struct prefix_ipv6 *prefix, - unsigned int ifindex, struct in6_addr *nexthop) -{ - unsigned char uchar_prefix[16]; - - in6addr_to_uchar(uchar_prefix, &prefix->prefix); - debugf(BABEL_DEBUG_ROUTE, "Adding new route coming from Zebra."); - xroute_add_new_route(uchar_prefix, prefix->prefixlen, api->metric, ifindex, - 0, 1); - return 0; -} - -/* Remove redistributed route from Babel table. */ -int -babel_ipv6_route_delete (struct zapi_ipv6 *api, struct prefix_ipv6 *prefix, - unsigned int ifindex) -{ - unsigned char uchar_prefix[16]; - struct xroute *xroute = NULL; - - in6addr_to_uchar(uchar_prefix, &prefix->prefix); - xroute = find_xroute(uchar_prefix, prefix->prefixlen); - if (xroute != NULL) { - debugf(BABEL_DEBUG_ROUTE, "Removing route (from zebra)."); - flush_xroute(xroute); - } return 0; } diff --git a/babeld/xroute.h b/babeld/xroute.h index 27899e62a1..59afccb590 100644 --- a/babeld/xroute.h +++ b/babeld/xroute.h @@ -36,14 +36,8 @@ struct xroute_stream; struct xroute *find_xroute(const unsigned char *prefix, unsigned char plen); void flush_xroute(struct xroute *xroute); -int babel_ipv4_route_add (struct zapi_ipv4 *api, struct prefix_ipv4 *prefix, - unsigned int ifindex, struct in_addr *nexthop); -int babel_ipv4_route_delete (struct zapi_ipv4 *api, struct prefix_ipv4 *prefix, - unsigned int ifindex); -int babel_ipv6_route_add (struct zapi_ipv6 *api, struct prefix_ipv6 *prefix, - unsigned int ifindex, struct in6_addr *nexthop); -int babel_ipv6_route_delete (struct zapi_ipv6 *api, struct prefix_ipv6 *prefix, - unsigned int ifindex); +int babel_route_add (struct zapi_route *api); +int babel_route_delete (struct zapi_route *api); int xroutes_estimate(void); struct xroute_stream *xroute_stream(void); struct xroute *xroute_stream_next(struct xroute_stream *stream); diff --git a/bgpd/bgp_attr.h b/bgpd/bgp_attr.h index 324813c085..4dd38459f8 100644 --- a/bgpd/bgp_attr.h +++ b/bgpd/bgp_attr.h @@ -72,7 +72,7 @@ struct bgp_attr_encap_subtlv { unsigned long refcnt; uint16_t type; uint16_t length; - uint8_t value[1]; /* will be extended */ + uint8_t value[0]; /* will be extended */ }; #if ENABLE_BGP_VNC diff --git a/bgpd/bgp_main.c b/bgpd/bgp_main.c index 3bf9ea02d5..fa8c45b004 100644 --- a/bgpd/bgp_main.c +++ b/bgpd/bgp_main.c @@ -219,9 +219,6 @@ static __attribute__((__noreturn__)) void bgp_exit(int status) memset(bm, 0, sizeof(*bm)); frr_fini(); - - if (bgp_debug_count()) - log_memstats_stderr("bgpd"); exit(status); } diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index e12c6fb7d8..46227cec79 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -20,6 +20,7 @@ */ #include +#include #include "prefix.h" #include "linklist.h" @@ -2087,7 +2088,7 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_node *rn, * to do this upon changes to best path except of the label index * changes. */ - if (safi == SAFI_UNICAST) { + if (bgp->allocate_mpls_labels[afi][safi]) { if (new_select) { if (!old_select || bgp_label_index_differs(new_select, old_select) @@ -2108,8 +2109,11 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_node *rn, } else bgp_register_for_label(rn, new_select); } - } else if (CHECK_FLAG(rn->flags, BGP_NODE_REGISTERED_FOR_LABEL)) + } else if (CHECK_FLAG(rn->flags, BGP_NODE_REGISTERED_FOR_LABEL)) { bgp_unregister_for_label(rn); + } + } else if (CHECK_FLAG(rn->flags, BGP_NODE_REGISTERED_FOR_LABEL)) { + bgp_unregister_for_label(rn); } /* If best route remains the same and this is not due to user-initiated @@ -6153,8 +6157,7 @@ DEFUN (no_ipv6_aggregate_address, /* Redistribute route treatment. */ void bgp_redistribute_add(struct bgp *bgp, struct prefix *p, - const struct in_addr *nexthop, - const struct in6_addr *nexthop6, unsigned int ifindex, + const union g_addr *nexthop, unsigned int ifindex, u_int32_t metric, u_char type, u_short instance, route_tag_t tag) { @@ -6170,14 +6173,17 @@ void bgp_redistribute_add(struct bgp *bgp, struct prefix *p, /* Make default attribute. */ bgp_attr_default_set(&attr, BGP_ORIGIN_INCOMPLETE); - if (nexthop) - attr.nexthop = *nexthop; - attr.nh_ifindex = ifindex; - - if (nexthop6) { - attr.mp_nexthop_global = *nexthop6; - attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL; + if (nexthop) { + switch (p->family) { + case AF_INET: + attr.nexthop = nexthop->ipv4; + break; + case AF_INET6: + attr.mp_nexthop_global = nexthop->ipv6; + attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL; + } } + attr.nh_ifindex = ifindex; attr.med = metric; attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC); @@ -8087,7 +8093,8 @@ static int bgp_show_community_list(struct vty *vty, struct bgp *bgp, static int bgp_show_prefix_longer(struct vty *vty, struct bgp *bgp, const char *prefix, afi_t afi, safi_t safi, enum bgp_show_type type); -static int bgp_show_regexp(struct vty *vty, const char *regstr, afi_t afi, +static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, + const char *regstr, afi_t afi, safi_t safi, enum bgp_show_type type); static int bgp_show_community(struct vty *vty, struct bgp *bgp, const char *comstr, int exact, afi_t afi, @@ -8905,32 +8912,28 @@ DEFUN (show_ip_bgp_large_community, static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi); -/* BGP route print out function. */ + +/* BGP route print out function without JSON */ DEFUN (show_ip_bgp, show_ip_bgp_cmd, "show [ip] bgp [ VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]]\ - [<\ - cidr-only\ - |dampening \ - |route-map WORD\ - |prefix-list WORD\ - |filter-list WORD\ - |statistics\ - |community [ [exact-match]]\ - |community-list <(1-500)|WORD> [exact-match]\ - |A.B.C.D/M longer-prefixes\ - |X:X::X:X/M longer-prefixes>\ - ] [json]", + \ + |route-map WORD\ + |prefix-list WORD\ + |filter-list WORD\ + |statistics\ + |community [exact-match]\ + |community-list <(1-500)|WORD> [exact-match]\ + |A.B.C.D/M longer-prefixes\ + |X:X::X:X/M longer-prefixes\ + >", SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR BGP_SAFI_WITH_LABEL_HELP_STR - "Display only routes with non-natural netmasks\n" "Display detailed information about dampening\n" - "Display flap statistics of routes\n" - "Display paths suppressed due to dampening\n" "Display detail of configured dampening parameters\n" "Display routes matching the route-map\n" "A route-map to match on\n" @@ -8953,13 +8956,11 @@ DEFUN (show_ip_bgp, "IPv4 prefix\n" "Display route and more specific routes\n" "IPv6 prefix\n" - "Display route and more specific routes\n" - JSON_STR) + "Display route and more specific routes\n") { afi_t afi = AFI_IP6; safi_t safi = SAFI_UNICAST; int exact_match = 0; - enum bgp_show_type sh_type = bgp_show_type_normal; struct bgp *bgp = NULL; int idx = 0; int idx_community_type = 0; @@ -8969,23 +8970,8 @@ DEFUN (show_ip_bgp, if (!idx) return CMD_WARNING; - int uj = use_json(argc, argv); - if (uj) - argc--; - - if (argv_find(argv, argc, "cidr-only", &idx)) - return bgp_show(vty, bgp, afi, safi, bgp_show_type_cidr_only, - NULL, uj); - if (argv_find(argv, argc, "dampening", &idx)) { - if (argv_find(argv, argc, "dampened-paths", &idx)) - return bgp_show(vty, bgp, afi, safi, - bgp_show_type_dampend_paths, NULL, uj); - else if (argv_find(argv, argc, "flap-statistics", &idx)) - return bgp_show(vty, bgp, afi, safi, - bgp_show_type_flap_statistics, NULL, - uj); - else if (argv_find(argv, argc, "parameters", &idx)) + if (argv_find(argv, argc, "parameters", &idx)) return bgp_show_dampening_parameters(vty, afi, safi); } @@ -9017,10 +9003,6 @@ DEFUN (show_ip_bgp, return bgp_show_community(vty, bgp, argv[idx_community_type]->arg, exact_match, afi, safi); } - /* show all communities */ - else - return bgp_show(vty, bgp, afi, safi, - bgp_show_type_community_all, NULL, uj); } if (argv_find(argv, argc, "community-list", &idx)) { @@ -9037,6 +9019,66 @@ DEFUN (show_ip_bgp, safi, bgp_show_type_prefix_longer); + return CMD_WARNING; +} + +/* BGP route print out function with JSON */ +DEFUN (show_ip_bgp_json, + show_ip_bgp_json_cmd, + "show [ip] bgp [ VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]]\ + [<\ + cidr-only\ + |dampening \ + |community \ + >] [json]", + SHOW_STR + IP_STR + BGP_STR + BGP_INSTANCE_HELP_STR + BGP_AFI_HELP_STR + BGP_SAFI_WITH_LABEL_HELP_STR + "Display only routes with non-natural netmasks\n" + "Display detailed information about dampening\n" + "Display flap statistics of routes\n" + "Display paths suppressed due to dampening\n" + "Display routes matching the communities\n" + JSON_STR) +{ + afi_t afi = AFI_IP6; + safi_t safi = SAFI_UNICAST; + enum bgp_show_type sh_type = bgp_show_type_normal; + struct bgp *bgp = NULL; + int idx = 0; + + bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi, + &bgp); + if (!idx) + return CMD_WARNING; + + int uj = use_json(argc, argv); + if (uj) + argc--; + + if (argv_find(argv, argc, "cidr-only", &idx)) + return bgp_show(vty, bgp, afi, safi, bgp_show_type_cidr_only, + NULL, uj); + + if (argv_find(argv, argc, "dampening", &idx)) { + if (argv_find(argv, argc, "dampened-paths", &idx)) + return bgp_show(vty, bgp, afi, safi, + bgp_show_type_dampend_paths, NULL, uj); + else if (argv_find(argv, argc, "flap-statistics", &idx)) + return bgp_show(vty, bgp, afi, safi, + bgp_show_type_flap_statistics, NULL, + uj); + } + + if (argv_find(argv, argc, "community", &idx)) { + /* show all communities */ + return bgp_show(vty, bgp, afi, safi, + bgp_show_type_community_all, NULL, uj); + } + if (safi == SAFI_MPLS_VPN) return bgp_show_mpls_vpn(vty, afi, NULL, bgp_show_type_normal, NULL, 0, uj); @@ -9146,7 +9188,7 @@ DEFUN (show_ip_bgp_regexp, idx++; char *regstr = argv_concat(argv, argc, idx); - int rc = bgp_show_regexp(vty, (const char *)regstr, afi, safi, + int rc = bgp_show_regexp(vty, bgp, (const char *)regstr, afi, safi, bgp_show_type_regexp); XFREE(MTYPE_TMP, regstr); return rc; @@ -9181,7 +9223,8 @@ DEFUN (show_ip_bgp_instance_all, return CMD_SUCCESS; } -static int bgp_show_regexp(struct vty *vty, const char *regstr, afi_t afi, +static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, + const char *regstr, afi_t afi, safi_t safi, enum bgp_show_type type) { regex_t *regex; @@ -9193,7 +9236,7 @@ static int bgp_show_regexp(struct vty *vty, const char *regstr, afi_t afi, return CMD_WARNING; } - rc = bgp_show(vty, NULL, afi, safi, type, regex, 0); + rc = bgp_show(vty, bgp, afi, safi, type, regex, 0); bgp_regex_free(regex); return rc; } @@ -9399,6 +9442,7 @@ static const char *table_stats_strs[] = { struct bgp_table_stats { struct bgp_table *table; unsigned long long counts[BGP_STATS_MAX]; + double total_space; }; #if 0 @@ -9467,8 +9511,8 @@ static int bgp_table_stats_walker(struct thread *t) ts->counts[BGP_STATS_UNAGGREGATEABLE]++; /* announced address space */ if (space) - ts->counts[BGP_STATS_SPACE] += - 1 << (space - rn->p.prefixlen); + ts->total_space += pow(2.0, + space - rn->p.prefixlen); } else if (prn->info) ts->counts[BGP_STATS_MAX_AGGREGATEABLE]++; @@ -9578,31 +9622,26 @@ static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi, break; case BGP_STATS_SPACE: vty_out(vty, "%-30s: ", table_stats_strs[i]); - vty_out(vty, "%12llu\n", ts.counts[i]); - if (ts.counts[BGP_STATS_MAXBITLEN] < 9) - break; - vty_out(vty, "%30s: ", "%% announced "); - vty_out(vty, "%12.2f\n", - 100 * (float)ts.counts[BGP_STATS_SPACE] - / (float)((uint64_t)1UL - << ts.counts - [BGP_STATS_MAXBITLEN])); - vty_out(vty, "%30s: ", "/8 equivalent "); - vty_out(vty, "%12.2f\n", - (float)ts.counts[BGP_STATS_SPACE] - / (float)(1UL - << (ts.counts - [BGP_STATS_MAXBITLEN] - - 8))); - if (ts.counts[BGP_STATS_MAXBITLEN] < 25) - break; - vty_out(vty, "%30s: ", "/24 equivalent "); - vty_out(vty, "%12.2f", - (float)ts.counts[BGP_STATS_SPACE] - / (float)(1UL - << (ts.counts - [BGP_STATS_MAXBITLEN] - - 24))); + vty_out(vty, "%12g\n", ts.total_space); + + if (afi == AFI_IP6) { + vty_out(vty, "%30s: ", "/32 equivalent "); + vty_out(vty, "%12g\n", + ts.total_space * pow(2.0, -128+32)); + vty_out(vty, "%30s: ", "/48 equivalent "); + vty_out(vty, "%12g\n", + ts.total_space * pow(2.0, -128+48)); + } else { + vty_out(vty, "%30s: ", "% announced "); + vty_out(vty, "%12.2f\n", + ts.total_space * 100. * pow(2.0, -32)); + vty_out(vty, "%30s: ", "/8 equivalent "); + vty_out(vty, "%12.2f\n", + ts.total_space * pow(2.0, -32+8)); + vty_out(vty, "%30s: ", "/24 equivalent "); + vty_out(vty, "%12.2f\n", + ts.total_space * pow(2.0, -32+24)); + } break; default: vty_out(vty, "%-30s: ", table_stats_strs[i]); @@ -11332,6 +11371,7 @@ void bgp_route_init(void) /* IPv4 labeled-unicast configuration. */ install_element(VIEW_NODE, &show_ip_bgp_instance_all_cmd); install_element(VIEW_NODE, &show_ip_bgp_cmd); + install_element(VIEW_NODE, &show_ip_bgp_json_cmd); install_element(VIEW_NODE, &show_ip_bgp_route_cmd); install_element(VIEW_NODE, &show_ip_bgp_regexp_cmd); diff --git a/bgpd/bgp_route.h b/bgpd/bgp_route.h index b9d7957c68..d2309d4d05 100644 --- a/bgpd/bgp_route.h +++ b/bgpd/bgp_route.h @@ -22,6 +22,7 @@ #define _QUAGGA_BGP_ROUTE_H #include "queue.h" +#include "nexthop.h" #include "bgp_table.h" struct bgp_nexthop_cache; @@ -326,8 +327,7 @@ extern int bgp_nlri_parse_ip(struct peer *, struct attr *, struct bgp_nlri *); extern int bgp_maximum_prefix_overflow(struct peer *, afi_t, safi_t, int); extern void bgp_redistribute_add(struct bgp *, struct prefix *, - const struct in_addr *, - const struct in6_addr *, unsigned int ifindex, + const union g_addr *, unsigned int ifindex, u_int32_t, u_char, u_short, route_tag_t); extern void bgp_redistribute_delete(struct bgp *, struct prefix *, u_char, u_short); diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index d9117deaf5..b9fa844ff9 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -7081,26 +7081,6 @@ static int bgp_show_summary(struct vty *vty, struct bgp *bgp, int afi, int safi, return CMD_SUCCESS; } -/* - * Return if we have a peer configured to use this afi/safi - */ -static int bgp_show_summary_afi_safi_peer_exists(struct bgp *bgp, int afi, - int safi) -{ - struct listnode *node; - struct peer *peer; - - for (ALL_LIST_ELEMENTS_RO(bgp->peer, node, peer)) { - if (!CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE)) - continue; - - if (peer->afc[afi][safi]) - return 1; - } - - return 0; -} - static void bgp_show_summary_afi_safi(struct vty *vty, struct bgp *bgp, int afi, int safi, u_char use_json, json_object *json) @@ -7119,8 +7099,7 @@ static void bgp_show_summary_afi_safi(struct vty *vty, struct bgp *bgp, int afi, if (safi_wildcard) safi = 1; /* SAFI_UNICAST */ while (safi < SAFI_MAX) { - if (bgp_show_summary_afi_safi_peer_exists(bgp, afi, - safi)) { + if (bgp_afi_safi_peer_exists(bgp, afi, safi)) { json_output = true; if (is_wildcard) { /* diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c index 2fc75ea5a2..9a092404d5 100644 --- a/bgpd/bgp_zebra.c +++ b/bgpd/bgp_zebra.c @@ -58,11 +58,6 @@ /* All information about zebra. */ struct zclient *zclient = NULL; -/* Growable buffer for nexthops sent to zebra */ -struct stream *bgp_nexthop_buf = NULL; -struct stream *bgp_ifindices_buf = NULL; -struct stream *bgp_label_buf = NULL; - /* These array buffers are used in making a copy of the attributes for route-map apply. Arrays are being used here to minimize mallocs and frees for the temporary copy of the attributes. @@ -559,75 +554,36 @@ static int bgp_interface_vrf_update(int command, struct zclient *zclient, } /* Zebra route add and delete treatment. */ -static int zebra_read_ipv4(int command, struct zclient *zclient, - zebra_size_t length, vrf_id_t vrf_id) +static int zebra_read_route(int command, struct zclient *zclient, + zebra_size_t length, vrf_id_t vrf_id) { - struct stream *s; - struct zapi_ipv4 api; - struct in_addr nexthop; - struct prefix_ipv4 p; + struct zapi_route api; + union g_addr nexthop; unsigned int ifindex; - int i; + int add, i; struct bgp *bgp; bgp = bgp_lookup_by_vrf_id(vrf_id); if (!bgp) return 0; - s = zclient->ibuf; - nexthop.s_addr = 0; + if (zapi_route_decode(zclient->ibuf, &api) < 0) + return -1; - /* Type, flags, message. */ - api.type = stream_getc(s); - api.instance = stream_getw(s); - api.flags = stream_getl(s); - api.message = stream_getc(s); + /* we completely ignore srcdest routes for now. */ + if (CHECK_FLAG(api.message, ZAPI_MESSAGE_SRCPFX)) + return 0; - /* IPv4 prefix. */ - memset(&p, 0, sizeof(struct prefix_ipv4)); - p.family = AF_INET; - p.prefixlen = MIN(IPV4_MAX_PREFIXLEN, stream_getc(s)); - stream_get(&p.prefix, s, PSIZE(p.prefixlen)); + /* ignore link-local address. */ + if (api.prefix.family == AF_INET6 + && IN6_IS_ADDR_LINKLOCAL(&api.prefix.u.prefix6)) + return 0; - /* Nexthop, ifindex, distance, metric. */ - if (CHECK_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP)) { - api.nexthop_num = stream_getc(s); - nexthop.s_addr = stream_get_ipv4(s); - } - - if (CHECK_FLAG(api.message, ZAPI_MESSAGE_IFINDEX)) { - api.ifindex_num = stream_getc(s); - ifindex = stream_getl(s); /* ifindex, unused */ - } else { - ifindex = 0; - } - - if (CHECK_FLAG(api.message, ZAPI_MESSAGE_DISTANCE)) - api.distance = stream_getc(s); - - if (CHECK_FLAG(api.message, ZAPI_MESSAGE_METRIC)) - api.metric = stream_getl(s); - else - api.metric = 0; - - if (CHECK_FLAG(api.message, ZAPI_MESSAGE_TAG)) - api.tag = stream_getl(s); - else - api.tag = 0; - - if (command == ZEBRA_REDISTRIBUTE_IPV4_ADD) { - if (bgp_debug_zebra((struct prefix *)&p)) { - char buf[2][INET_ADDRSTRLEN]; - zlog_debug( - "Rx IPv4 route add VRF %u %s[%d] %s/%d nexthop %s metric %u tag %" ROUTE_TAG_PRI, - vrf_id, zebra_route_string(api.type), - api.instance, inet_ntop(AF_INET, &p.prefix, - buf[0], sizeof(buf[0])), - p.prefixlen, inet_ntop(AF_INET, &nexthop, - buf[1], sizeof(buf[1])), - api.metric, api.tag); - } + nexthop = api.nexthops[0].gate; + ifindex = api.nexthops[0].ifindex; + add = (command == ZEBRA_REDISTRIBUTE_ROUTE_ADD); + if (add) { /* * The ADD message is actually an UPDATE and there is no * explicit DEL @@ -639,156 +595,30 @@ static int zebra_read_ipv4(int command, struct zclient *zclient, */ for (i = 0; i < ZEBRA_ROUTE_MAX; i++) { if (i != api.type) - bgp_redistribute_delete(bgp, - (struct prefix *)&p, i, + bgp_redistribute_delete(bgp, &api.prefix, i, api.instance); } /* Now perform the add/update. */ - bgp_redistribute_add(bgp, (struct prefix *)&p, &nexthop, NULL, - ifindex, api.metric, api.type, - api.instance, api.tag); - } else if (command == ZEBRA_REDISTRIBUTE_IPV4_DEL) { - if (bgp_debug_zebra((struct prefix *)&p)) { - char buf[2][INET_ADDRSTRLEN]; - zlog_debug( - "Rx IPv4 route delete VRF %u %s[%d] %s/%d " - "nexthop %s metric %u tag %" ROUTE_TAG_PRI, - vrf_id, zebra_route_string(api.type), - api.instance, inet_ntop(AF_INET, &p.prefix, - buf[0], sizeof(buf[0])), - p.prefixlen, inet_ntop(AF_INET, &nexthop, - buf[1], sizeof(buf[1])), - api.metric, api.tag); - } - bgp_redistribute_delete(bgp, (struct prefix *)&p, api.type, - api.instance); - } - - return 0; -} - -/* Zebra route add and delete treatment. */ -static int zebra_read_ipv6(int command, struct zclient *zclient, - zebra_size_t length, vrf_id_t vrf_id) -{ - struct stream *s; - struct zapi_ipv6 api; - struct in6_addr nexthop; - struct prefix_ipv6 p, src_p; - unsigned int ifindex; - int i; - struct bgp *bgp; - - bgp = bgp_lookup_by_vrf_id(vrf_id); - if (!bgp) - return 0; - - s = zclient->ibuf; - memset(&nexthop, 0, sizeof(struct in6_addr)); - - /* Type, flags, message. */ - api.type = stream_getc(s); - api.instance = stream_getw(s); - api.flags = stream_getl(s); - api.message = stream_getc(s); - - /* IPv6 prefix. */ - memset(&p, 0, sizeof(struct prefix_ipv6)); - p.family = AF_INET6; - p.prefixlen = MIN(IPV6_MAX_PREFIXLEN, stream_getc(s)); - stream_get(&p.prefix, s, PSIZE(p.prefixlen)); - - memset(&src_p, 0, sizeof(struct prefix_ipv6)); - src_p.family = AF_INET6; - if (CHECK_FLAG(api.message, ZAPI_MESSAGE_SRCPFX)) { - src_p.prefixlen = stream_getc(s); - stream_get(&src_p.prefix, s, PSIZE(src_p.prefixlen)); - } - - if (src_p.prefixlen) - /* we completely ignore srcdest routes for now. */ - return 0; - - /* Nexthop, ifindex, distance, metric. */ - if (CHECK_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP)) { - api.nexthop_num = stream_getc(s); - stream_get(&nexthop, s, 16); - } - - if (CHECK_FLAG(api.message, ZAPI_MESSAGE_IFINDEX)) { - api.ifindex_num = stream_getc(s); - ifindex = stream_getl(s); /* ifindex, unused */ + bgp_redistribute_add(bgp, &api.prefix, &nexthop, ifindex, + api.metric, api.type, api.instance, + api.tag); } else { - ifindex = 0; + bgp_redistribute_delete(bgp, &api.prefix, api.type, + api.instance); } - if (CHECK_FLAG(api.message, ZAPI_MESSAGE_DISTANCE)) - api.distance = stream_getc(s); - else - api.distance = 0; + if (bgp_debug_zebra(&api.prefix)) { + char buf[2][PREFIX_STRLEN]; - if (CHECK_FLAG(api.message, ZAPI_MESSAGE_METRIC)) - api.metric = stream_getl(s); - else - api.metric = 0; - - if (CHECK_FLAG(api.message, ZAPI_MESSAGE_TAG)) - api.tag = stream_getl(s); - else - api.tag = 0; - - /* Simply ignore link-local address. */ - if (IN6_IS_ADDR_LINKLOCAL(&p.prefix)) - return 0; - - if (command == ZEBRA_REDISTRIBUTE_IPV6_ADD) { - if (bgp_debug_zebra((struct prefix *)&p)) { - char buf[2][INET6_ADDRSTRLEN]; - zlog_debug( - "Rx IPv6 route add VRF %u %s[%d] %s/%d nexthop %s metric %u tag %" ROUTE_TAG_PRI, - vrf_id, zebra_route_string(api.type), - api.instance, inet_ntop(AF_INET6, &p.prefix, - buf[0], sizeof(buf[0])), - p.prefixlen, inet_ntop(AF_INET, &nexthop, - buf[1], sizeof(buf[1])), - api.metric, api.tag); - } - - /* - * The ADD message is actually an UPDATE and there is no - * explicit DEL - * for a prior redistributed route, if any. So, perform an - * implicit - * DEL processing for the same redistributed route from any - * other - * source type. - */ - for (i = 0; i < ZEBRA_ROUTE_MAX; i++) { - if (i != api.type) - bgp_redistribute_delete(bgp, - (struct prefix *)&p, i, - api.instance); - } - - bgp_redistribute_add(bgp, (struct prefix *)&p, NULL, &nexthop, - ifindex, api.metric, api.type, - api.instance, api.tag); - } else if (command == ZEBRA_REDISTRIBUTE_IPV6_DEL) { - if (bgp_debug_zebra((struct prefix *)&p)) { - char buf[2][INET6_ADDRSTRLEN]; - zlog_debug( - "Rx IPv6 route delete VRF %u %s[%d] %s/%d " - "nexthop %s metric %u tag %" ROUTE_TAG_PRI, - vrf_id, zebra_route_string(api.type), - api.instance, inet_ntop(AF_INET6, &p.prefix, - buf[0], sizeof(buf[0])), - p.prefixlen, inet_ntop(AF_INET6, &nexthop, - buf[1], sizeof(buf[1])), - api.metric, api.tag); - } - bgp_redistribute_delete(bgp, (struct prefix *)&p, api.type, - api.instance); + prefix2str(&api.prefix, buf[0], sizeof(buf[0])); + inet_ntop(api.prefix.family, &nexthop, buf[1], sizeof(buf[1])); + zlog_debug( + "Rx route %s VRF %u %s[%d] %s " + "nexthop %s metric %u tag %" ROUTE_TAG_PRI, + (add) ? "add" : "delete", vrf_id, + zebra_route_string(api.type), api.instance, buf[0], + buf[1], api.metric, api.tag); } return 0; @@ -1153,7 +983,11 @@ void bgp_zebra_announce(struct bgp_node *rn, struct prefix *p, struct bgp_info *info, struct bgp *bgp, afi_t afi, safi_t safi) { - u_int32_t flags; + struct zapi_route api; + struct zapi_nexthop *api_nh; + int nh_family; + int valid_nh_count = 0; + int has_valid_label = 0; u_char distance; struct peer *peer; struct bgp_info *mpinfo; @@ -1169,18 +1003,17 @@ void bgp_zebra_announce(struct bgp_node *rn, struct prefix *p, if (!bgp_install_info_to_zebra(bgp)) return; - if ((p->family == AF_INET - && !vrf_bitmap_check(zclient->redist[AFI_IP][ZEBRA_ROUTE_BGP], - bgp->vrf_id)) - || (p->family == AF_INET6 - && !vrf_bitmap_check(zclient->redist[AFI_IP6][ZEBRA_ROUTE_BGP], - bgp->vrf_id))) - return; - if (bgp->main_zebra_update_hold) return; - flags = 0; + /* Make Zebra API structure. */ + memset(&api, 0, sizeof(api)); + api.vrf_id = bgp->vrf_id; + api.type = ZEBRA_ROUTE_BGP; + api.safi = safi; + api.prefix = *p; + SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP); + peer = info->peer; tag = info->attr->tag; @@ -1189,40 +1022,39 @@ void bgp_zebra_announce(struct bgp_node *rn, struct prefix *p, * in * the RIB */ if (info->sub_type == BGP_ROUTE_AGGREGATE) - SET_FLAG(flags, ZEBRA_FLAG_BLACKHOLE); + SET_FLAG(api.flags, ZEBRA_FLAG_BLACKHOLE); if (peer->sort == BGP_PEER_IBGP || peer->sort == BGP_PEER_CONFED || info->sub_type == BGP_ROUTE_AGGREGATE) { - SET_FLAG(flags, ZEBRA_FLAG_IBGP); - SET_FLAG(flags, ZEBRA_FLAG_INTERNAL); + SET_FLAG(api.flags, ZEBRA_FLAG_IBGP); + SET_FLAG(api.flags, ZEBRA_FLAG_INTERNAL); } if ((peer->sort == BGP_PEER_EBGP && peer->ttl != 1) || CHECK_FLAG(peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK) || bgp_flag_check(bgp, BGP_FLAG_DISABLE_NH_CONNECTED_CHK)) - SET_FLAG(flags, ZEBRA_FLAG_INTERNAL); + SET_FLAG(api.flags, ZEBRA_FLAG_INTERNAL); - if (p->family == AF_INET && !BGP_ATTR_NEXTHOP_AFI_IP6(info->attr)) { - struct zapi_ipv4 api; - struct in_addr *nexthop; - char buf[2][INET_ADDRSTRLEN]; - int valid_nh_count = 0; - int has_valid_label = 0; + /* Get nexthop address-family */ + if (p->family == AF_INET && !BGP_ATTR_NEXTHOP_AFI_IP6(info->attr)) + nh_family = AF_INET; + else if (p->family == AF_INET6 + || (p->family == AF_INET + && BGP_ATTR_NEXTHOP_AFI_IP6(info->attr))) + nh_family = AF_INET6; + else + return; - /* resize nexthop buffer size if necessary */ - stream_reset(bgp_nexthop_buf); - nexthop = NULL; + if (bgp->table_map[afi][safi].name) + BGP_INFO_ATTR_BUF_INIT(); - stream_reset(bgp_label_buf); + /* Metric is currently based on the best-path only */ + metric = info->attr->med; + for (mpinfo = info; mpinfo; mpinfo = bgp_info_mpath_next(mpinfo)) { + if (nh_family == AF_INET) { + struct in_addr *nexthop; - if (bgp->table_map[afi][safi].name) - BGP_INFO_ATTR_BUF_INIT(); - - /* Metric is currently based on the best-path only */ - metric = info->attr->med; - for (mpinfo = info; mpinfo; - mpinfo = bgp_info_mpath_next(mpinfo)) { nexthop = NULL; if (bgp->table_map[afi][safi].name) { @@ -1234,8 +1066,6 @@ void bgp_zebra_announce(struct bgp_node *rn, struct prefix *p, bgp->table_map[afi][safi].map, p, info_cp)) { if (mpinfo == info) { - /* Metric is currently based on - * the best-path only */ metric = info_cp->attr->med; tag = info_cp->attr->tag; } @@ -1248,118 +1078,13 @@ void bgp_zebra_announce(struct bgp_node *rn, struct prefix *p, if (nexthop == NULL) continue; - stream_put(bgp_nexthop_buf, &nexthop, - sizeof(struct in_addr *)); - if (mpinfo->extra - && bgp_is_valid_label(&mpinfo->extra->label)) { - has_valid_label = 1; - label = label_pton(&mpinfo->extra->label); - stream_put(bgp_label_buf, &label, - sizeof(mpls_label_t)); - } - valid_nh_count++; - } - - api.vrf_id = bgp->vrf_id; - api.flags = flags; - api.type = ZEBRA_ROUTE_BGP; - api.instance = 0; - api.message = 0; - api.safi = safi; - SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP); - - if (has_valid_label) - SET_FLAG(api.message, ZAPI_MESSAGE_LABEL); - - /* Note that this currently only applies to Null0 routes for - * aggregates. - * ZEBRA_FLAG_BLACKHOLE signals zapi_ipv4_route to encode a - * special - * BLACKHOLE nexthop. We want to set api.nexthop_num to zero - * since we - * do not want to also encode the 0.0.0.0 nexthop for the - * aggregate route. - */ - if (CHECK_FLAG(flags, ZEBRA_FLAG_BLACKHOLE)) - api.nexthop_num = 0; - else - api.nexthop_num = valid_nh_count; - - api.nexthop = (struct in_addr **)STREAM_DATA(bgp_nexthop_buf); - if (has_valid_label) { - api.label_num = valid_nh_count; - api.label = (unsigned int *)STREAM_DATA(bgp_label_buf); + api_nh = &api.nexthops[valid_nh_count]; + api_nh->gate.ipv4 = *nexthop; + api_nh->type = NEXTHOP_TYPE_IPV4; } else { - api.label_num = 0; - api.label = NULL; - } - api.ifindex_num = 0; - SET_FLAG(api.message, ZAPI_MESSAGE_METRIC); - api.metric = metric; - api.tag = 0; + ifindex_t ifindex; + struct in6_addr *nexthop; - if (tag) { - SET_FLAG(api.message, ZAPI_MESSAGE_TAG); - api.tag = tag; - } - - distance = bgp_distance_apply(p, info, afi, safi, bgp); - if (distance) { - SET_FLAG(api.message, ZAPI_MESSAGE_DISTANCE); - api.distance = distance; - } - - if (bgp_debug_zebra(p)) { - int i; - char label_buf[20]; - zlog_debug( - "Tx IPv4 route %s VRF %u %s/%d metric %u tag %" ROUTE_TAG_PRI - " count %d", - (valid_nh_count ? "add" : "delete"), - bgp->vrf_id, inet_ntop(AF_INET, &p->u.prefix4, - buf[0], sizeof(buf[0])), - p->prefixlen, api.metric, api.tag, - api.nexthop_num); - for (i = 0; i < api.nexthop_num; i++) { - label_buf[0] = '\0'; - if (has_valid_label) - sprintf(label_buf, "label %u", - api.label[i]); - zlog_debug(" nhop [%d]: %s %s", i + 1, - inet_ntop(AF_INET, api.nexthop[i], - buf[1], sizeof(buf[1])), - label_buf); - } - } - - zapi_ipv4_route(valid_nh_count ? ZEBRA_IPV4_ROUTE_ADD - : ZEBRA_IPV4_ROUTE_DELETE, - zclient, (struct prefix_ipv4 *)p, &api); - } - - /* We have to think about a IPv6 link-local address curse. */ - if (p->family == AF_INET6 - || (p->family == AF_INET && BGP_ATTR_NEXTHOP_AFI_IP6(info->attr))) { - ifindex_t ifindex; - struct in6_addr *nexthop; - struct zapi_ipv6 api; - int valid_nh_count = 0; - char buf[2][INET6_ADDRSTRLEN]; - int has_valid_label = 0; - - stream_reset(bgp_nexthop_buf); - stream_reset(bgp_ifindices_buf); - stream_reset(bgp_label_buf); - - ifindex = 0; - nexthop = NULL; - - if (bgp->table_map[afi][safi].name) - BGP_INFO_ATTR_BUF_INIT(); - - metric = info->attr->med; - for (mpinfo = info; mpinfo; - mpinfo = bgp_info_mpath_next(mpinfo)) { ifindex = 0; nexthop = NULL; @@ -1407,147 +1132,72 @@ void bgp_zebra_announce(struct bgp_node *rn, struct prefix *p, if (ifindex == 0) continue; - stream_put(bgp_nexthop_buf, &nexthop, - sizeof(struct in6_addr *)); - stream_put(bgp_ifindices_buf, &ifindex, - sizeof(unsigned int)); - - if (mpinfo->extra - && bgp_is_valid_label(&mpinfo->extra->label)) { - has_valid_label = 1; - label = label_pton(&mpinfo->extra->label); - stream_put(bgp_label_buf, &label, - sizeof(mpls_label_t)); - } - valid_nh_count++; + api_nh = &api.nexthops[valid_nh_count]; + api_nh->gate.ipv6 = *nexthop; + api_nh->ifindex = ifindex; + api_nh->type = NEXTHOP_TYPE_IPV6_IFINDEX; } - /* Make Zebra API structure. */ - api.vrf_id = bgp->vrf_id; - api.flags = flags; - api.type = ZEBRA_ROUTE_BGP; - api.instance = 0; - api.message = 0; - api.safi = safi; - SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP); + if (mpinfo->extra + && bgp_is_valid_label(&mpinfo->extra->label)) { + has_valid_label = 1; + label = label_pton(&mpinfo->extra->label); - if (has_valid_label) - SET_FLAG(api.message, ZAPI_MESSAGE_LABEL); - - /* Note that this currently only applies to Null0 routes for - * aggregates. - * ZEBRA_FLAG_BLACKHOLE signals zapi_ipv6_route to encode a - * special - * BLACKHOLE nexthop. We want to set api.nexthop_num to zero - * since we - * do not want to also encode the :: nexthop for the aggregate - * route. - */ - if (CHECK_FLAG(flags, ZEBRA_FLAG_BLACKHOLE)) - api.nexthop_num = 0; - else - api.nexthop_num = valid_nh_count; - - api.nexthop = (struct in6_addr **)STREAM_DATA(bgp_nexthop_buf); - SET_FLAG(api.message, ZAPI_MESSAGE_IFINDEX); - api.ifindex_num = valid_nh_count; - api.ifindex = (ifindex_t *)STREAM_DATA(bgp_ifindices_buf); - if (has_valid_label) { - api.label_num = valid_nh_count; - api.label = (unsigned int *)STREAM_DATA(bgp_label_buf); - } else { - api.label_num = 0; - api.label = NULL; + api_nh->label_num = 1; + api_nh->labels[0] = label; } - SET_FLAG(api.message, ZAPI_MESSAGE_METRIC); - api.metric = metric; - api.tag = 0; + valid_nh_count++; + } - if (tag) { - SET_FLAG(api.message, ZAPI_MESSAGE_TAG); - api.tag = tag; - } + if (has_valid_label) + SET_FLAG(api.message, ZAPI_MESSAGE_LABEL); - distance = bgp_distance_apply(p, info, afi, safi, bgp); - if (distance) { - SET_FLAG(api.message, ZAPI_MESSAGE_DISTANCE); - api.distance = distance; - } + if (!CHECK_FLAG(api.flags, ZEBRA_FLAG_BLACKHOLE)) + api.nexthop_num = valid_nh_count; - if (p->family == AF_INET) { - if (bgp_debug_zebra(p)) { - int i; - char label_buf[20]; - zlog_debug( - "Tx IPv4 route %s VRF %u %s/%d metric %u tag %" ROUTE_TAG_PRI, - valid_nh_count ? "add" : "delete", - bgp->vrf_id, - inet_ntop(AF_INET, &p->u.prefix4, - buf[0], sizeof(buf[0])), - p->prefixlen, api.metric, api.tag); - for (i = 0; i < api.nexthop_num; i++) { - label_buf[0] = '\0'; - if (has_valid_label) - sprintf(label_buf, "label %u", - api.label[i]); - zlog_debug( - " nhop [%d]: %s if %s %s", - i + 1, - inet_ntop(AF_INET6, - api.nexthop[i], - buf[1], - sizeof(buf[1])), - ifindex2ifname(api.ifindex[i], - bgp->vrf_id), - label_buf); - } - } + SET_FLAG(api.message, ZAPI_MESSAGE_METRIC); + api.metric = metric; - if (valid_nh_count) - zapi_ipv4_route_ipv6_nexthop( - ZEBRA_IPV4_ROUTE_IPV6_NEXTHOP_ADD, - zclient, (struct prefix_ipv4 *)p, - (struct zapi_ipv6 *)&api); - else - zapi_ipv4_route(ZEBRA_IPV4_ROUTE_DELETE, - zclient, - (struct prefix_ipv4 *)p, - (struct zapi_ipv4 *)&api); - } else { - if (bgp_debug_zebra(p)) { - int i; - char label_buf[20]; - zlog_debug( - "Tx IPv6 route %s VRF %u %s/%d metric %u tag %" ROUTE_TAG_PRI, - valid_nh_count ? "add" : "delete", - bgp->vrf_id, - inet_ntop(AF_INET6, &p->u.prefix6, - buf[0], sizeof(buf[0])), - p->prefixlen, api.metric, api.tag); - for (i = 0; i < api.nexthop_num; i++) { - label_buf[0] = '\0'; - if (has_valid_label) - sprintf(label_buf, "label %u", - api.label[i]); - zlog_debug( - " nhop [%d]: %s if %s %s", - i + 1, - inet_ntop(AF_INET6, - api.nexthop[i], - buf[1], - sizeof(buf[1])), - ifindex2ifname(api.ifindex[i], - bgp->vrf_id), - label_buf); - } - } + if (tag) { + SET_FLAG(api.message, ZAPI_MESSAGE_TAG); + api.tag = tag; + } - zapi_ipv6_route( - valid_nh_count ? ZEBRA_IPV6_ROUTE_ADD - : ZEBRA_IPV6_ROUTE_DELETE, - zclient, (struct prefix_ipv6 *)p, NULL, &api); + distance = bgp_distance_apply(p, info, afi, safi, bgp); + if (distance) { + SET_FLAG(api.message, ZAPI_MESSAGE_DISTANCE); + api.distance = distance; + } + + if (bgp_debug_zebra(p)) { + char prefix_buf[PREFIX_STRLEN]; + char nh_buf[INET6_ADDRSTRLEN]; + char label_buf[20]; + int i; + + prefix2str(&api.prefix, prefix_buf, sizeof(prefix_buf)); + zlog_debug("Tx route %s VRF %u %s metric %u tag %" ROUTE_TAG_PRI + " count %d", + valid_nh_count ? "add" : "delete", bgp->vrf_id, + prefix_buf, api.metric, api.tag, api.nexthop_num); + for (i = 0; i < api.nexthop_num; i++) { + api_nh = &api.nexthops[i]; + + inet_ntop(nh_family, &api_nh->gate, nh_buf, + sizeof(nh_buf)); + + label_buf[0] = '\0'; + if (has_valid_label) + sprintf(label_buf, "label %u", + api_nh->labels[0]); + zlog_debug(" nhop [%d]: %s %s", i + 1, nh_buf, + label_buf); } } + + zclient_route_send(valid_nh_count ? ZEBRA_ROUTE_ADD + : ZEBRA_ROUTE_DELETE, + zclient, &api); } /* Announce all routes of a table to zebra */ @@ -1578,7 +1228,7 @@ void bgp_zebra_announce_table(struct bgp *bgp, afi_t afi, safi_t safi) void bgp_zebra_withdraw(struct prefix *p, struct bgp_info *info, safi_t safi) { - u_int32_t flags; + struct zapi_route api; struct peer *peer; peer = info->peer; @@ -1590,101 +1240,30 @@ void bgp_zebra_withdraw(struct prefix *p, struct bgp_info *info, safi_t safi) if (!bgp_install_info_to_zebra(peer->bgp)) return; - if ((p->family == AF_INET - && !vrf_bitmap_check(zclient->redist[AFI_IP][ZEBRA_ROUTE_BGP], - peer->bgp->vrf_id)) - || (p->family == AF_INET6 - && !vrf_bitmap_check(zclient->redist[AFI_IP6][ZEBRA_ROUTE_BGP], - peer->bgp->vrf_id))) - return; - - flags = 0; + memset(&api, 0, sizeof(api)); + api.vrf_id = peer->bgp->vrf_id; + api.type = ZEBRA_ROUTE_BGP; + api.safi = safi; + api.prefix = *p; if (peer->sort == BGP_PEER_IBGP) { - SET_FLAG(flags, ZEBRA_FLAG_INTERNAL); - SET_FLAG(flags, ZEBRA_FLAG_IBGP); + SET_FLAG(api.flags, ZEBRA_FLAG_INTERNAL); + SET_FLAG(api.flags, ZEBRA_FLAG_IBGP); } if ((peer->sort == BGP_PEER_EBGP && peer->ttl != 1) || CHECK_FLAG(peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK) || bgp_flag_check(peer->bgp, BGP_FLAG_DISABLE_NH_CONNECTED_CHK)) - SET_FLAG(flags, ZEBRA_FLAG_INTERNAL); + SET_FLAG(api.flags, ZEBRA_FLAG_INTERNAL); - if (p->family == AF_INET) { - struct zapi_ipv4 api; + if (bgp_debug_zebra(p)) { + char buf[PREFIX_STRLEN]; - api.vrf_id = peer->bgp->vrf_id; - api.flags = flags; - - api.type = ZEBRA_ROUTE_BGP; - api.instance = 0; - api.message = 0; - api.safi = safi; - SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP); - api.nexthop_num = 0; - api.nexthop = NULL; - api.label_num = 0; - api.label = NULL; - api.ifindex_num = 0; - SET_FLAG(api.message, ZAPI_MESSAGE_METRIC); - api.metric = info->attr->med; - api.tag = 0; - - if (info->attr->tag != 0) { - SET_FLAG(api.message, ZAPI_MESSAGE_TAG); - api.tag = info->attr->tag; - } - - if (bgp_debug_zebra(p)) { - char buf[2][INET_ADDRSTRLEN]; - zlog_debug( - "Tx IPv4 route delete VRF %u %s/%d metric %u tag %" ROUTE_TAG_PRI, - peer->bgp->vrf_id, - inet_ntop(AF_INET, &p->u.prefix4, buf[0], - sizeof(buf[0])), - p->prefixlen, api.metric, api.tag); - } - - zapi_ipv4_route(ZEBRA_IPV4_ROUTE_DELETE, zclient, - (struct prefix_ipv4 *)p, &api); + prefix2str(&api.prefix, buf, sizeof(buf)); + zlog_debug("Tx route delete VRF %u %s", peer->bgp->vrf_id, buf); } - /* We have to think about a IPv6 link-local address curse. */ - if (p->family == AF_INET6) { - struct zapi_ipv6 api; - api.vrf_id = peer->bgp->vrf_id; - api.flags = flags; - api.type = ZEBRA_ROUTE_BGP; - api.instance = 0; - api.message = 0; - api.safi = safi; - SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP); - api.nexthop_num = 0; - api.nexthop = NULL; - api.ifindex_num = 0; - api.label_num = 0; - SET_FLAG(api.message, ZAPI_MESSAGE_METRIC); - api.metric = info->attr->med; - api.tag = 0; - - if (info->attr->tag != 0) { - SET_FLAG(api.message, ZAPI_MESSAGE_TAG); - api.tag = info->attr->tag; - } - - if (bgp_debug_zebra(p)) { - char buf[2][INET6_ADDRSTRLEN]; - zlog_debug( - "Tx IPv6 route delete VRF %u %s/%d metric %u tag %" ROUTE_TAG_PRI, - peer->bgp->vrf_id, - inet_ntop(AF_INET6, &p->u.prefix6, buf[0], - sizeof(buf[0])), - p->prefixlen, api.metric, api.tag); - } - - zapi_ipv6_route(ZEBRA_IPV6_ROUTE_DELETE, zclient, - (struct prefix_ipv6 *)p, NULL, &api); - } + zclient_route_send(ZEBRA_ROUTE_DELETE, zclient, &api); } struct bgp_redist *bgp_redist_lookup(struct bgp *bgp, afi_t afi, u_char type, @@ -2198,12 +1777,10 @@ void bgp_zebra_init(struct thread_master *master) zclient->interface_nbr_address_delete = bgp_interface_nbr_address_delete; zclient->interface_vrf_update = bgp_interface_vrf_update; - zclient->redistribute_route_ipv4_add = zebra_read_ipv4; - zclient->redistribute_route_ipv4_del = zebra_read_ipv4; + zclient->redistribute_route_add = zebra_read_route; + zclient->redistribute_route_del = zebra_read_route; zclient->interface_up = bgp_interface_up; zclient->interface_down = bgp_interface_down; - zclient->redistribute_route_ipv6_add = zebra_read_ipv6; - zclient->redistribute_route_ipv6_del = zebra_read_ipv6; zclient->nexthop_update = bgp_read_nexthop_update; zclient->import_check_update = bgp_read_import_check_update; zclient->fec_update = bgp_read_fec_update; @@ -2211,22 +1788,10 @@ void bgp_zebra_init(struct thread_master *master) zclient->local_vni_del = bgp_zebra_process_local_vni; zclient->local_macip_add = bgp_zebra_process_local_macip; zclient->local_macip_del = bgp_zebra_process_local_macip; - - bgp_nexthop_buf = stream_new(multipath_num * sizeof(struct in6_addr)); - bgp_ifindices_buf = stream_new(multipath_num * sizeof(unsigned int)); - bgp_label_buf = stream_new(multipath_num * sizeof(unsigned int)); } void bgp_zebra_destroy(void) { - - if (bgp_nexthop_buf) - stream_free(bgp_nexthop_buf); - if (bgp_ifindices_buf) - stream_free(bgp_ifindices_buf); - if (bgp_label_buf) - stream_free(bgp_label_buf); - if (zclient == NULL) return; zclient_stop(zclient); diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c index 258d650d20..7edd4fe754 100644 --- a/bgpd/bgpd.c +++ b/bgpd/bgpd.c @@ -1391,6 +1391,32 @@ void bgp_peer_conf_if_to_su_update(struct peer *peer) hash_get(peer->bgp->peerhash, peer, hash_alloc_intern); } +static void bgp_recalculate_afi_safi_bestpaths(struct bgp *bgp, afi_t afi, + safi_t safi) +{ + struct bgp_node *rn, *nrn; + + for (rn = bgp_table_top(bgp->rib[afi][safi]); rn; + rn = bgp_route_next(rn)) { + if (rn->info != NULL) { + /* Special handling for 2-level routing + * tables. */ + if (safi == SAFI_MPLS_VPN + || safi == SAFI_ENCAP + || safi == SAFI_EVPN) { + for (nrn = bgp_table_top(( + struct bgp_table + *)(rn->info)); + nrn; + nrn = bgp_route_next(nrn)) + bgp_process(bgp, nrn, + afi, safi); + } else + bgp_process(bgp, rn, afi, safi); + } + } +} + /* Force a bestpath recalculation for all prefixes. This is used * when 'bgp bestpath' commands are entered. */ @@ -1398,29 +1424,10 @@ void bgp_recalculate_all_bestpaths(struct bgp *bgp) { afi_t afi; safi_t safi; - struct bgp_node *rn, *nrn; for (afi = AFI_IP; afi < AFI_MAX; afi++) { for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) { - for (rn = bgp_table_top(bgp->rib[afi][safi]); rn; - rn = bgp_route_next(rn)) { - if (rn->info != NULL) { - /* Special handling for 2-level routing - * tables. */ - if (safi == SAFI_MPLS_VPN - || safi == SAFI_ENCAP - || safi == SAFI_EVPN) { - for (nrn = bgp_table_top(( - struct bgp_table - *)(rn->info)); - nrn; - nrn = bgp_route_next(nrn)) - bgp_process(bgp, nrn, - afi, safi); - } else - bgp_process(bgp, rn, afi, safi); - } - } + bgp_recalculate_afi_safi_bestpaths(bgp, afi, safi); } } } @@ -1500,6 +1507,25 @@ struct peer *peer_create_accept(struct bgp *bgp) return peer; } +/* + * Return true if we have a peer configured to use this afi/safi + */ +int bgp_afi_safi_peer_exists(struct bgp *bgp, afi_t afi, safi_t safi) +{ + struct listnode *node; + struct peer *peer; + + for (ALL_LIST_ELEMENTS_RO(bgp->peer, node, peer)) { + if (!CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE)) + continue; + + if (peer->afc[afi][safi]) + return 1; + } + + return 0; +} + /* Change peer's AS number. */ void peer_as_change(struct peer *peer, as_t as, int as_specified) { @@ -1714,11 +1740,14 @@ int peer_activate(struct peer *peer, afi_t afi, safi_t safi) struct peer_group *group; struct listnode *node, *nnode; struct peer *tmp_peer; + struct bgp *bgp; /* Nothing to do if we've already activated this peer */ if (peer->afc[afi][safi]) return ret; + bgp = peer->bgp; + /* This is a peer-group so activate all of the members of the * peer-group as well */ if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) { @@ -1741,6 +1770,17 @@ int peer_activate(struct peer *peer, afi_t afi, safi_t safi) ret |= non_peergroup_activate_af(peer, afi, safi); } + /* If this is the first peer to be activated for this afi/labeled-unicast + * recalc bestpaths to trigger label allocation */ + if (safi == SAFI_LABELED_UNICAST && !bgp->allocate_mpls_labels[afi][SAFI_UNICAST]) { + + if (BGP_DEBUG(zebra, ZEBRA)) + zlog_info("peer(s) are now active for labeled-unicast, allocate MPLS labels"); + + bgp->allocate_mpls_labels[afi][SAFI_UNICAST] = 1; + bgp_recalculate_afi_safi_bestpaths(bgp, afi, SAFI_UNICAST); + } + return ret; } @@ -1798,6 +1838,7 @@ int peer_deactivate(struct peer *peer, afi_t afi, safi_t safi) struct peer_group *group; struct peer *tmp_peer; struct listnode *node, *nnode; + struct bgp *bgp; /* Nothing to do if we've already de-activated this peer */ if (!peer->afc[afi][safi]) @@ -1821,6 +1862,20 @@ int peer_deactivate(struct peer *peer, afi_t afi, safi_t safi) ret |= non_peergroup_deactivate_af(peer, afi, safi); } + bgp = peer->bgp; + + /* If this is the last peer to be deactivated for this afi/labeled-unicast + * recalc bestpaths to trigger label deallocation */ + if (safi == SAFI_LABELED_UNICAST && + bgp->allocate_mpls_labels[afi][SAFI_UNICAST] && + !bgp_afi_safi_peer_exists(bgp, afi, safi)) { + + if (BGP_DEBUG(zebra, ZEBRA)) + zlog_info("peer(s) are no longer active for labeled-unicast, deallocate MPLS labels"); + + bgp->allocate_mpls_labels[afi][SAFI_UNICAST] = 0; + bgp_recalculate_afi_safi_bestpaths(bgp, afi, SAFI_UNICAST); + } return ret; } @@ -3087,6 +3142,8 @@ int bgp_delete(struct bgp *bgp) * routes to be processed still referencing the struct bgp. */ listnode_delete(bm->bgp, bgp); + if (list_isempty(bm->bgp)) + bgp_close(); /* Deregister from Zebra, if needed */ if (IS_BGP_INST_KNOWN_TO_ZEBRA(bgp)) diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h index da30ecd963..80b5746f11 100644 --- a/bgpd/bgpd.h +++ b/bgpd/bgpd.h @@ -334,6 +334,9 @@ struct bgp { /* BGP redistribute configuration. */ struct list *redist[AFI_MAX][ZEBRA_ROUTE_MAX]; + /* Allocate MPLS labels */ + u_char allocate_mpls_labels[AFI_MAX][SAFI_MAX]; + /* timer to re-evaluate neighbor default-originate route-maps */ struct thread *t_rmap_def_originate_eval; #define RMAP_DEFAULT_ORIGINATE_EVAL_TIMER 5 @@ -1285,6 +1288,7 @@ extern int bgp_listen_limit_unset(struct bgp *); extern int bgp_update_delay_active(struct bgp *); extern int bgp_update_delay_configured(struct bgp *); +extern int bgp_afi_safi_peer_exists(struct bgp *bgp, afi_t afi, safi_t safi); extern void peer_as_change(struct peer *, as_t, int); extern int peer_remote_as(struct bgp *, union sockunion *, const char *, as_t *, int, afi_t, safi_t); diff --git a/bgpd/rfapi/vnc_zebra.c b/bgpd/rfapi/vnc_zebra.c index 3075d4109f..d472e06fa5 100644 --- a/bgpd/rfapi/vnc_zebra.c +++ b/bgpd/rfapi/vnc_zebra.c @@ -57,8 +57,8 @@ static struct zclient *zclient_vnc = NULL; /* * Routes coming from zebra get added to VNC here */ -static void vnc_redistribute_add(struct prefix *p, struct in_addr *nexthop, - u_int32_t metric, uint8_t type) +static void vnc_redistribute_add(struct prefix *p, u_int32_t metric, + uint8_t type) { struct bgp *bgp = bgp_get_default(); struct prefix_rd prd; @@ -329,156 +329,33 @@ static void vnc_redistribute_withdraw(struct bgp *bgp, afi_t afi, uint8_t type) * * Assumes 1 nexthop */ -static int vnc_zebra_read_ipv4(int command, struct zclient *zclient, - zebra_size_t length, vrf_id_t vrf_id) +static int vnc_zebra_read_route(int command, struct zclient *zclient, + zebra_size_t length, vrf_id_t vrf_id) { - struct stream *s; - struct zapi_ipv4 api; - struct in_addr nexthop; - struct prefix_ipv4 p; + struct zapi_route api; + int add; - s = zclient->ibuf; - nexthop.s_addr = 0; + if (zapi_route_decode(zclient->ibuf, &api) < 0) + return -1; - /* Type, flags, message. */ - api.type = stream_getc(s); - api.flags = stream_getc(s); - api.message = stream_getc(s); - - /* IPv4 prefix. */ - memset(&p, 0, sizeof(struct prefix_ipv4)); - p.family = AF_INET; - p.prefixlen = stream_getc(s); - stream_get(&p.prefix, s, PSIZE(p.prefixlen)); - - /* Nexthop, ifindex, distance, metric. */ - if (CHECK_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP)) { - api.nexthop_num = stream_getc(s); - nexthop.s_addr = stream_get_ipv4(s); - } - if (CHECK_FLAG(api.message, ZAPI_MESSAGE_IFINDEX)) { - api.ifindex_num = stream_getc(s); - stream_getl(s); - } - if (CHECK_FLAG(api.message, ZAPI_MESSAGE_DISTANCE)) - api.distance = stream_getc(s); - if (CHECK_FLAG(api.message, ZAPI_MESSAGE_METRIC)) - api.metric = stream_getl(s); - else - api.metric = 0; - - if (command == ZEBRA_IPV4_ROUTE_ADD) { - if (BGP_DEBUG(zebra, ZEBRA)) { - char buf[2][INET_ADDRSTRLEN]; - vnc_zlog_debug_verbose( - "%s: Zebra rcvd: IPv4 route add %s %s/%d nexthop %s metric %u", - __func__, zebra_route_string(api.type), - inet_ntop(AF_INET, &p.prefix, buf[0], - sizeof(buf[0])), - p.prefixlen, inet_ntop(AF_INET, &nexthop, - buf[1], sizeof(buf[1])), - api.metric); - } - vnc_redistribute_add((struct prefix *)&p, &nexthop, api.metric, - api.type); - } else { - if (BGP_DEBUG(zebra, ZEBRA)) { - char buf[2][INET_ADDRSTRLEN]; - vnc_zlog_debug_verbose( - "%s: Zebra rcvd: IPv4 route delete %s %s/%d " - "nexthop %s metric %u", - __func__, zebra_route_string(api.type), - inet_ntop(AF_INET, &p.prefix, buf[0], - sizeof(buf[0])), - p.prefixlen, inet_ntop(AF_INET, &nexthop, - buf[1], sizeof(buf[1])), - api.metric); - } - vnc_redistribute_delete((struct prefix *)&p, api.type); - } - - return 0; -} - -/* Zebra route add and delete treatment. */ -static int vnc_zebra_read_ipv6(int command, struct zclient *zclient, - zebra_size_t length, vrf_id_t vrf_id) -{ - struct stream *s; - struct zapi_ipv6 api; - struct in6_addr nexthop; - struct prefix_ipv6 p, src_p; - - s = zclient->ibuf; - memset(&nexthop, 0, sizeof(struct in6_addr)); - - /* Type, flags, message. */ - api.type = stream_getc(s); - api.flags = stream_getc(s); - api.message = stream_getc(s); - - /* IPv6 prefix. */ - memset(&p, 0, sizeof(struct prefix_ipv6)); - p.family = AF_INET6; - p.prefixlen = stream_getc(s); - stream_get(&p.prefix, s, PSIZE(p.prefixlen)); - - memset(&src_p, 0, sizeof(struct prefix_ipv6)); - src_p.family = AF_INET6; - if (CHECK_FLAG(api.message, ZAPI_MESSAGE_SRCPFX)) { - src_p.prefixlen = stream_getc(s); - stream_get(&src_p.prefix, s, PSIZE(src_p.prefixlen)); - } - - if (src_p.prefixlen) - /* we completely ignore srcdest routes for now. */ + /* we completely ignore srcdest routes for now. */ + if (CHECK_FLAG(api.message, ZAPI_MESSAGE_SRCPFX)) return 0; - /* Nexthop, ifindex, distance, metric. */ - if (CHECK_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP)) { - api.nexthop_num = stream_getc(s); - stream_get(&nexthop, s, 16); - } - if (CHECK_FLAG(api.message, ZAPI_MESSAGE_IFINDEX)) { - api.ifindex_num = stream_getc(s); - stream_getl(s); - } - if (CHECK_FLAG(api.message, ZAPI_MESSAGE_DISTANCE)) - api.distance = stream_getc(s); + add = (command == ZEBRA_REDISTRIBUTE_ROUTE_ADD); + if (add) + vnc_redistribute_add(&api.prefix, api.metric, api.type); else - api.distance = 0; - if (CHECK_FLAG(api.message, ZAPI_MESSAGE_METRIC)) - api.metric = stream_getl(s); - else - api.metric = 0; + vnc_redistribute_delete(&api.prefix, api.type); - /* Simply ignore link-local address. */ - if (IN6_IS_ADDR_LINKLOCAL(&p.prefix)) - return 0; + if (BGP_DEBUG(zebra, ZEBRA)) { + char buf[PREFIX_STRLEN]; - if (command == ZEBRA_IPV6_ROUTE_ADD) { - if (BGP_DEBUG(zebra, ZEBRA)) { - char buf[INET6_ADDRSTRLEN]; - vnc_zlog_debug_verbose( - "Zebra rcvd: IPv6 route add %s %s/%d metric %u", - zebra_route_string(api.type), - inet_ntop(AF_INET6, &p.prefix, buf, - sizeof(buf)), - p.prefixlen, api.metric); - } - vnc_redistribute_add((struct prefix *)&p, NULL, api.metric, - api.type); - } else { - if (BGP_DEBUG(zebra, ZEBRA)) { - char buf[INET6_ADDRSTRLEN]; - vnc_zlog_debug_verbose( - "Zebra rcvd: IPv6 route delete %s %s/%d metric %u", - zebra_route_string(api.type), - inet_ntop(AF_INET6, &p.prefix, buf, - sizeof(buf)), - p.prefixlen, api.metric); - } - vnc_redistribute_delete((struct prefix *)&p, api.type); + prefix2str(&api.prefix, buf, sizeof(buf)); + vnc_zlog_debug_verbose( + "%s: Zebra rcvd: route delete %s %s metric %u", + __func__, zebra_route_string(api.type), buf, + api.metric); } return 0; @@ -494,83 +371,57 @@ static int vnc_zebra_read_ipv6(int command, struct zclient *zclient, static void vnc_zebra_route_msg(struct prefix *p, int nhp_count, void *nhp_ary, int add) /* 1 = add, 0 = del */ { + struct zapi_route api; + struct zapi_nexthop *api_nh; + int i; + if (!nhp_count) { vnc_zlog_debug_verbose("%s: empty nexthop list, skipping", __func__); return; } - if (p->family == AF_INET) { + memset(&api, 0, sizeof(api)); + api.vrf_id = VRF_DEFAULT; + api.type = ZEBRA_ROUTE_VNC; + api.safi = SAFI_UNICAST; + api.prefix = *p; - struct zapi_ipv4 api; + /* Nexthops */ + SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP); + api.nexthop_num = nhp_count; + for (i = 0; i < nhp_count; i++) { + struct in_addr *nhp_ary4; + struct in6_addr *nhp_ary6; - api.flags = 0; - api.vrf_id = VRF_DEFAULT; - api.type = ZEBRA_ROUTE_VNC; - api.message = 0; - SET_FLAG(api.message, - ZAPI_MESSAGE_NEXTHOP); /* TBD what's it mean? */ - api.nexthop_num = nhp_count; - api.nexthop = nhp_ary; - api.ifindex_num = 0; - api.instance = 0; - api.safi = SAFI_UNICAST; - - if (BGP_DEBUG(zebra, ZEBRA)) { - - char buf[INET_ADDRSTRLEN]; - vnc_zlog_debug_verbose( - "%s: Zebra send: IPv4 route %s %s/%d, nhp_count=%d", - __func__, (add ? "add" : "del"), - inet_ntop(AF_INET, &p->u.prefix4, buf, - sizeof(buf)), - p->prefixlen, nhp_count); + api_nh = &api.nexthops[i]; + switch (p->family) { + case AF_INET: + nhp_ary4 = nhp_ary; + memcpy(&api_nh->gate.ipv4, &nhp_ary4[i], + sizeof(api_nh->gate.ipv4)); + api_nh->type = NEXTHOP_TYPE_IPV4; + break; + case AF_INET6: + nhp_ary6 = nhp_ary; + memcpy(&api_nh->gate.ipv6, &nhp_ary6[i], + sizeof(api_nh->gate.ipv6)); + api_nh->type = NEXTHOP_TYPE_IPV6; + break; } - - zapi_ipv4_route((add ? ZEBRA_IPV4_NEXTHOP_ADD - : ZEBRA_IPV4_NEXTHOP_DELETE), - zclient_vnc, (struct prefix_ipv4 *)p, &api); - - } else if (p->family == AF_INET6) { - - struct zapi_ipv6 api; - ifindex_t ifindex = 0; - - /* Make Zebra API structure. */ - api.flags = 0; - api.vrf_id = VRF_DEFAULT; - api.type = ZEBRA_ROUTE_VNC; - api.message = 0; - SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP); /* TBD means? */ - api.nexthop_num = nhp_count; - api.nexthop = nhp_ary; - SET_FLAG(api.message, ZAPI_MESSAGE_IFINDEX); - api.ifindex_num = 1; - api.ifindex = &ifindex; - api.instance = 0; - api.safi = SAFI_UNICAST; - - if (BGP_DEBUG(zebra, ZEBRA)) { - - char buf[INET6_ADDRSTRLEN]; - vnc_zlog_debug_verbose( - "%s: Zebra send: IPv6 route %s %s/%d nhp_count=%d", - __func__, (add ? "add" : "del"), - inet_ntop(AF_INET6, &p->u.prefix6, buf, - sizeof(buf)), - p->prefixlen, nhp_count); - } - - zapi_ipv6_route((add ? ZEBRA_IPV6_NEXTHOP_ADD - : ZEBRA_IPV6_NEXTHOP_DELETE), - zclient_vnc, (struct prefix_ipv6 *)p, NULL, - &api); - } else { - vnc_zlog_debug_verbose( - "%s: unknown prefix address family, skipping", - __func__); - return; } + + if (BGP_DEBUG(zebra, ZEBRA)) { + char buf[PREFIX_STRLEN]; + + prefix2str(&api.prefix, buf, sizeof(buf)); + vnc_zlog_debug_verbose( + "%s: Zebra send: route %s %s, nhp_count=%d", __func__, + (add ? "add" : "del"), buf, nhp_count); + } + + zclient_route_send((add ? ZEBRA_ROUTE_ADD : ZEBRA_ROUTE_DELETE), + zclient_vnc, &api); } @@ -1042,10 +893,8 @@ void vnc_zebra_init(struct thread_master *master) zclient_vnc = zclient_new(master); zclient_init(zclient_vnc, ZEBRA_ROUTE_VNC, 0); - zclient_vnc->redistribute_route_ipv4_add = vnc_zebra_read_ipv4; - zclient_vnc->redistribute_route_ipv4_del = vnc_zebra_read_ipv4; - zclient_vnc->redistribute_route_ipv6_add = vnc_zebra_read_ipv6; - zclient_vnc->redistribute_route_ipv6_del = vnc_zebra_read_ipv6; + zclient_vnc->redistribute_route_add = vnc_zebra_read_route; + zclient_vnc->redistribute_route_del = vnc_zebra_read_route; } void vnc_zebra_destroy(void) diff --git a/common.am b/common.am index b115a871b9..c0094b1b88 100644 --- a/common.am +++ b/common.am @@ -13,8 +13,7 @@ CLIPPY_DEPS = $(HOSTTOOLS)lib/clippy $(top_srcdir)/python/clidef.py SUFFIXES = _clippy.c .proto .pb-c.c .pb-c.h .pb.h .c_clippy.c: @{ test -x $(top_builddir)/$(HOSTTOOLS)lib/clippy || $(MAKE) -C $(top_builddir)/$(HOSTTOOLS) lib/clippy; } - $(AM_V_CLIPPY)$(top_builddir)/$(HOSTTOOLS)lib/clippy $(top_srcdir)/python/clidef.py $< > $@.tmp - @{ test -f $@ && diff $@.tmp $@ >/dev/null 2>/dev/null; } && rm $@.tmp || mv $@.tmp $@ + $(AM_V_CLIPPY)$(top_builddir)/$(HOSTTOOLS)lib/clippy $(top_srcdir)/python/clidef.py -o $@ $< ## automake's "ylwrap" is a great piece of GNU software... not. .l.c: diff --git a/eigrpd/eigrp_dump.c b/eigrpd/eigrp_dump.c index 0cb1ee5876..74515c98cb 100644 --- a/eigrpd/eigrp_dump.c +++ b/eigrpd/eigrp_dump.c @@ -158,7 +158,7 @@ const char *eigrp_topology_ip_string(struct eigrp_prefix_entry *tn) static char buf[EIGRP_IF_STRING_MAXLEN] = ""; u_int32_t ifaddr; - ifaddr = ntohl(tn->destination_ipv4->prefix.s_addr); + ifaddr = ntohl(tn->destination->u.prefix4.s_addr); snprintf(buf, EIGRP_IF_STRING_MAXLEN, "%u.%u.%u.%u", (ifaddr >> 24) & 0xff, (ifaddr >> 16) & 0xff, (ifaddr >> 8) & 0xff, ifaddr & 0xff); @@ -289,11 +289,12 @@ void show_ip_eigrp_topology_header(struct vty *vty, struct eigrp *eigrp) void show_ip_eigrp_prefix_entry(struct vty *vty, struct eigrp_prefix_entry *tn) { struct list *successors = eigrp_topology_get_successor(tn); + char buffer[PREFIX_STRLEN]; vty_out(vty, "%-3c", (tn->state > 0) ? 'A' : 'P'); - vty_out(vty, "%s/%u, ", inet_ntoa(tn->destination_ipv4->prefix), - tn->destination_ipv4->prefixlen); + vty_out(vty, "%s, ", + prefix2str(tn->destination, buffer, PREFIX_STRLEN)); vty_out(vty, "%u successors, ", successors->count); vty_out(vty, "FD is %u, serno: %" PRIu64 " \n", tn->fdistance, tn->serno); diff --git a/eigrpd/eigrp_fsm.c b/eigrpd/eigrp_fsm.c index ba2d1f7e8d..47cd112cf5 100644 --- a/eigrpd/eigrp_fsm.c +++ b/eigrpd/eigrp_fsm.c @@ -178,7 +178,7 @@ struct { * Return number of occurred event (arrow in diagram). * */ -int eigrp_get_fsm_event(struct eigrp_fsm_action_message *msg) +static int eigrp_get_fsm_event(struct eigrp_fsm_action_message *msg) { // Loading base information from message // struct eigrp *eigrp = msg->eigrp; @@ -204,8 +204,7 @@ int eigrp_get_fsm_event(struct eigrp_fsm_action_message *msg) switch (actual_state) { case EIGRP_FSM_STATE_PASSIVE: { struct eigrp_neighbor_entry *head = - (struct eigrp_neighbor_entry *) - entry->prefix->entries->head->data; + listnode_head(prefix->entries); if (head->reported_distance < prefix->fdistance) { return EIGRP_FSM_KEEP_STATE; @@ -226,8 +225,7 @@ int eigrp_get_fsm_event(struct eigrp_fsm_action_message *msg) case EIGRP_FSM_STATE_ACTIVE_0: { if (msg->packet_type == EIGRP_OPC_REPLY) { struct eigrp_neighbor_entry *head = - (struct eigrp_neighbor_entry *) - entry->prefix->entries->head->data; + listnode_head(prefix->entries); listnode_delete(prefix->rij, entry->adv_router); if (prefix->rij->count) @@ -279,8 +277,7 @@ int eigrp_get_fsm_event(struct eigrp_fsm_action_message *msg) case EIGRP_FSM_STATE_ACTIVE_2: { if (msg->packet_type == EIGRP_OPC_REPLY) { struct eigrp_neighbor_entry *head = - (struct eigrp_neighbor_entry *) - prefix->entries->head->data; + listnode_head(prefix->entries); listnode_delete(prefix->rij, entry->adv_router); if (prefix->rij->count) { @@ -331,8 +328,9 @@ int eigrp_get_fsm_event(struct eigrp_fsm_action_message *msg) * Function made to execute in separate thread. * Load argument from thread and execute proper NSM function */ -int eigrp_fsm_event(struct eigrp_fsm_action_message *msg, int event) +int eigrp_fsm_event(struct eigrp_fsm_action_message *msg) { + int event = eigrp_get_fsm_event(msg); zlog_info("EIGRP AS: %d State: %d Event: %d Network: %s", msg->eigrp->AS, msg->prefix->state, event, eigrp_topology_ip_string(msg->prefix)); @@ -350,16 +348,15 @@ int eigrp_fsm_event_nq_fcn(struct eigrp_fsm_action_message *msg) struct eigrp *eigrp = msg->eigrp; struct eigrp_prefix_entry *prefix = msg->prefix; struct list *successors = eigrp_topology_get_successor(prefix); + struct eigrp_neighbor_entry *ne; assert(successors); // If this is NULL we have shit the bed, fun huh? + ne = listnode_head(successors); prefix->state = EIGRP_FSM_STATE_ACTIVE_1; prefix->rdistance = prefix->distance = prefix->fdistance = - ((struct eigrp_neighbor_entry *)successors->head->data) - ->distance; - prefix->reported_metric = - ((struct eigrp_neighbor_entry *)successors->head->data) - ->total_metric; + ne->distance; + prefix->reported_metric = ne->total_metric; if (eigrp_nbr_count_get()) { prefix->req_action |= EIGRP_FSM_NEED_QUERY; @@ -379,16 +376,15 @@ int eigrp_fsm_event_q_fcn(struct eigrp_fsm_action_message *msg) struct eigrp *eigrp = msg->eigrp; struct eigrp_prefix_entry *prefix = msg->prefix; struct list *successors = eigrp_topology_get_successor(prefix); + struct eigrp_neighbor_entry *ne; assert(successors); // If this is NULL somebody poked us in the eye. + ne = listnode_head(successors); prefix->state = EIGRP_FSM_STATE_ACTIVE_3; prefix->rdistance = prefix->distance = prefix->fdistance = - ((struct eigrp_neighbor_entry *)successors->head->data) - ->distance; - prefix->reported_metric = - ((struct eigrp_neighbor_entry *)successors->head->data) - ->total_metric; + ne->distance; + prefix->reported_metric = ne->total_metric; if (eigrp_nbr_count_get()) { prefix->req_action |= EIGRP_FSM_NEED_QUERY; listnode_add(eigrp->topology_changes_internalIPV4, prefix); @@ -405,21 +401,15 @@ int eigrp_fsm_event_q_fcn(struct eigrp_fsm_action_message *msg) int eigrp_fsm_event_keep_state(struct eigrp_fsm_action_message *msg) { struct eigrp_prefix_entry *prefix = msg->prefix; + struct eigrp_neighbor_entry *ne = listnode_head(prefix->entries); if (prefix->state == EIGRP_FSM_STATE_PASSIVE) { if (!eigrp_metrics_is_same(prefix->reported_metric, - ((struct eigrp_neighbor_entry *) - prefix->entries->head->data) - ->total_metric)) { + ne->total_metric)) { prefix->rdistance = prefix->fdistance = - prefix->distance = - ((struct eigrp_neighbor_entry *) - prefix->entries->head->data) - ->distance; + prefix->distance = ne->distance; prefix->reported_metric = - ((struct eigrp_neighbor_entry *) - prefix->entries->head->data) - ->total_metric; + ne->total_metric; if (msg->packet_type == EIGRP_OPC_QUERY) eigrp_send_reply(msg->adv_router, prefix); prefix->req_action |= EIGRP_FSM_NEED_UPDATE; @@ -441,22 +431,20 @@ int eigrp_fsm_event_lr(struct eigrp_fsm_action_message *msg) { struct eigrp *eigrp = msg->eigrp; struct eigrp_prefix_entry *prefix = msg->prefix; + struct eigrp_neighbor_entry *ne = listnode_head(prefix->entries); + prefix->fdistance = prefix->distance = prefix->rdistance = - ((struct eigrp_neighbor_entry *)(prefix->entries->head->data)) - ->distance; - prefix->reported_metric = - ((struct eigrp_neighbor_entry *)(prefix->entries->head->data)) - ->total_metric; + ne->distance; + prefix->reported_metric = ne->total_metric; if (prefix->state == EIGRP_FSM_STATE_ACTIVE_3) { struct list *successors = eigrp_topology_get_successor(prefix); assert(successors); // It's like Napolean and Waterloo - eigrp_send_reply( - ((struct eigrp_neighbor_entry *)successors->head->data) - ->adv_router, - prefix); + ne = listnode_head(successors); + eigrp_send_reply(ne->adv_router, + prefix); list_delete(successors); } @@ -473,15 +461,15 @@ int eigrp_fsm_event_lr(struct eigrp_fsm_action_message *msg) int eigrp_fsm_event_dinc(struct eigrp_fsm_action_message *msg) { struct list *successors = eigrp_topology_get_successor(msg->prefix); + struct eigrp_neighbor_entry *ne; assert(successors); // Trump and his big hands + ne = listnode_head(successors); msg->prefix->state = msg->prefix->state == EIGRP_FSM_STATE_ACTIVE_1 ? EIGRP_FSM_STATE_ACTIVE_0 : EIGRP_FSM_STATE_ACTIVE_2; - msg->prefix->distance = - ((struct eigrp_neighbor_entry *)successors->head->data) - ->distance; + msg->prefix->distance = ne->distance; if (!msg->prefix->rij->count) (*(NSM[msg->prefix->state][eigrp_get_fsm_event(msg)].func))( msg); @@ -495,13 +483,11 @@ int eigrp_fsm_event_lr_fcs(struct eigrp_fsm_action_message *msg) { struct eigrp *eigrp = msg->eigrp; struct eigrp_prefix_entry *prefix = msg->prefix; + struct eigrp_neighbor_entry *ne = listnode_head(prefix->entries); + prefix->state = EIGRP_FSM_STATE_PASSIVE; - prefix->distance = prefix->rdistance = - ((struct eigrp_neighbor_entry *)(prefix->entries->head->data)) - ->distance; - prefix->reported_metric = - ((struct eigrp_neighbor_entry *)(prefix->entries->head->data)) - ->total_metric; + prefix->distance = prefix->rdistance = ne->distance; + prefix->reported_metric = ne->total_metric; prefix->fdistance = prefix->fdistance > prefix->distance ? prefix->distance : prefix->fdistance; @@ -510,11 +496,9 @@ int eigrp_fsm_event_lr_fcs(struct eigrp_fsm_action_message *msg) assert(successors); // Having a spoon and all you need is a // knife - - eigrp_send_reply( - ((struct eigrp_neighbor_entry *)successors->head->data) - ->adv_router, - prefix); + ne = listnode_head(successors); + eigrp_send_reply(ne->adv_router, + prefix); list_delete(successors); } @@ -531,6 +515,7 @@ int eigrp_fsm_event_lr_fcn(struct eigrp_fsm_action_message *msg) { struct eigrp *eigrp = msg->eigrp; struct eigrp_prefix_entry *prefix = msg->prefix; + struct eigrp_neighbor_entry *best_successor; struct list *successors = eigrp_topology_get_successor(prefix); assert(successors); // Routing without a stack @@ -538,8 +523,8 @@ int eigrp_fsm_event_lr_fcn(struct eigrp_fsm_action_message *msg) prefix->state = prefix->state == EIGRP_FSM_STATE_ACTIVE_0 ? EIGRP_FSM_STATE_ACTIVE_1 : EIGRP_FSM_STATE_ACTIVE_3; - struct eigrp_neighbor_entry *best_successor = - ((struct eigrp_neighbor_entry *)(successors->head->data)); + + best_successor = listnode_head(successors); prefix->rdistance = prefix->distance = best_successor->distance; prefix->reported_metric = best_successor->total_metric; @@ -559,13 +544,13 @@ int eigrp_fsm_event_lr_fcn(struct eigrp_fsm_action_message *msg) int eigrp_fsm_event_qact(struct eigrp_fsm_action_message *msg) { struct list *successors = eigrp_topology_get_successor(msg->prefix); + struct eigrp_neighbor_entry *ne; assert(successors); // Cats and no Dogs + ne = listnode_head(successors); msg->prefix->state = EIGRP_FSM_STATE_ACTIVE_2; - msg->prefix->distance = - ((struct eigrp_neighbor_entry *)(successors->head->data)) - ->distance; + msg->prefix->distance = ne->distance; list_delete(successors); return 1; diff --git a/eigrpd/eigrp_fsm.h b/eigrpd/eigrp_fsm.h index 97a1f49281..8fad9d1f51 100644 --- a/eigrpd/eigrp_fsm.h +++ b/eigrpd/eigrp_fsm.h @@ -28,8 +28,7 @@ #ifndef _ZEBRA_EIGRP_FSM_H #define _ZEBRA_EIGRP_FSM_H -extern int eigrp_get_fsm_event(struct eigrp_fsm_action_message *); -extern int eigrp_fsm_event(struct eigrp_fsm_action_message *, int); +extern int eigrp_fsm_event(struct eigrp_fsm_action_message *msg); #endif /* _ZEBRA_EIGRP_DUAL_H */ diff --git a/eigrpd/eigrp_interface.c b/eigrpd/eigrp_interface.c index 22b6fa394f..aa59516002 100644 --- a/eigrpd/eigrp_interface.c +++ b/eigrpd/eigrp_interface.c @@ -53,6 +53,7 @@ #include "eigrpd/eigrp_network.h" #include "eigrpd/eigrp_topology.h" #include "eigrpd/eigrp_memory.h" +#include "eigrpd/eigrp_fsm.h" static void eigrp_delete_from_if(struct interface *, struct eigrp_interface *); @@ -224,14 +225,14 @@ void eigrp_del_if_params(struct eigrp_if_params *eip) struct eigrp_if_params *eigrp_lookup_if_params(struct interface *ifp, struct in_addr addr) { - struct prefix_ipv4 p; + struct prefix p; struct route_node *rn; p.family = AF_INET; p.prefixlen = IPV4_MAX_PREFIXLEN; - p.prefix = addr; + p.u.prefix4 = addr; - rn = route_node_lookup(IF_OIFS_PARAMS(ifp), (struct prefix *)&p); + rn = route_node_lookup(IF_OIFS_PARAMS(ifp), &p); if (rn) { route_unlock_node(rn); @@ -279,49 +280,63 @@ int eigrp_if_up(struct eigrp_interface *ei) /*Add connected entry to topology table*/ - struct prefix_ipv4 dest_addr; - - dest_addr.family = AF_INET; - dest_addr.prefix = ei->connected->address->u.prefix4; - dest_addr.prefixlen = ei->connected->address->prefixlen; - apply_mask_ipv4(&dest_addr); - pe = eigrp_topology_table_lookup_ipv4(eigrp->topology_table, - &dest_addr); - - if (pe == NULL) { - pe = eigrp_prefix_entry_new(); - pe->serno = eigrp->serno; - pe->destination_ipv4 = prefix_ipv4_new(); - prefix_copy((struct prefix *)pe->destination_ipv4, - (struct prefix *)&dest_addr); - pe->af = AF_INET; - pe->nt = EIGRP_TOPOLOGY_TYPE_CONNECTED; - - pe->state = EIGRP_FSM_STATE_PASSIVE; - pe->fdistance = eigrp_calculate_metrics(eigrp, metric); - pe->req_action |= EIGRP_FSM_NEED_UPDATE; - eigrp_prefix_entry_add(eigrp->topology_table, pe); - listnode_add(eigrp->topology_changes_internalIPV4, pe); - } ne = eigrp_neighbor_entry_new(); ne->ei = ei; ne->reported_metric = metric; ne->total_metric = metric; ne->distance = eigrp_calculate_metrics(eigrp, metric); ne->reported_distance = 0; - ne->prefix = pe; ne->adv_router = eigrp->neighbor_self; ne->flags = EIGRP_NEIGHBOR_ENTRY_SUCCESSOR_FLAG; - eigrp_neighbor_entry_add(pe, ne); - for (ALL_LIST_ELEMENTS(eigrp->eiflist, node, nnode, ei2)) { - if (ei2->nbrs->count != 0) { + struct prefix dest_addr; + + dest_addr.family = AF_INET; + dest_addr.u.prefix4 = ei->connected->address->u.prefix4; + dest_addr.prefixlen = ei->connected->address->prefixlen; + apply_mask(&dest_addr); + pe = eigrp_topology_table_lookup_ipv4(eigrp->topology_table, + &dest_addr); + + if (pe == NULL) { + pe = eigrp_prefix_entry_new(); + pe->serno = eigrp->serno; + pe->destination = (struct prefix *)prefix_ipv4_new(); + prefix_copy(pe->destination, &dest_addr); + pe->af = AF_INET; + pe->nt = EIGRP_TOPOLOGY_TYPE_CONNECTED; + + ne->prefix = pe; + pe->reported_metric = metric; + pe->state = EIGRP_FSM_STATE_PASSIVE; + pe->fdistance = eigrp_calculate_metrics(eigrp, metric); + pe->req_action |= EIGRP_FSM_NEED_UPDATE; + eigrp_prefix_entry_add(eigrp->topology_table, pe); + listnode_add(eigrp->topology_changes_internalIPV4, pe); + + eigrp_neighbor_entry_add(pe, ne); + + for (ALL_LIST_ELEMENTS(eigrp->eiflist, node, nnode, ei2)) { eigrp_update_send(ei2); } - } - pe->req_action &= ~EIGRP_FSM_NEED_UPDATE; - listnode_delete(eigrp->topology_changes_internalIPV4, pe); + pe->req_action &= ~EIGRP_FSM_NEED_UPDATE; + listnode_delete(eigrp->topology_changes_internalIPV4, pe); + } else { + struct eigrp_fsm_action_message msg; + + ne->prefix = pe; + eigrp_neighbor_entry_add(pe, ne); + + msg.packet_type = EIGRP_OPC_UPDATE; + msg.eigrp = eigrp; + msg.data_type = EIGRP_CONNECTED; + msg.adv_router = NULL; + msg.entry = ne; + msg.prefix = pe; + + eigrp_fsm_event(&msg); + } return 1; } @@ -416,7 +431,7 @@ u_char eigrp_default_iftype(struct interface *ifp) void eigrp_if_free(struct eigrp_interface *ei, int source) { - struct prefix_ipv4 dest_addr; + struct prefix dest_addr; struct eigrp_prefix_entry *pe; struct eigrp *eigrp = eigrp_lookup(); @@ -425,10 +440,8 @@ void eigrp_if_free(struct eigrp_interface *ei, int source) eigrp_hello_send(ei, EIGRP_HELLO_GRACEFUL_SHUTDOWN, NULL); } - dest_addr.family = AF_INET; - dest_addr.prefix = ei->connected->address->u.prefix4; - dest_addr.prefixlen = ei->connected->address->prefixlen; - apply_mask_ipv4(&dest_addr); + dest_addr = *ei->connected->address; + apply_mask(&dest_addr); pe = eigrp_topology_table_lookup_ipv4(eigrp->topology_table, &dest_addr); if (pe) @@ -532,11 +545,11 @@ struct eigrp_interface *eigrp_if_lookup_recv_if(struct eigrp *eigrp, struct interface *ifp) { struct route_node *rn; - struct prefix_ipv4 addr; + struct prefix addr; struct eigrp_interface *ei, *match; addr.family = AF_INET; - addr.prefix = src; + addr.u.prefix4 = src; addr.prefixlen = IPV4_MAX_BITLEN; match = NULL; @@ -551,7 +564,7 @@ struct eigrp_interface *eigrp_if_lookup_recv_if(struct eigrp *eigrp, continue; if (prefix_match(CONNECTED_PREFIX(ei->connected), - (struct prefix *)&addr)) { + &addr)) { if ((match == NULL) || (match->address->prefixlen < ei->address->prefixlen)) match = ei; diff --git a/eigrpd/eigrp_neighbor.c b/eigrpd/eigrp_neighbor.c index d5fc6a2996..5d78dc375c 100644 --- a/eigrpd/eigrp_neighbor.c +++ b/eigrpd/eigrp_neighbor.c @@ -357,3 +357,11 @@ void eigrp_nbr_hard_restart(struct eigrp_neighbor *nbr, struct vty *vty) /* delete neighbor */ eigrp_nbr_delete(nbr); } + +int eigrp_nbr_split_horizon_check(struct eigrp_neighbor_entry *ne, struct eigrp_interface *ei) +{ + if (ne->distance == EIGRP_MAX_METRIC) + return 0; + + return (ne->ei == ei); +} diff --git a/eigrpd/eigrp_neighbor.h b/eigrpd/eigrp_neighbor.h index 006aa9ab75..6467fb24a9 100644 --- a/eigrpd/eigrp_neighbor.h +++ b/eigrpd/eigrp_neighbor.h @@ -53,4 +53,6 @@ extern struct eigrp_neighbor *eigrp_nbr_lookup_by_addr_process(struct eigrp *, struct in_addr); extern void eigrp_nbr_hard_restart(struct eigrp_neighbor *nbr, struct vty *vty); +extern int eigrp_nbr_split_horizon_check(struct eigrp_neighbor_entry *ne, + struct eigrp_interface *ei); #endif /* _ZEBRA_EIGRP_NEIGHBOR_H */ diff --git a/eigrpd/eigrp_network.c b/eigrpd/eigrp_network.c index ec8806750b..0cf5bd9bad 100644 --- a/eigrpd/eigrp_network.c +++ b/eigrpd/eigrp_network.c @@ -229,7 +229,7 @@ int eigrp_if_drop_allspfrouters(struct eigrp *top, struct prefix *p, return ret; } -int eigrp_network_set(struct eigrp *eigrp, struct prefix_ipv4 *p) +int eigrp_network_set(struct eigrp *eigrp, struct prefix *p) { struct route_node *rn; struct interface *ifp; @@ -242,7 +242,7 @@ int eigrp_network_set(struct eigrp *eigrp, struct prefix_ipv4 *p) return 0; } - struct prefix_ipv4 *pref = prefix_ipv4_new(); + struct prefix *pref = prefix_new(); PREFIX_COPY_IPV4(pref, p); rn->info = (void *)pref; @@ -253,7 +253,7 @@ int eigrp_network_set(struct eigrp *eigrp, struct prefix_ipv4 *p) /* Get target interface. */ for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), node, ifp)) { zlog_debug("Setting up %s", ifp->name); - eigrp_network_run_interface(eigrp, (struct prefix *)p, ifp); + eigrp_network_run_interface(eigrp, p, ifp); } return 1; } @@ -334,21 +334,21 @@ void eigrp_if_update(struct interface *ifp) } } -int eigrp_network_unset(struct eigrp *eigrp, struct prefix_ipv4 *p) +int eigrp_network_unset(struct eigrp *eigrp, struct prefix *p) { struct route_node *rn; struct listnode *node, *nnode; struct eigrp_interface *ei; struct prefix *pref; - rn = route_node_lookup(eigrp->networks, (struct prefix *)p); + rn = route_node_lookup(eigrp->networks, p); if (rn == NULL) return 0; pref = rn->info; route_unlock_node(rn); - if (!IPV4_ADDR_SAME(&pref->u.prefix4, &p->prefix)) + if (!IPV4_ADDR_SAME(&pref->u.prefix4, &p->u.prefix4)) return 0; prefix_ipv4_free(rn->info); diff --git a/eigrpd/eigrp_network.h b/eigrpd/eigrp_network.h index e38f7ded40..6ddd57eee5 100644 --- a/eigrpd/eigrp_network.h +++ b/eigrpd/eigrp_network.h @@ -32,8 +32,8 @@ extern int eigrp_sock_init(void); extern int eigrp_if_ipmulticast(struct eigrp *, struct prefix *, unsigned int); -extern int eigrp_network_set(struct eigrp *, struct prefix_ipv4 *); -extern int eigrp_network_unset(struct eigrp *eigrp, struct prefix_ipv4 *p); +extern int eigrp_network_set(struct eigrp *eigrp, struct prefix *p); +extern int eigrp_network_unset(struct eigrp *eigrp, struct prefix *p); extern int eigrp_hello_timer(struct thread *); extern void eigrp_if_update(struct interface *); diff --git a/eigrpd/eigrp_packet.c b/eigrpd/eigrp_packet.c index 72aaef1b37..68e7cdcbbe 100644 --- a/eigrpd/eigrp_packet.c +++ b/eigrpd/eigrp_packet.c @@ -1101,6 +1101,16 @@ struct eigrp_packet *eigrp_packet_duplicate(struct eigrp_packet *old, return new; } +static struct TLV_IPv4_Internal_type *eigrp_IPv4_InternalTLV_new() +{ + struct TLV_IPv4_Internal_type *new; + + new = XCALLOC(MTYPE_EIGRP_IPV4_INT_TLV, + sizeof(struct TLV_IPv4_Internal_type)); + + return new; +} + struct TLV_IPv4_Internal_type *eigrp_read_ipv4_tlv(struct stream *s) { struct TLV_IPv4_Internal_type *tlv; @@ -1157,21 +1167,21 @@ u_int16_t eigrp_add_internalTLV_to_stream(struct stream *s, u_int16_t length; stream_putw(s, EIGRP_TLV_IPv4_INT); - if (pe->destination_ipv4->prefixlen <= 8) { + if (pe->destination->prefixlen <= 8) { stream_putw(s, 0x001A); length = 0x001A; } - if ((pe->destination_ipv4->prefixlen > 8) - && (pe->destination_ipv4->prefixlen <= 16)) { + if ((pe->destination->prefixlen > 8) + && (pe->destination->prefixlen <= 16)) { stream_putw(s, 0x001B); length = 0x001B; } - if ((pe->destination_ipv4->prefixlen > 16) - && (pe->destination_ipv4->prefixlen <= 24)) { + if ((pe->destination->prefixlen > 16) + && (pe->destination->prefixlen <= 24)) { stream_putw(s, 0x001C); length = 0x001C; } - if (pe->destination_ipv4->prefixlen > 24) { + if (pe->destination->prefixlen > 24) { stream_putw(s, 0x001D); length = 0x001D; } @@ -1190,34 +1200,18 @@ u_int16_t eigrp_add_internalTLV_to_stream(struct stream *s, stream_putc(s, pe->reported_metric.tag); stream_putc(s, pe->reported_metric.flags); - stream_putc(s, pe->destination_ipv4->prefixlen); + stream_putc(s, pe->destination->prefixlen); - if (pe->destination_ipv4->prefixlen <= 8) { - stream_putc(s, pe->destination_ipv4->prefix.s_addr & 0xFF); - } - if ((pe->destination_ipv4->prefixlen > 8) - && (pe->destination_ipv4->prefixlen <= 16)) { - stream_putc(s, pe->destination_ipv4->prefix.s_addr & 0xFF); + stream_putc(s, pe->destination->u.prefix4.s_addr & 0xFF); + if (pe->destination->prefixlen > 8) stream_putc(s, - (pe->destination_ipv4->prefix.s_addr >> 8) & 0xFF); - } - if ((pe->destination_ipv4->prefixlen > 16) - && (pe->destination_ipv4->prefixlen <= 24)) { - stream_putc(s, pe->destination_ipv4->prefix.s_addr & 0xFF); + (pe->destination->u.prefix4.s_addr >> 8) & 0xFF); + if (pe->destination->prefixlen > 16) stream_putc(s, - (pe->destination_ipv4->prefix.s_addr >> 8) & 0xFF); + (pe->destination->u.prefix4.s_addr >> 16) & 0xFF); + if (pe->destination->prefixlen > 24) stream_putc(s, - (pe->destination_ipv4->prefix.s_addr >> 16) & 0xFF); - } - if (pe->destination_ipv4->prefixlen > 24) { - stream_putc(s, pe->destination_ipv4->prefix.s_addr & 0xFF); - stream_putc(s, - (pe->destination_ipv4->prefix.s_addr >> 8) & 0xFF); - stream_putc(s, - (pe->destination_ipv4->prefix.s_addr >> 16) & 0xFF); - stream_putc(s, - (pe->destination_ipv4->prefix.s_addr >> 24) & 0xFF); - } + (pe->destination->u.prefix4.s_addr >> 24) & 0xFF); return length; } @@ -1332,16 +1326,6 @@ void eigrp_authTLV_SHA256_free(struct TLV_SHA256_Authentication_Type *authTLV) XFREE(MTYPE_EIGRP_AUTH_SHA256_TLV, authTLV); } -struct TLV_IPv4_Internal_type *eigrp_IPv4_InternalTLV_new() -{ - struct TLV_IPv4_Internal_type *new; - - new = XCALLOC(MTYPE_EIGRP_IPV4_INT_TLV, - sizeof(struct TLV_IPv4_Internal_type)); - - return new; -} - void eigrp_IPv4_InternalTLV_free( struct TLV_IPv4_Internal_type *IPv4_InternalTLV) { diff --git a/eigrpd/eigrp_packet.h b/eigrpd/eigrp_packet.h index e72048ecc3..e52fd268fa 100644 --- a/eigrpd/eigrp_packet.h +++ b/eigrpd/eigrp_packet.h @@ -152,7 +152,6 @@ extern int eigrp_check_sha256_digest(struct stream *, struct eigrp_neighbor *, u_char); -extern struct TLV_IPv4_Internal_type *eigrp_IPv4_InternalTLV_new(void); extern void eigrp_IPv4_InternalTLV_free(struct TLV_IPv4_Internal_type *); extern struct TLV_Sequence_Type *eigrp_SequenceTLV_new(void); diff --git a/eigrpd/eigrp_query.c b/eigrpd/eigrp_query.c index 00f9ee1267..0167c8b3c2 100644 --- a/eigrpd/eigrp_query.c +++ b/eigrpd/eigrp_query.c @@ -91,7 +91,7 @@ void eigrp_query_receive(struct eigrp *eigrp, struct ip *iph, { struct eigrp_neighbor *nbr; struct TLV_IPv4_Internal_type *tlv; - struct prefix_ipv4 dest_addr; + struct prefix dest_addr; u_int16_t type; u_int16_t length; @@ -116,7 +116,7 @@ void eigrp_query_receive(struct eigrp *eigrp, struct ip *iph, tlv = eigrp_read_ipv4_tlv(s); dest_addr.family = AF_INET; - dest_addr.prefix = tlv->destination; + dest_addr.u.prefix4 = tlv->destination; dest_addr.prefixlen = tlv->prefix_length; struct eigrp_prefix_entry *dest = eigrp_topology_table_lookup_ipv4( @@ -125,22 +125,18 @@ void eigrp_query_receive(struct eigrp *eigrp, struct ip *iph, /* If the destination exists (it should, but one never * know)*/ if (dest != NULL) { - struct eigrp_fsm_action_message *msg; - msg = XCALLOC(MTYPE_EIGRP_FSM_MSG, - sizeof(struct - eigrp_fsm_action_message)); + struct eigrp_fsm_action_message msg; struct eigrp_neighbor_entry *entry = eigrp_prefix_entry_lookup(dest->entries, nbr); - msg->packet_type = EIGRP_OPC_QUERY; - msg->eigrp = eigrp; - msg->data_type = EIGRP_TLV_IPv4_INT; - msg->adv_router = nbr; - msg->data.ipv4_int_type = tlv; - msg->entry = entry; - msg->prefix = dest; - int event = eigrp_get_fsm_event(msg); - eigrp_fsm_event(msg, event); + msg.packet_type = EIGRP_OPC_QUERY; + msg.eigrp = eigrp; + msg.data_type = EIGRP_INT; + msg.adv_router = nbr; + msg.metrics = tlv->metric; + msg.entry = entry; + msg.prefix = dest; + eigrp_fsm_event(&msg); } eigrp_IPv4_InternalTLV_free(tlv); break; diff --git a/eigrpd/eigrp_reply.c b/eigrpd/eigrp_reply.c index e59db80393..2b5b0aa44b 100644 --- a/eigrpd/eigrp_reply.c +++ b/eigrpd/eigrp_reply.c @@ -87,19 +87,19 @@ void eigrp_send_reply(struct eigrp_neighbor *nbr, struct eigrp_prefix_entry *pe) /* Check if any list fits */ if ((alist - && access_list_apply(alist, (struct prefix *)pe2->destination_ipv4) + && access_list_apply(alist, pe2->destination) == FILTER_DENY) || (plist && prefix_list_apply(plist, - (struct prefix *)pe2->destination_ipv4) + pe2->destination) == PREFIX_DENY) || (alist_i && access_list_apply(alist_i, - (struct prefix *)pe2->destination_ipv4) + pe2->destination) == FILTER_DENY) || (plist_i && prefix_list_apply(plist_i, - (struct prefix *)pe2->destination_ipv4) + pe2->destination) == PREFIX_DENY)) { zlog_info("REPLY SEND: Setting Metric to max"); pe2->reported_metric.delay = EIGRP_MAX_METRIC; @@ -179,14 +179,14 @@ void eigrp_reply_receive(struct eigrp *eigrp, struct ip *iph, while (s->endp > s->getp) { type = stream_getw(s); if (type == EIGRP_TLV_IPv4_INT) { - struct prefix_ipv4 dest_addr; + struct prefix dest_addr; stream_set_getp(s, s->getp - sizeof(u_int16_t)); tlv = eigrp_read_ipv4_tlv(s); dest_addr.family = AF_INET; - dest_addr.prefix = tlv->destination; + dest_addr.u.prefix4 = tlv->destination; dest_addr.prefixlen = tlv->prefix_length; struct eigrp_prefix_entry *dest = eigrp_topology_table_lookup_ipv4( @@ -196,9 +196,7 @@ void eigrp_reply_receive(struct eigrp *eigrp, struct ip *iph, */ assert(dest); - struct eigrp_fsm_action_message *msg; - msg = XCALLOC(MTYPE_EIGRP_FSM_MSG, - sizeof(struct eigrp_fsm_action_message)); + struct eigrp_fsm_action_message msg; struct eigrp_neighbor_entry *entry = eigrp_prefix_entry_lookup(dest->entries, nbr); @@ -237,15 +235,14 @@ void eigrp_reply_receive(struct eigrp *eigrp, struct ip *iph, * End of filtering */ - msg->packet_type = EIGRP_OPC_REPLY; - msg->eigrp = eigrp; - msg->data_type = EIGRP_TLV_IPv4_INT; - msg->adv_router = nbr; - msg->data.ipv4_int_type = tlv; - msg->entry = entry; - msg->prefix = dest; - int event = eigrp_get_fsm_event(msg); - eigrp_fsm_event(msg, event); + msg.packet_type = EIGRP_OPC_REPLY; + msg.eigrp = eigrp; + msg.data_type = EIGRP_INT; + msg.adv_router = nbr; + msg.metrics = tlv->metric; + msg.entry = entry; + msg.prefix = dest; + eigrp_fsm_event(&msg); eigrp_IPv4_InternalTLV_free(tlv); diff --git a/eigrpd/eigrp_siaquery.c b/eigrpd/eigrp_siaquery.c index 30f65ee87d..7264e53b6b 100644 --- a/eigrpd/eigrp_siaquery.c +++ b/eigrpd/eigrp_siaquery.c @@ -78,14 +78,14 @@ void eigrp_siaquery_receive(struct eigrp *eigrp, struct ip *iph, while (s->endp > s->getp) { type = stream_getw(s); if (type == EIGRP_TLV_IPv4_INT) { - struct prefix_ipv4 dest_addr; + struct prefix dest_addr; stream_set_getp(s, s->getp - sizeof(u_int16_t)); tlv = eigrp_read_ipv4_tlv(s); dest_addr.family = AFI_IP; - dest_addr.prefix = tlv->destination; + dest_addr.u.prefix4 = tlv->destination; dest_addr.prefixlen = tlv->prefix_length; struct eigrp_prefix_entry *dest = eigrp_topology_table_lookup_ipv4( @@ -94,22 +94,18 @@ void eigrp_siaquery_receive(struct eigrp *eigrp, struct ip *iph, /* If the destination exists (it should, but one never * know)*/ if (dest != NULL) { - struct eigrp_fsm_action_message *msg; - msg = XCALLOC(MTYPE_EIGRP_FSM_MSG, - sizeof(struct - eigrp_fsm_action_message)); + struct eigrp_fsm_action_message msg; struct eigrp_neighbor_entry *entry = eigrp_prefix_entry_lookup(dest->entries, nbr); - msg->packet_type = EIGRP_OPC_SIAQUERY; - msg->eigrp = eigrp; - msg->data_type = EIGRP_TLV_IPv4_INT; - msg->adv_router = nbr; - msg->data.ipv4_int_type = tlv; - msg->entry = entry; - msg->prefix = dest; - int event = eigrp_get_fsm_event(msg); - eigrp_fsm_event(msg, event); + msg.packet_type = EIGRP_OPC_SIAQUERY; + msg.eigrp = eigrp; + msg.data_type = EIGRP_INT; + msg.adv_router = nbr; + msg.metrics = tlv->metric; + msg.entry = entry; + msg.prefix = dest; + eigrp_fsm_event(&msg); } eigrp_IPv4_InternalTLV_free(tlv); } diff --git a/eigrpd/eigrp_siareply.c b/eigrpd/eigrp_siareply.c index 3050b91032..8496c05675 100644 --- a/eigrpd/eigrp_siareply.c +++ b/eigrpd/eigrp_siareply.c @@ -77,14 +77,14 @@ void eigrp_siareply_receive(struct eigrp *eigrp, struct ip *iph, while (s->endp > s->getp) { type = stream_getw(s); if (type == EIGRP_TLV_IPv4_INT) { - struct prefix_ipv4 dest_addr; + struct prefix dest_addr; stream_set_getp(s, s->getp - sizeof(u_int16_t)); tlv = eigrp_read_ipv4_tlv(s); dest_addr.family = AFI_IP; - dest_addr.prefix = tlv->destination; + dest_addr.u.prefix4 = tlv->destination; dest_addr.prefixlen = tlv->prefix_length; struct eigrp_prefix_entry *dest = eigrp_topology_table_lookup_ipv4( @@ -93,22 +93,18 @@ void eigrp_siareply_receive(struct eigrp *eigrp, struct ip *iph, /* If the destination exists (it should, but one never * know)*/ if (dest != NULL) { - struct eigrp_fsm_action_message *msg; - msg = XCALLOC(MTYPE_EIGRP_FSM_MSG, - sizeof(struct - eigrp_fsm_action_message)); + struct eigrp_fsm_action_message msg; struct eigrp_neighbor_entry *entry = eigrp_prefix_entry_lookup(dest->entries, nbr); - msg->packet_type = EIGRP_OPC_SIAQUERY; - msg->eigrp = eigrp; - msg->data_type = EIGRP_TLV_IPv4_INT; - msg->adv_router = nbr; - msg->data.ipv4_int_type = tlv; - msg->entry = entry; - msg->prefix = dest; - int event = eigrp_get_fsm_event(msg); - eigrp_fsm_event(msg, event); + msg.packet_type = EIGRP_OPC_SIAQUERY; + msg.eigrp = eigrp; + msg.data_type = EIGRP_INT; + msg.adv_router = nbr; + msg.metrics = tlv->metric; + msg.entry = entry; + msg.prefix = dest; + eigrp_fsm_event(&msg); } eigrp_IPv4_InternalTLV_free(tlv); } diff --git a/eigrpd/eigrp_structs.h b/eigrpd/eigrp_structs.h index 0c15436d4f..b769774a03 100644 --- a/eigrpd/eigrp_structs.h +++ b/eigrpd/eigrp_structs.h @@ -469,10 +469,7 @@ struct eigrp_prefix_entry { u_char af; // address family u_char req_action; // required action - struct prefix_ipv4 - *destination_ipv4; // pointer to struct with ipv4 address - struct prefix_ipv6 - *destination_ipv6; // pointer to struct with ipv6 address + struct prefix *destination; // If network type is REMOTE_EXTERNAL, pointer will have reference to // its external TLV @@ -499,6 +496,11 @@ struct eigrp_neighbor_entry { }; //--------------------------------------------------------------------------------------------------------------------------------------------- +typedef enum { + EIGRP_CONNECTED, + EIGRP_INT, + EIGRP_EXT, +} msg_data_t; /* EIGRP Finite State Machine */ @@ -508,11 +510,8 @@ struct eigrp_fsm_action_message { struct eigrp_neighbor *adv_router; // advertising neighbor struct eigrp_neighbor_entry *entry; struct eigrp_prefix_entry *prefix; - int data_type; // internal or external tlv type - union { - struct TLV_IPv4_External_type *ipv4_ext_data; - struct TLV_IPv4_Internal_type *ipv4_int_type; - } data; + msg_data_t data_type; // internal or external tlv type + struct eigrp_metrics metrics; }; #endif /* _ZEBRA_EIGRP_STRUCTURES_H_ */ diff --git a/eigrpd/eigrp_topology.c b/eigrpd/eigrp_topology.c index 50d83430a8..64e65b694c 100644 --- a/eigrpd/eigrp_topology.c +++ b/eigrpd/eigrp_topology.c @@ -81,25 +81,18 @@ static int eigrp_prefix_entry_cmp(struct eigrp_prefix_entry *node1, { if (node1->af == AF_INET) { if (node2->af == AF_INET) { - if (node1->destination_ipv4->prefix.s_addr - < node2->destination_ipv4->prefix.s_addr) { - return -1; // if it belong above node2 - } else { - if (node1->destination_ipv4->prefix.s_addr - > node2->destination_ipv4->prefix.s_addr) { - return 1; // if it belongs under node2 - } else { - return 0; // same value... ERROR...in - // case of adding same prefix - // again - } - } - } else { + if (node1->destination->u.prefix4.s_addr + < node2->destination->u.prefix4.s_addr) + return -1; + if (node1->destination->u.prefix4.s_addr + > node2->destination->u.prefix4.s_addr) + return 1; + else + return 0; + } else return 1; - } - } else { // TODO check if the prefix dont exists - return 1; // add to end - } + } else + return 1; } /* @@ -125,8 +118,7 @@ struct eigrp_prefix_entry *eigrp_prefix_entry_new() new->rij = list_new(); new->entries->cmp = (int (*)(void *, void *))eigrp_neighbor_entry_cmp; new->distance = new->fdistance = new->rdistance = EIGRP_MAX_METRIC; - new->destination_ipv4 = NULL; - new->destination_ipv6 = NULL; + new->destination = NULL; return new; } @@ -137,9 +129,8 @@ struct eigrp_prefix_entry *eigrp_prefix_entry_new() static int eigrp_neighbor_entry_cmp(struct eigrp_neighbor_entry *entry1, struct eigrp_neighbor_entry *entry2) { - if (entry1->distance - < entry2->distance) // parameter used in list_add_sort () - return -1; // actually set to sort by distance + if (entry1->distance < entry2->distance) + return -1; if (entry1->distance > entry2->distance) return 1; @@ -205,7 +196,7 @@ void eigrp_neighbor_entry_add(struct eigrp_prefix_entry *node, listnode_add_sort(node->entries, entry); entry->prefix = node; - eigrp_zebra_route_add(node->destination_ipv4, l); + eigrp_zebra_route_add(node->destination, l); } list_delete(l); @@ -230,7 +221,7 @@ void eigrp_prefix_entry_delete(struct list *topology, list_free(node->entries); list_free(node->rij); listnode_delete(topology, node); - eigrp_zebra_route_delete(node->destination_ipv4); + eigrp_zebra_route_delete(node->destination); XFREE(MTYPE_EIGRP_PREFIX_ENTRY, node); } } @@ -243,7 +234,7 @@ void eigrp_neighbor_entry_delete(struct eigrp_prefix_entry *node, { if (listnode_lookup(node->entries, entry) != NULL) { listnode_delete(node->entries, entry); - eigrp_zebra_route_delete(node->destination_ipv4); + eigrp_zebra_route_delete(node->destination); XFREE(MTYPE_EIGRP_NEIGHBOR_ENTRY, entry); } } @@ -270,16 +261,12 @@ unsigned int eigrp_topology_table_isempty(struct list *topology) struct eigrp_prefix_entry * eigrp_topology_table_lookup_ipv4(struct list *topology_table, - struct prefix_ipv4 *address) + struct prefix *address) { struct eigrp_prefix_entry *data; struct listnode *node; for (ALL_LIST_ELEMENTS_RO(topology_table, node, data)) { - if ((data->af == AF_INET) - && (data->destination_ipv4->prefix.s_addr - == address->prefix.s_addr) - && (data->destination_ipv4->prefixlen - == address->prefixlen)) + if (prefix_same(data->destination, address)) return data; } @@ -380,37 +367,56 @@ enum metric_change eigrp_topology_update_distance(struct eigrp_fsm_action_messag struct eigrp_prefix_entry *prefix = msg->prefix; struct eigrp_neighbor_entry *entry = msg->entry; enum metric_change change = METRIC_SAME; + u_int32_t new_reported_distance; + assert(entry); - struct TLV_IPv4_External_type *ext_data = NULL; - struct TLV_IPv4_Internal_type *int_data = NULL; - if (msg->data_type == EIGRP_TLV_IPv4_INT) { - u_int32_t new_reported_distance; + switch(msg->data_type) { + case EIGRP_CONNECTED: + if (prefix->nt == EIGRP_TOPOLOGY_TYPE_CONNECTED) + return change; - int_data = msg->data.ipv4_int_type; - if (eigrp_metrics_is_same(int_data->metric, + change = METRIC_DECREASE; + break; + case EIGRP_INT: + if (prefix->nt == EIGRP_TOPOLOGY_TYPE_CONNECTED) { + change = METRIC_INCREASE; + goto distance_done; + } + if (eigrp_metrics_is_same(msg->metrics, entry->reported_metric)) { return change; // No change } new_reported_distance = eigrp_calculate_metrics(eigrp, - int_data->metric); + msg->metrics); - if (entry->reported_distance < new_reported_distance) + if (entry->reported_distance < new_reported_distance) { change = METRIC_INCREASE; - else + goto distance_done; + } else change = METRIC_DECREASE; - entry->reported_metric = int_data->metric; + entry->reported_metric = msg->metrics; entry->reported_distance = new_reported_distance; - eigrp_calculate_metrics(eigrp, int_data->metric); + eigrp_calculate_metrics(eigrp, msg->metrics); entry->distance = eigrp_calculate_total_metrics(eigrp, entry); - } else { - ext_data = msg->data.ipv4_ext_data; - if (eigrp_metrics_is_same(ext_data->metric, - entry->reported_metric)) - return change; + break; + case EIGRP_EXT: + if (prefix->nt == EIGRP_TOPOLOGY_TYPE_REMOTE_EXTERNAL) { + if (eigrp_metrics_is_same(msg->metrics, + entry->reported_metric)) + return change; + } else { + change = METRIC_INCREASE; + goto distance_done; + } + break; + default: + zlog_err("%s: Please implement handler", __PRETTY_FUNCTION__); + break; } + distance_done: /* * Move to correct position in list according to new distance */ @@ -464,13 +470,14 @@ void eigrp_update_routing_table(struct eigrp_prefix_entry *prefix) struct eigrp_neighbor_entry *entry; if (successors) { - eigrp_zebra_route_add(prefix->destination_ipv4, successors); + eigrp_zebra_route_add(prefix->destination, + successors); for (ALL_LIST_ELEMENTS_RO(successors, node, entry)) entry->flags |= EIGRP_NEIGHBOR_ENTRY_INTABLE_FLAG; list_delete(successors); } else { - eigrp_zebra_route_delete(prefix->destination_ipv4); + eigrp_zebra_route_delete(prefix->destination); for (ALL_LIST_ELEMENTS_RO(prefix->entries, node, entry)) entry->flags &= ~EIGRP_NEIGHBOR_ENTRY_INTABLE_FLAG; } @@ -485,24 +492,19 @@ void eigrp_topology_neighbor_down(struct eigrp *eigrp, for (ALL_LIST_ELEMENTS(eigrp->topology_table, node1, node11, prefix)) { for (ALL_LIST_ELEMENTS(prefix->entries, node2, node22, entry)) { - if (entry->adv_router == nbr) { - struct eigrp_fsm_action_message *msg; - msg = XCALLOC(MTYPE_EIGRP_FSM_MSG, - sizeof(struct - eigrp_fsm_action_message)); - struct TLV_IPv4_Internal_type *tlv = - eigrp_IPv4_InternalTLV_new(); - tlv->metric.delay = EIGRP_MAX_METRIC; - msg->packet_type = EIGRP_OPC_UPDATE; - msg->eigrp = eigrp; - msg->data_type = EIGRP_TLV_IPv4_INT; - msg->adv_router = nbr; - msg->data.ipv4_int_type = tlv; - msg->entry = entry; - msg->prefix = prefix; - int event = eigrp_get_fsm_event(msg); - eigrp_fsm_event(msg, event); - } + struct eigrp_fsm_action_message msg; + + if (entry->adv_router != nbr) + continue; + + msg.metrics.delay = EIGRP_MAX_METRIC; + msg.packet_type = EIGRP_OPC_UPDATE; + msg.eigrp = eigrp; + msg.data_type = EIGRP_INT; + msg.adv_router = nbr; + msg.entry = entry; + msg.prefix = prefix; + eigrp_fsm_event(&msg); } } diff --git a/eigrpd/eigrp_topology.h b/eigrpd/eigrp_topology.h index 0c9b5c60c6..8bff08b75a 100644 --- a/eigrpd/eigrp_topology.h +++ b/eigrpd/eigrp_topology.h @@ -49,7 +49,7 @@ extern void eigrp_neighbor_entry_delete(struct eigrp_prefix_entry *, extern void eigrp_topology_delete_all(struct list *); extern unsigned int eigrp_topology_table_isempty(struct list *); extern struct eigrp_prefix_entry * -eigrp_topology_table_lookup_ipv4(struct list *, struct prefix_ipv4 *); +eigrp_topology_table_lookup_ipv4(struct list *, struct prefix *); extern struct list *eigrp_topology_get_successor(struct eigrp_prefix_entry *); extern struct list * eigrp_topology_get_successor_max(struct eigrp_prefix_entry *pe, diff --git a/eigrpd/eigrp_update.c b/eigrpd/eigrp_update.c index d0c6520c4e..d6a1134124 100644 --- a/eigrpd/eigrp_update.c +++ b/eigrpd/eigrp_update.c @@ -112,47 +112,31 @@ static void eigrp_update_receive_GR_ask(struct eigrp *eigrp, { struct listnode *node1; struct eigrp_prefix_entry *prefix; - struct TLV_IPv4_Internal_type *tlv_max; + struct eigrp_fsm_action_message fsm_msg; /* iterate over all prefixes which weren't advertised by neighbor */ for (ALL_LIST_ELEMENTS_RO(nbr_prefixes, node1, prefix)) { - zlog_debug("GR receive: Neighbor not advertised %s/%d", - inet_ntoa(prefix->destination_ipv4->prefix), - prefix->destination_ipv4->prefixlen); + char buffer[PREFIX_STRLEN]; + zlog_debug("GR receive: Neighbor not advertised %s", + prefix2str(prefix->destination, + buffer, PREFIX_STRLEN)); - /* create internal IPv4 TLV with infinite delay */ - tlv_max = eigrp_IPv4_InternalTLV_new(); - tlv_max->type = EIGRP_TLV_IPv4_INT; - tlv_max->length = 28U; - tlv_max->metric = prefix->reported_metric; + fsm_msg.metrics = prefix->reported_metric; /* set delay to MAX */ - tlv_max->metric.delay = EIGRP_MAX_METRIC; - tlv_max->destination = prefix->destination_ipv4->prefix; - tlv_max->prefix_length = prefix->destination_ipv4->prefixlen; - - - /* prepare message for FSM */ - struct eigrp_fsm_action_message *fsm_msg; - fsm_msg = XCALLOC(MTYPE_EIGRP_FSM_MSG, - sizeof(struct eigrp_fsm_action_message)); + fsm_msg.metrics.delay = EIGRP_MAX_METRIC; struct eigrp_neighbor_entry *entry = eigrp_prefix_entry_lookup(prefix->entries, nbr); - fsm_msg->packet_type = EIGRP_OPC_UPDATE; - fsm_msg->eigrp = eigrp; - fsm_msg->data_type = EIGRP_TLV_IPv4_INT; - fsm_msg->adv_router = nbr; - fsm_msg->data.ipv4_int_type = tlv_max; - fsm_msg->entry = entry; - fsm_msg->prefix = prefix; + fsm_msg.packet_type = EIGRP_OPC_UPDATE; + fsm_msg.eigrp = eigrp; + fsm_msg.data_type = EIGRP_INT; + fsm_msg.adv_router = nbr; + fsm_msg.entry = entry; + fsm_msg.prefix = prefix; /* send message to FSM */ - int event = eigrp_get_fsm_event(fsm_msg); - eigrp_fsm_event(fsm_msg, event); - - /* free memory used by TLV */ - eigrp_IPv4_InternalTLV_free(tlv_max); + eigrp_fsm_event(&fsm_msg); } } @@ -173,7 +157,7 @@ void eigrp_update_receive(struct eigrp *eigrp, struct ip *iph, u_char same; struct access_list *alist; struct prefix_list *plist; - struct prefix_ipv4 dest_addr; + struct prefix dest_addr; struct eigrp *e; u_char graceful_restart; u_char graceful_restart_final; @@ -297,7 +281,7 @@ void eigrp_update_receive(struct eigrp *eigrp, struct ip *iph, /*searching if destination exists */ dest_addr.family = AF_INET; - dest_addr.prefix = tlv->destination; + dest_addr.u.prefix4 = tlv->destination; dest_addr.prefixlen = tlv->prefix_length; struct eigrp_prefix_entry *dest = eigrp_topology_table_lookup_ipv4( @@ -311,31 +295,26 @@ void eigrp_update_receive(struct eigrp *eigrp, struct ip *iph, remove_received_prefix_gr(nbr_prefixes, dest); - struct eigrp_fsm_action_message *msg; - msg = XCALLOC(MTYPE_EIGRP_FSM_MSG, - sizeof(struct - eigrp_fsm_action_message)); + struct eigrp_fsm_action_message msg; struct eigrp_neighbor_entry *entry = eigrp_prefix_entry_lookup(dest->entries, nbr); - msg->packet_type = EIGRP_OPC_UPDATE; - msg->eigrp = eigrp; - msg->data_type = EIGRP_TLV_IPv4_INT; - msg->adv_router = nbr; - msg->data.ipv4_int_type = tlv; - msg->entry = entry; - msg->prefix = dest; - int event = eigrp_get_fsm_event(msg); - eigrp_fsm_event(msg, event); + msg.packet_type = EIGRP_OPC_UPDATE; + msg.eigrp = eigrp; + msg.data_type = EIGRP_INT; + msg.adv_router = nbr; + msg.metrics = tlv->metric; + msg.entry = entry; + msg.prefix = dest; + eigrp_fsm_event(&msg); } else { /*Here comes topology information save*/ pe = eigrp_prefix_entry_new(); pe->serno = eigrp->serno; - pe->destination_ipv4 = prefix_ipv4_new(); - prefix_copy( - (struct prefix *)pe->destination_ipv4, - (struct prefix *)&dest_addr); + pe->destination = (struct prefix *)prefix_ipv4_new(); + prefix_copy(pe->destination, + &dest_addr); pe->af = AF_INET; pe->state = EIGRP_FSM_STATE_PASSIVE; pe->nt = EIGRP_TOPOLOGY_TYPE_REMOTE; @@ -359,9 +338,8 @@ void eigrp_update_receive(struct eigrp *eigrp, struct ip *iph, /* Check if access-list fits */ if (alist - && access_list_apply( - alist, - (struct prefix *)&dest_addr) + && access_list_apply(alist, + &dest_addr) == FILTER_DENY) { /* If yes, set reported metric to Max */ ne->reported_metric.delay = @@ -376,9 +354,8 @@ void eigrp_update_receive(struct eigrp *eigrp, struct ip *iph, /* Check if prefix-list fits */ if (plist - && prefix_list_apply( - plist, - (struct prefix *)&dest_addr) + && prefix_list_apply(plist, + &dest_addr) == PREFIX_DENY) { /* If yes, set reported metric to Max */ ne->reported_metric.delay = @@ -390,9 +367,8 @@ void eigrp_update_receive(struct eigrp *eigrp, struct ip *iph, /* Check if access-list fits */ if (alist - && access_list_apply( - alist, - (struct prefix *)&dest_addr) + && access_list_apply(alist, + &dest_addr) == FILTER_DENY) { /* If yes, set reported metric to Max */ ne->reported_metric.delay = @@ -403,9 +379,8 @@ void eigrp_update_receive(struct eigrp *eigrp, struct ip *iph, /* Check if prefix-list fits */ if (plist - && prefix_list_apply( - plist, - (struct prefix *)&dest_addr) + && prefix_list_apply(plist, + &dest_addr) == PREFIX_DENY) { /* If yes, set reported metric to Max */ ne->reported_metric.delay = @@ -592,7 +567,7 @@ void eigrp_update_send_EOT(struct eigrp_neighbor *nbr) struct access_list *alist_i; struct prefix_list *plist_i; struct eigrp *e; - struct prefix_ipv4 *dest_addr; + struct prefix *dest_addr; u_int32_t seq_no = nbr->ei->eigrp->sequence_number; ep = eigrp_packet_new(nbr->ei->ifp->mtu, nbr); @@ -610,8 +585,7 @@ void eigrp_update_send_EOT(struct eigrp_neighbor *nbr) for (ALL_LIST_ELEMENTS(nbr->ei->eigrp->topology_table, node, nnode, pe)) { for (ALL_LIST_ELEMENTS(pe->entries, node2, nnode2, te)) { - if ((te->ei == nbr->ei) - && (te->prefix->nt == EIGRP_TOPOLOGY_TYPE_REMOTE)) + if (eigrp_nbr_split_horizon_check(te, nbr->ei)) continue; if ((length + 0x001D) > (u_int16_t)nbr->ei->ifp->mtu) { @@ -631,7 +605,7 @@ void eigrp_update_send_EOT(struct eigrp_neighbor *nbr) } } /* Get destination address from prefix */ - dest_addr = pe->destination_ipv4; + dest_addr = pe->destination; /* * Filtering @@ -648,13 +622,13 @@ void eigrp_update_send_EOT(struct eigrp_neighbor *nbr) /* Check if any list fits */ if ((alist && access_list_apply (alist, - (struct prefix *) dest_addr) == FILTER_DENY)|| + dest_addr) == FILTER_DENY)|| (plist && prefix_list_apply (plist, - (struct prefix *) dest_addr) == PREFIX_DENY)|| + dest_addr) == PREFIX_DENY)|| (alist_i && access_list_apply (alist_i, - (struct prefix *) dest_addr) == FILTER_DENY)|| + dest_addr) == FILTER_DENY)|| (plist_i && prefix_list_apply (plist_i, - (struct prefix *) dest_addr) == PREFIX_DENY)) { + dest_addr) == PREFIX_DENY)) { //pe->reported_metric.delay = EIGRP_MAX_METRIC; continue; } else { @@ -678,7 +652,7 @@ void eigrp_update_send(struct eigrp_interface *ei) struct access_list *alist_i; struct prefix_list *plist_i; struct eigrp *e; - struct prefix_ipv4 *dest_addr; + struct prefix *dest_addr; u_int32_t seq_no = ei->eigrp->sequence_number; if (ei->nbrs->count == 0) @@ -701,10 +675,15 @@ void eigrp_update_send(struct eigrp_interface *ei) has_tlv = 0; for (ALL_LIST_ELEMENTS(ei->eigrp->topology_changes_internalIPV4, node, nnode, pe)) { + struct eigrp_neighbor_entry *ne; if (!(pe->req_action & EIGRP_FSM_NEED_UPDATE)) continue; + ne = listnode_head(pe->entries); + if (eigrp_nbr_split_horizon_check(ne, ei)) + continue; + if ((length + 0x001D) > (u_int16_t)ei->ifp->mtu) { if ((IF_DEF_PARAMS(ei->ifp)->auth_type == EIGRP_AUTH_TYPE_MD5) && (IF_DEF_PARAMS(ei->ifp)->auth_keychain != NULL)) { @@ -731,7 +710,7 @@ void eigrp_update_send(struct eigrp_interface *ei) has_tlv = 0; } /* Get destination address from prefix */ - dest_addr = pe->destination_ipv4; + dest_addr = pe->destination; /* * Filtering @@ -747,19 +726,19 @@ void eigrp_update_send(struct eigrp_interface *ei) /* Check if any list fits */ if ((alist && access_list_apply(alist, - (struct prefix *)dest_addr) + dest_addr) == FILTER_DENY) || (plist && prefix_list_apply(plist, - (struct prefix *)dest_addr) + dest_addr) == PREFIX_DENY) || (alist_i && access_list_apply(alist_i, - (struct prefix *)dest_addr) + dest_addr) == FILTER_DENY) || (plist_i && prefix_list_apply(plist_i, - (struct prefix *)dest_addr) + dest_addr) == PREFIX_DENY)) { // pe->reported_metric.delay = EIGRP_MAX_METRIC; continue; @@ -841,14 +820,13 @@ static void eigrp_update_send_GR_part(struct eigrp_neighbor *nbr) u_int16_t length = EIGRP_HEADER_LEN; struct listnode *node, *nnode; struct eigrp_prefix_entry *pe; - struct prefix_ipv4 *dest_addr; + struct prefix *dest_addr; struct eigrp *e; struct access_list *alist, *alist_i; struct prefix_list *plist, *plist_i; struct list *prefixes; u_int32_t flags; unsigned int send_prefixes; - struct TLV_IPv4_Internal_type *tlv_max; /* get prefixes to send to neighbor */ prefixes = nbr->nbr_gr_prefixes_send; @@ -905,7 +883,7 @@ static void eigrp_update_send_GR_part(struct eigrp_neighbor *nbr) /* * Filtering */ - dest_addr = pe->destination_ipv4; + dest_addr = pe->destination; /* get list from eigrp process */ e = eigrp_lookup(); /* Get access-lists and prefix-lists from process and interface @@ -917,22 +895,20 @@ static void eigrp_update_send_GR_part(struct eigrp_neighbor *nbr) /* Check if any list fits */ if ((alist - && access_list_apply(alist, (struct prefix *)dest_addr) + && access_list_apply(alist, dest_addr) == FILTER_DENY) || (plist - && prefix_list_apply(plist, (struct prefix *)dest_addr) + && prefix_list_apply(plist, dest_addr) == PREFIX_DENY) || (alist_i - && access_list_apply(alist_i, - (struct prefix *)dest_addr) + && access_list_apply(alist_i, dest_addr) == FILTER_DENY) || (plist_i - && prefix_list_apply(plist_i, - (struct prefix *)dest_addr) + && prefix_list_apply(plist_i, dest_addr) == PREFIX_DENY)) { /* do not send filtered route */ zlog_info("Filtered prefix %s won't be sent out.", - inet_ntoa(dest_addr->prefix)); + inet_ntoa(dest_addr->u.prefix4)); } else { /* sending route which wasn't filtered */ length += eigrp_add_internalTLV_to_stream(ep->s, pe); @@ -946,56 +922,39 @@ static void eigrp_update_send_GR_part(struct eigrp_neighbor *nbr) /* Check if any list fits */ if ((alist - && access_list_apply(alist, (struct prefix *)dest_addr) + && access_list_apply(alist, dest_addr) == FILTER_DENY) || (plist - && prefix_list_apply(plist, (struct prefix *)dest_addr) + && prefix_list_apply(plist, dest_addr) == PREFIX_DENY) || (alist_i - && access_list_apply(alist_i, - (struct prefix *)dest_addr) + && access_list_apply(alist_i, dest_addr) == FILTER_DENY) || (plist_i - && prefix_list_apply(plist_i, - (struct prefix *)dest_addr) + && prefix_list_apply(plist_i, dest_addr) == PREFIX_DENY)) { /* do not send filtered route */ zlog_info("Filtered prefix %s will be removed.", - inet_ntoa(dest_addr->prefix)); - - tlv_max = eigrp_IPv4_InternalTLV_new(); - tlv_max->type = EIGRP_TLV_IPv4_INT; - tlv_max->length = 28U; - tlv_max->metric = pe->reported_metric; - /* set delay to MAX */ - tlv_max->metric.delay = EIGRP_MAX_METRIC; - tlv_max->destination = pe->destination_ipv4->prefix; - tlv_max->prefix_length = - pe->destination_ipv4->prefixlen; + inet_ntoa(dest_addr->u.prefix4)); /* prepare message for FSM */ - struct eigrp_fsm_action_message *fsm_msg; - fsm_msg = XCALLOC( - MTYPE_EIGRP_FSM_MSG, - sizeof(struct eigrp_fsm_action_message)); + struct eigrp_fsm_action_message fsm_msg; struct eigrp_neighbor_entry *entry = eigrp_prefix_entry_lookup(pe->entries, nbr); - fsm_msg->packet_type = EIGRP_OPC_UPDATE; - fsm_msg->eigrp = e; - fsm_msg->data_type = EIGRP_TLV_IPv4_INT; - fsm_msg->adv_router = nbr; - fsm_msg->data.ipv4_int_type = tlv_max; - fsm_msg->entry = entry; - fsm_msg->prefix = pe; + fsm_msg.packet_type = EIGRP_OPC_UPDATE; + fsm_msg.eigrp = e; + fsm_msg.data_type = EIGRP_INT; + fsm_msg.adv_router = nbr; + fsm_msg.metrics = pe->reported_metric; + /* Set delay to MAX */ + fsm_msg.metrics.delay = EIGRP_MAX_METRIC; + fsm_msg.entry = entry; + fsm_msg.prefix = pe; /* send message to FSM */ - int event = eigrp_get_fsm_event(fsm_msg); - eigrp_fsm_event(fsm_msg, event); - - /* free memory used by TLV */ - eigrp_IPv4_InternalTLV_free(tlv_max); + eigrp_fsm_event(&fsm_msg); } /* * End of filtering diff --git a/eigrpd/eigrp_vty.c b/eigrpd/eigrp_vty.c index 465007478d..4a8842f30e 100644 --- a/eigrpd/eigrp_vty.c +++ b/eigrpd/eigrp_vty.c @@ -391,10 +391,10 @@ DEFUN (eigrp_network, "EIGRP network prefix\n") { VTY_DECLVAR_CONTEXT(eigrp, eigrp); - struct prefix_ipv4 p; + struct prefix p; int ret; - str2prefix_ipv4(argv[1]->arg, &p); + str2prefix(argv[1]->arg, &p); ret = eigrp_network_set(eigrp, &p); @@ -414,10 +414,10 @@ DEFUN (no_eigrp_network, "EIGRP network prefix\n") { VTY_DECLVAR_CONTEXT(eigrp, eigrp); - struct prefix_ipv4 p; + struct prefix p; int ret; - str2prefix_ipv4(argv[2]->arg, &p); + str2prefix(argv[2]->arg, &p); ret = eigrp_network_unset(eigrp, &p); diff --git a/eigrpd/eigrp_zebra.c b/eigrpd/eigrp_zebra.c index 1ee1237f75..47871dfd3e 100644 --- a/eigrpd/eigrp_zebra.c +++ b/eigrpd/eigrp_zebra.c @@ -66,8 +66,8 @@ static int eigrp_interface_state_down(int, struct zclient *, zebra_size_t, vrf_id_t vrf_id); static struct interface *zebra_interface_if_lookup(struct stream *); -static int eigrp_zebra_read_ipv4(int, struct zclient *, zebra_size_t, - vrf_id_t vrf_id); +static int eigrp_zebra_read_route(int, struct zclient *, zebra_size_t, + vrf_id_t vrf_id); /* Zebra structure to hold current status. */ struct zclient *zclient = NULL; @@ -112,59 +112,31 @@ void eigrp_zebra_init(void) zclient->interface_down = eigrp_interface_state_down; zclient->interface_address_add = eigrp_interface_address_add; zclient->interface_address_delete = eigrp_interface_address_delete; - zclient->redistribute_route_ipv4_add = eigrp_zebra_read_ipv4; - zclient->redistribute_route_ipv4_del = eigrp_zebra_read_ipv4; + zclient->redistribute_route_add = eigrp_zebra_read_route; + zclient->redistribute_route_del = eigrp_zebra_read_route; } /* Zebra route add and delete treatment. */ -static int eigrp_zebra_read_ipv4(int command, struct zclient *zclient, - zebra_size_t length, vrf_id_t vrf_id) +static int eigrp_zebra_read_route(int command, struct zclient *zclient, + zebra_size_t length, vrf_id_t vrf_id) { - struct stream *s; - struct zapi_ipv4 api; - struct prefix_ipv4 p; + struct zapi_route api; struct eigrp *eigrp; - s = zclient->ibuf; + if (zapi_route_decode(zclient->ibuf, &api) < 0) + return -1; - /* Type, flags, message. */ - api.type = stream_getc(s); - api.instance = stream_getw(s); - api.flags = stream_getc(s); - api.message = stream_getc(s); - - /* IPv4 prefix. */ - memset(&p, 0, sizeof(struct prefix_ipv4)); - p.family = AF_INET; - p.prefixlen = stream_getc(s); - stream_get(&p.prefix, s, PSIZE(p.prefixlen)); - - if (IPV4_NET127(ntohl(p.prefix.s_addr))) + if (IPV4_NET127(ntohl(api.prefix.u.prefix4.s_addr))) return 0; - /* Nexthop, ifindex, distance, metric. */ - if (CHECK_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP)) { - api.nexthop_num = stream_getc(s); - stream_get_ipv4(s); - } - if (CHECK_FLAG(api.message, ZAPI_MESSAGE_IFINDEX)) { - api.ifindex_num = stream_getc(s); - /* XXX assert(api.ifindex_num == 1); */ - stream_getl(s); /* ifindex, unused */ - } - if (CHECK_FLAG(api.message, ZAPI_MESSAGE_DISTANCE)) - api.distance = stream_getc(s); - if (CHECK_FLAG(api.message, ZAPI_MESSAGE_METRIC)) - api.metric = stream_getl(s); - eigrp = eigrp_lookup(); if (eigrp == NULL) return 0; - if (command == ZEBRA_IPV4_ROUTE_ADD) { + if (command == ZEBRA_REDISTRIBUTE_ROUTE_ADD) { - } else /* if (command == ZEBRA_IPV4_ROUTE_DELETE) */ + } else /* if (command == ZEBRA_REDISTRIBUTE_ROUTE_DEL) */ { } @@ -389,90 +361,67 @@ static struct interface *zebra_interface_if_lookup(struct stream *s) ifname_tmp, strnlen(ifname_tmp, INTERFACE_NAMSIZ), VRF_DEFAULT); } -void eigrp_zebra_route_add(struct prefix_ipv4 *p, struct list *successors) +void eigrp_zebra_route_add(struct prefix *p, struct list *successors) { + struct zapi_route api; + struct zapi_nexthop *api_nh; struct eigrp_neighbor_entry *te; struct listnode *node; - u_char message; - u_char flags; - int psize; - struct stream *s; + int count = 0; - if (zclient->redist[AFI_IP][ZEBRA_ROUTE_EIGRP]) { - message = 0; - flags = 0; + if (!zclient->redist[AFI_IP][ZEBRA_ROUTE_EIGRP]) + return; - /* EIGRP pass nexthop and metric */ - SET_FLAG(message, ZAPI_MESSAGE_NEXTHOP); + memset(&api, 0, sizeof(api)); + api.vrf_id = VRF_DEFAULT; + api.type = ZEBRA_ROUTE_EIGRP; + api.safi = SAFI_UNICAST; + memcpy(&api.prefix, p, sizeof(*p)); - /* Make packet. */ - s = zclient->obuf; - stream_reset(s); + SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP); + api.nexthop_num = successors->count; - /* Put command, type, flags, message. */ - zclient_create_header(s, ZEBRA_IPV4_ROUTE_ADD, VRF_DEFAULT); - stream_putc(s, ZEBRA_ROUTE_EIGRP); - stream_putw(s, 0); - stream_putl(s, flags); - stream_putc(s, message); - stream_putw(s, SAFI_UNICAST); + /* Nexthop, ifindex, distance and metric information. */ + for (ALL_LIST_ELEMENTS_RO(successors, node, te)) { + api_nh = &api.nexthops[count]; + if (te->adv_router->src.s_addr) { + api_nh->gate.ipv4 = te->adv_router->src; + api_nh->type = NEXTHOP_TYPE_IPV4_IFINDEX; + } else + api_nh->type = NEXTHOP_TYPE_IFINDEX; + api_nh->ifindex = te->ei->ifp->ifindex; - /* Put prefix information. */ - psize = PSIZE(p->prefixlen); - stream_putc(s, p->prefixlen); - stream_write(s, (u_char *)&p->prefix, psize); - - /* Nexthop count. */ - stream_putc(s, successors->count); - - /* Nexthop, ifindex, distance and metric information. */ - for (ALL_LIST_ELEMENTS_RO(successors, node, te)) { - if (te->adv_router->src.s_addr) { - stream_putc(s, NEXTHOP_TYPE_IPV4_IFINDEX); - stream_put_in_addr(s, &te->adv_router->src); - } else - stream_putc(s, NEXTHOP_TYPE_IFINDEX); - stream_putl(s, te->ei->ifp->ifindex); - } - - if (IS_DEBUG_EIGRP(zebra, ZEBRA_REDISTRIBUTE)) { - char buf[2][INET_ADDRSTRLEN]; - zlog_debug("Zebra: Route add %s/%d nexthop %s", - inet_ntop(AF_INET, &p->prefix, buf[0], - sizeof(buf[0])), - p->prefixlen, - inet_ntop(AF_INET, 0 /*&p->nexthop*/, buf[1], - sizeof(buf[1]))); - } - - stream_putw_at(s, 0, stream_get_endp(s)); - - zclient_send_message(zclient); + count++; } + + if (IS_DEBUG_EIGRP(zebra, ZEBRA_REDISTRIBUTE)) { + char buf[2][PREFIX_STRLEN]; + zlog_debug("Zebra: Route add %s nexthop %s", + prefix2str(p, buf[0], PREFIX_STRLEN), + inet_ntop(AF_INET, 0, buf[1], PREFIX_STRLEN)); + } + + zclient_route_send(ZEBRA_ROUTE_ADD, zclient, &api); } -void eigrp_zebra_route_delete(struct prefix_ipv4 *p) +void eigrp_zebra_route_delete(struct prefix *p) { - struct zapi_ipv4 api; + struct zapi_route api; - if (zclient->redist[AFI_IP][ZEBRA_ROUTE_EIGRP]) { - api.vrf_id = VRF_DEFAULT; - api.type = ZEBRA_ROUTE_EIGRP; - api.instance = 0; - api.flags = 0; - api.message = 0; - api.safi = SAFI_UNICAST; - zapi_ipv4_route(ZEBRA_IPV4_ROUTE_DELETE, zclient, p, &api); + if (!zclient->redist[AFI_IP][ZEBRA_ROUTE_EIGRP]) + return; - if (IS_DEBUG_EIGRP(zebra, ZEBRA_REDISTRIBUTE)) { - char buf[2][INET_ADDRSTRLEN]; - zlog_debug("Zebra: Route del %s/%d nexthop %s", - inet_ntop(AF_INET, &p->prefix, buf[0], - sizeof(buf[0])), - p->prefixlen, - inet_ntop(AF_INET, 0 /*&p->nexthop*/, buf[1], - sizeof(buf[1]))); - } + memset(&api, 0, sizeof(api)); + api.vrf_id = VRF_DEFAULT; + api.type = ZEBRA_ROUTE_EIGRP; + api.safi = SAFI_UNICAST; + memcpy(&api.prefix, p, sizeof(*p)); + zclient_route_send(ZEBRA_ROUTE_DELETE, zclient, &api); + + if (IS_DEBUG_EIGRP(zebra, ZEBRA_REDISTRIBUTE)) { + char buf[PREFIX_STRLEN]; + zlog_debug("Zebra: Route del %s", + prefix2str(p, buf, PREFIX_STRLEN)); } return; diff --git a/eigrpd/eigrp_zebra.h b/eigrpd/eigrp_zebra.h index 3281c47018..1c418dddef 100644 --- a/eigrpd/eigrp_zebra.h +++ b/eigrpd/eigrp_zebra.h @@ -33,8 +33,8 @@ extern void eigrp_zebra_init(void); -extern void eigrp_zebra_route_add(struct prefix_ipv4 *, struct list *); -extern void eigrp_zebra_route_delete(struct prefix_ipv4 *); +extern void eigrp_zebra_route_add(struct prefix *, struct list *); +extern void eigrp_zebra_route_delete(struct prefix *); extern int eigrp_redistribute_set(struct eigrp *, int, struct eigrp_metrics); extern int eigrp_redistribute_unset(struct eigrp *, int); extern int eigrp_is_type_redistributed(int); diff --git a/git-reindent-branch.py b/git-reindent-branch.py index b0dd8db6de..c207f5946f 100644 --- a/git-reindent-branch.py +++ b/git-reindent-branch.py @@ -11,14 +11,28 @@ def run(cmd): proc.wait() return rv +clangfmt = run(['git', 'show', 'master:.clang-format']) + argp = argparse.ArgumentParser(description = 'git whitespace-fixing tool') argp.add_argument('branch', metavar='BRANCH', type = str, nargs = '?', default = 'HEAD') args = argp.parse_args() branch = args.branch commit = run(['git', 'rev-list', '-n', '1', branch, '--']).strip() -beforeid = run(['git', 'rev-list', '-n', '1', 'reindent-master-before', '--']).strip() -afterid = run(['git', 'rev-list', '-n', '1', 'reindent-master-after', '--']).strip() + +# frr-3.1-dev = first commit that is on master but not on stable/3.0 +masterid = run(['git', 'rev-list', '-n', '1', 'frr-3.1-dev', '--']).strip() +masterbase = run(['git', 'merge-base', commit, masterid]).strip() + +if masterbase == masterid: + refbranch = 'master' +else: + refbranch = '3.0' + +sys.stderr.write('autodetected base: %s (can be 3.0 or master)\n' % refbranch) + +beforeid = run(['git', 'rev-list', '-n', '1', 'reindent-%s-before' % refbranch, '--']).strip() +afterid = run(['git', 'rev-list', '-n', '1', 'reindent-%s-after' % refbranch, '--']).strip() beforebase = run(['git', 'merge-base', commit, beforeid]).strip() afterbase = run(['git', 'merge-base', commit, afterid]).strip() @@ -28,10 +42,10 @@ if afterbase == afterid: sys.exit(1) if beforebase != beforeid: - sys.stderr.write('you need to rebase your branch onto the tag "reindent-master-before"\n') + sys.stderr.write('you need to rebase your branch onto the tag "reindent-%s-before"\n' % refbranch) sys.exit(1) -revs = run(['git', 'rev-list', 'reindent-master-before..%s' % commit]).strip().split('\n') +revs = run(['git', 'rev-list', 'reindent-%s-before..%s' % (refbranch, commit)]).strip().split('\n') revs.reverse() srcdir = os.getcwd() @@ -39,9 +53,12 @@ tmpdir = tempfile.mkdtemp('frrindent') os.chdir(tmpdir) sys.stderr.write('using temporary directory %s; %d revisions\n' % (tmpdir, len(revs))) -run(['git', 'clone', '-s', '-b', 'reindent-master-after', srcdir, 'repo']) +run(['git', 'clone', '-s', '-b', 'reindent-%s-after' % refbranch, srcdir, 'repo']) os.chdir('repo') +with open('.clang-format', 'w') as fd: + fd.write(clangfmt) + prev = beforeid for rev in revs: filestat = run(['git', 'diff', '-z', '--name-status', prev, rev]).rstrip('\0').split('\0') diff --git a/isisd/isis_bpf.c b/isisd/isis_bpf.c index 98f612f827..2c8b126088 100644 --- a/isisd/isis_bpf.c +++ b/isisd/isis_bpf.c @@ -48,14 +48,15 @@ extern struct zebra_privs_t isisd_privs; struct bpf_insn llcfilter[] = { - BPF_STMT(BPF_LD + BPF_B + BPF_ABS, - ETHER_HDR_LEN), /* check first byte */ + /* check first byte */ + BPF_STMT(BPF_LD + BPF_B + BPF_ABS, ETH_ALEN), BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, ISO_SAP, 0, 5), - BPF_STMT(BPF_LD + BPF_B + BPF_ABS, ETHER_HDR_LEN + 1), - BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, ISO_SAP, 0, - 3), /* check second byte */ - BPF_STMT(BPF_LD + BPF_B + BPF_ABS, ETHER_HDR_LEN + 2), - BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 0x03, 0, 1), /* check third byte */ + /* check second byte */ + BPF_STMT(BPF_LD + BPF_B + BPF_ABS, ETH_ALEN + 1), + BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, ISO_SAP, 0, 3), + /* check third byte */ + BPF_STMT(BPF_LD + BPF_B + BPF_ABS, ETH_ALEN + 2), + BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 0x03, 0, 1), BPF_STMT(BPF_RET + BPF_K, (u_int)-1), BPF_STMT(BPF_RET + BPF_K, 0)}; u_int readblen = 0; @@ -243,15 +244,14 @@ int isis_recv_pdu_bcast(struct isis_circuit *circuit, u_char *ssnpa) assert(bpf_hdr->bh_caplen == bpf_hdr->bh_datalen); - offset = bpf_hdr->bh_hdrlen + LLC_LEN + ETHER_HDR_LEN; + offset = bpf_hdr->bh_hdrlen + LLC_LEN + ETH_ALEN; /* then we lose the BPF, LLC and ethernet headers */ stream_write(circuit->rcv_stream, readbuff + offset, - bpf_hdr->bh_caplen - LLC_LEN - ETHER_HDR_LEN); + bpf_hdr->bh_caplen - LLC_LEN - ETH_ALEN); stream_set_getp(circuit->rcv_stream, 0); - memcpy(ssnpa, readbuff + bpf_hdr->bh_hdrlen + ETH_ALEN, - ETH_ALEN); + memcpy(ssnpa, readbuff + bpf_hdr->bh_hdrlen + ETH_ALEN, ETH_ALEN); if (ioctl(circuit->fd, BIOCFLUSH, &one) < 0) zlog_warn("Flushing failed: %s", safe_strerror(errno)); @@ -265,7 +265,7 @@ int isis_send_pdu_bcast(struct isis_circuit *circuit, int level) ssize_t written; size_t buflen; - buflen = stream_get_endp(circuit->snd_stream) + LLC_LEN + ETHER_HDR_LEN; + buflen = stream_get_endp(circuit->snd_stream) + LLC_LEN + ETH_ALEN; if (buflen > sizeof(sock_buff)) { zlog_warn( "isis_send_pdu_bcast: sock_buff size %zu is less than " @@ -291,12 +291,12 @@ int isis_send_pdu_bcast(struct isis_circuit *circuit, int level) /* * Then the LLC */ - sock_buff[ETHER_HDR_LEN] = ISO_SAP; - sock_buff[ETHER_HDR_LEN + 1] = ISO_SAP; - sock_buff[ETHER_HDR_LEN + 2] = 0x03; + sock_buff[ETH_ALEN] = ISO_SAP; + sock_buff[ETH_ALEN + 1] = ISO_SAP; + sock_buff[ETH_ALEN + 2] = 0x03; /* then we copy the data */ - memcpy(sock_buff + (LLC_LEN + ETHER_HDR_LEN), circuit->snd_stream->data, + memcpy(sock_buff + (LLC_LEN + ETH_ALEN), circuit->snd_stream->data, stream_get_endp(circuit->snd_stream)); /* now we can send this */ diff --git a/isisd/isis_vty.c b/isisd/isis_vty.c index 2a19465a01..17d8ad3c0b 100644 --- a/isisd/isis_vty.c +++ b/isisd/isis_vty.c @@ -181,7 +181,7 @@ DEFUN (no_isis_passive, if (if_is_loopback(circuit->interface)) { vty_out(vty, "Can't set no passive for loopback interface\n"); - return CMD_ERR_AMBIGUOUS; + return CMD_WARNING_CONFIG_FAILED; } isis_circuit_passive_set(circuit, 0); @@ -206,7 +206,7 @@ DEFUN (isis_circuit_type, is_type = string2circuit_t(argv[idx_level]->arg); if (!is_type) { vty_out(vty, "Unknown circuit-type \n"); - return CMD_ERR_AMBIGUOUS; + return CMD_WARNING_CONFIG_FAILED; } if (circuit->state == C_STATE_UP @@ -214,7 +214,7 @@ DEFUN (isis_circuit_type, && circuit->area->is_type != is_type) { vty_out(vty, "Invalid circuit level for area %s.\n", circuit->area->area_tag); - return CMD_ERR_AMBIGUOUS; + return CMD_WARNING_CONFIG_FAILED; } isis_circuit_is_type_set(circuit, is_type); @@ -262,7 +262,7 @@ DEFUN (isis_network, if (isis_circuit_circ_type_set(circuit, CIRCUIT_T_P2P)) { vty_out(vty, "isis network point-to-point is valid only on broadcast interfaces\n"); - return CMD_ERR_AMBIGUOUS; + return CMD_WARNING_CONFIG_FAILED; } return CMD_SUCCESS; @@ -283,7 +283,7 @@ DEFUN (no_isis_network, if (isis_circuit_circ_type_set(circuit, CIRCUIT_T_BROADCAST)) { vty_out(vty, "isis network point-to-point is valid only on broadcast interfaces\n"); - return CMD_ERR_AMBIGUOUS; + return CMD_WARNING_CONFIG_FAILED; } return CMD_SUCCESS; @@ -313,7 +313,7 @@ DEFUN (isis_passwd, argv[idx_word]->arg); if (rv) { vty_out(vty, "Too long circuit password (>254)\n"); - return CMD_ERR_AMBIGUOUS; + return CMD_WARNING_CONFIG_FAILED; } return CMD_SUCCESS; @@ -355,7 +355,7 @@ DEFUN (isis_priority, prio = atoi(argv[idx_number]->arg); if (prio < MIN_PRIORITY || prio > MAX_PRIORITY) { vty_out(vty, "Invalid priority %d - should be <0-127>\n", prio); - return CMD_ERR_AMBIGUOUS; + return CMD_WARNING_CONFIG_FAILED; } circuit->priority[0] = prio; @@ -400,7 +400,7 @@ DEFUN (isis_priority_l1, prio = atoi(argv[idx_number]->arg); if (prio < MIN_PRIORITY || prio > MAX_PRIORITY) { vty_out(vty, "Invalid priority %d - should be <0-127>\n", prio); - return CMD_ERR_AMBIGUOUS; + return CMD_WARNING_CONFIG_FAILED; } circuit->priority[0] = prio; @@ -444,7 +444,7 @@ DEFUN (isis_priority_l2, prio = atoi(argv[idx_number]->arg); if (prio < MIN_PRIORITY || prio > MAX_PRIORITY) { vty_out(vty, "Invalid priority %d - should be <0-127>\n", prio); - return CMD_ERR_AMBIGUOUS; + return CMD_WARNING_CONFIG_FAILED; } circuit->priority[1] = prio; @@ -494,7 +494,7 @@ DEFUN (isis_metric, "Invalid metric %d - should be <0-63> " "when narrow metric type enabled\n", met); - return CMD_ERR_AMBIGUOUS; + return CMD_WARNING_CONFIG_FAILED; } /* RFC4444 */ @@ -504,7 +504,7 @@ DEFUN (isis_metric, "Invalid metric %d - should be <0-16777215> " "when wide metric type enabled\n", met); - return CMD_ERR_AMBIGUOUS; + return CMD_WARNING_CONFIG_FAILED; } isis_circuit_metric_set(circuit, IS_LEVEL_1, met); @@ -554,7 +554,7 @@ DEFUN (isis_metric_l1, "Invalid metric %d - should be <0-63> " "when narrow metric type enabled\n", met); - return CMD_ERR_AMBIGUOUS; + return CMD_WARNING_CONFIG_FAILED; } /* RFC4444 */ @@ -564,7 +564,7 @@ DEFUN (isis_metric_l1, "Invalid metric %d - should be <0-16777215> " "when wide metric type enabled\n", met); - return CMD_ERR_AMBIGUOUS; + return CMD_WARNING_CONFIG_FAILED; } isis_circuit_metric_set(circuit, IS_LEVEL_1, met); @@ -613,7 +613,7 @@ DEFUN (isis_metric_l2, "Invalid metric %d - should be <0-63> " "when narrow metric type enabled\n", met); - return CMD_ERR_AMBIGUOUS; + return CMD_WARNING_CONFIG_FAILED; } /* RFC4444 */ @@ -623,7 +623,7 @@ DEFUN (isis_metric_l2, "Invalid metric %d - should be <0-16777215> " "when wide metric type enabled\n", met); - return CMD_ERR_AMBIGUOUS; + return CMD_WARNING_CONFIG_FAILED; } isis_circuit_metric_set(circuit, IS_LEVEL_2, met); @@ -667,7 +667,7 @@ DEFUN (isis_hello_interval, if (interval < MIN_HELLO_INTERVAL || interval > MAX_HELLO_INTERVAL) { vty_out(vty, "Invalid hello-interval %d - should be <1-600>\n", interval); - return CMD_ERR_AMBIGUOUS; + return CMD_WARNING_CONFIG_FAILED; } circuit->hello_interval[0] = (u_int16_t)interval; @@ -714,7 +714,7 @@ DEFUN (isis_hello_interval_l1, if (interval < MIN_HELLO_INTERVAL || interval > MAX_HELLO_INTERVAL) { vty_out(vty, "Invalid hello-interval %ld - should be <1-600>\n", interval); - return CMD_ERR_AMBIGUOUS; + return CMD_WARNING_CONFIG_FAILED; } circuit->hello_interval[0] = (u_int16_t)interval; @@ -760,7 +760,7 @@ DEFUN (isis_hello_interval_l2, if (interval < MIN_HELLO_INTERVAL || interval > MAX_HELLO_INTERVAL) { vty_out(vty, "Invalid hello-interval %ld - should be <1-600>\n", interval); - return CMD_ERR_AMBIGUOUS; + return CMD_WARNING_CONFIG_FAILED; } circuit->hello_interval[1] = (u_int16_t)interval; @@ -806,7 +806,7 @@ DEFUN (isis_hello_multiplier, vty_out(vty, "Invalid hello-multiplier %d - should be <2-100>\n", mult); - return CMD_ERR_AMBIGUOUS; + return CMD_WARNING_CONFIG_FAILED; } circuit->hello_multiplier[0] = (u_int16_t)mult; @@ -854,7 +854,7 @@ DEFUN (isis_hello_multiplier_l1, vty_out(vty, "Invalid hello-multiplier %d - should be <2-100>\n", mult); - return CMD_ERR_AMBIGUOUS; + return CMD_WARNING_CONFIG_FAILED; } circuit->hello_multiplier[0] = (u_int16_t)mult; @@ -901,7 +901,7 @@ DEFUN (isis_hello_multiplier_l2, vty_out(vty, "Invalid hello-multiplier %d - should be <2-100>\n", mult); - return CMD_ERR_AMBIGUOUS; + return CMD_WARNING_CONFIG_FAILED; } circuit->hello_multiplier[1] = (u_int16_t)mult; @@ -979,7 +979,7 @@ DEFUN (csnp_interval, if (interval < MIN_CSNP_INTERVAL || interval > MAX_CSNP_INTERVAL) { vty_out(vty, "Invalid csnp-interval %lu - should be <1-600>\n", interval); - return CMD_ERR_AMBIGUOUS; + return CMD_WARNING_CONFIG_FAILED; } circuit->csnp_interval[0] = (u_int16_t)interval; @@ -1026,7 +1026,7 @@ DEFUN (csnp_interval_l1, if (interval < MIN_CSNP_INTERVAL || interval > MAX_CSNP_INTERVAL) { vty_out(vty, "Invalid csnp-interval %lu - should be <1-600>\n", interval); - return CMD_ERR_AMBIGUOUS; + return CMD_WARNING_CONFIG_FAILED; } circuit->csnp_interval[0] = (u_int16_t)interval; @@ -1072,7 +1072,7 @@ DEFUN (csnp_interval_l2, if (interval < MIN_CSNP_INTERVAL || interval > MAX_CSNP_INTERVAL) { vty_out(vty, "Invalid csnp-interval %lu - should be <1-600>\n", interval); - return CMD_ERR_AMBIGUOUS; + return CMD_WARNING_CONFIG_FAILED; } circuit->csnp_interval[1] = (u_int16_t)interval; @@ -1117,7 +1117,7 @@ DEFUN (psnp_interval, if (interval < MIN_PSNP_INTERVAL || interval > MAX_PSNP_INTERVAL) { vty_out(vty, "Invalid psnp-interval %lu - should be <1-120>\n", interval); - return CMD_ERR_AMBIGUOUS; + return CMD_WARNING_CONFIG_FAILED; } circuit->psnp_interval[0] = (u_int16_t)interval; @@ -1164,7 +1164,7 @@ DEFUN (psnp_interval_l1, if (interval < MIN_PSNP_INTERVAL || interval > MAX_PSNP_INTERVAL) { vty_out(vty, "Invalid psnp-interval %lu - should be <1-120>\n", interval); - return CMD_ERR_AMBIGUOUS; + return CMD_WARNING_CONFIG_FAILED; } circuit->psnp_interval[0] = (u_int16_t)interval; @@ -1210,7 +1210,7 @@ DEFUN (psnp_interval_l2, if (interval < MIN_PSNP_INTERVAL || interval > MAX_PSNP_INTERVAL) { vty_out(vty, "Invalid psnp-interval %lu - should be <1-120>\n", interval); - return CMD_ERR_AMBIGUOUS; + return CMD_WARNING_CONFIG_FAILED; } circuit->psnp_interval[1] = (u_int16_t)interval; @@ -1253,12 +1253,12 @@ DEFUN (circuit_topology, if (circuit->area && circuit->area->oldmetric) { vty_out(vty, "Multi topology IS-IS can only be used with wide metrics\n"); - return CMD_ERR_AMBIGUOUS; + return CMD_WARNING_CONFIG_FAILED; } if (mtid == (uint16_t)-1) { vty_out(vty, "Don't know topology '%s'\n", arg); - return CMD_ERR_AMBIGUOUS; + return CMD_WARNING_CONFIG_FAILED; } return isis_circuit_mt_enabled_set(circuit, mtid, true); @@ -1281,12 +1281,12 @@ DEFUN (no_circuit_topology, if (circuit->area && circuit->area->oldmetric) { vty_out(vty, "Multi topology IS-IS can only be used with wide metrics\n"); - return CMD_ERR_AMBIGUOUS; + return CMD_WARNING_CONFIG_FAILED; } if (mtid == (uint16_t)-1) { vty_out(vty, "Don't know topology '%s'\n", arg); - return CMD_ERR_AMBIGUOUS; + return CMD_WARNING_CONFIG_FAILED; } return isis_circuit_mt_enabled_set(circuit, mtid, false); @@ -1298,11 +1298,11 @@ static int validate_metric_style_narrow(struct vty *vty, struct isis_area *area) struct listnode *node; if (!vty) - return CMD_ERR_AMBIGUOUS; + return CMD_WARNING_CONFIG_FAILED; if (!area) { vty_out(vty, "ISIS area is invalid\n"); - return CMD_ERR_AMBIGUOUS; + return CMD_WARNING_CONFIG_FAILED; } for (ALL_LIST_ELEMENTS_RO(area->circuit_list, node, circuit)) { @@ -1311,14 +1311,14 @@ static int validate_metric_style_narrow(struct vty *vty, struct isis_area *area) && (circuit->te_metric[0] > MAX_NARROW_LINK_METRIC)) { vty_out(vty, "ISIS circuit %s metric is invalid\n", circuit->interface->name); - return CMD_ERR_AMBIGUOUS; + return CMD_WARNING_CONFIG_FAILED; } if ((area->is_type & IS_LEVEL_2) && (circuit->is_type & IS_LEVEL_2) && (circuit->te_metric[1] > MAX_NARROW_LINK_METRIC)) { vty_out(vty, "ISIS circuit %s metric is invalid\n", circuit->interface->name); - return CMD_ERR_AMBIGUOUS; + return CMD_WARNING_CONFIG_FAILED; } } @@ -1345,7 +1345,7 @@ DEFUN (metric_style, if (area_is_mt(area)) { vty_out(vty, "Narrow metrics cannot be used while multi topology IS-IS is active\n"); - return CMD_ERR_AMBIGUOUS; + return CMD_WARNING_CONFIG_FAILED; } ret = validate_metric_style_narrow(vty, area); @@ -1373,7 +1373,7 @@ DEFUN (no_metric_style, if (area_is_mt(area)) { vty_out(vty, "Narrow metrics cannot be used while multi topology IS-IS is active\n"); - return CMD_ERR_AMBIGUOUS; + return CMD_WARNING_CONFIG_FAILED; } ret = validate_metric_style_narrow(vty, area); @@ -1470,7 +1470,7 @@ static int area_lsp_mtu_set(struct vty *vty, unsigned int lsp_mtu) "ISIS area contains circuit %s, which has a maximum PDU size of %zu.\n", circuit->interface->name, isis_circuit_pdu_size(circuit)); - return CMD_ERR_AMBIGUOUS; + return CMD_WARNING_CONFIG_FAILED; } } @@ -1568,7 +1568,7 @@ static int set_lsp_gen_interval(struct vty *vty, struct isis_area *area, "LSP gen interval %us must be less than " "the LSP refresh interval %us\n", interval, area->lsp_refresh[lvl - 1]); - return CMD_ERR_AMBIGUOUS; + return CMD_WARNING_CONFIG_FAILED; } } @@ -1817,7 +1817,7 @@ static int area_max_lsp_lifetime_set(struct vty *vty, int level, "the configured LSP gen interval %us\n", refresh_interval, area->lsp_gen_interval[lvl - 1]); - return CMD_ERR_AMBIGUOUS; + return CMD_WARNING_CONFIG_FAILED; } } } @@ -1890,14 +1890,14 @@ static int area_lsp_refresh_interval_set(struct vty *vty, int level, "LSP refresh interval %us must be greater than " "the configured LSP gen interval %us\n", interval, area->lsp_gen_interval[lvl - 1]); - return CMD_ERR_AMBIGUOUS; + return CMD_WARNING_CONFIG_FAILED; } if (interval > (area->max_lsp_lifetime[lvl - 1] - 300)) { vty_out(vty, "LSP refresh interval %us must be less than " "the configured LSP lifetime %us less 300\n", interval, area->max_lsp_lifetime[lvl - 1]); - return CMD_ERR_AMBIGUOUS; + return CMD_WARNING_CONFIG_FAILED; } } @@ -1961,7 +1961,7 @@ static int area_passwd_set(struct vty *vty, int level, if (passwd && strlen(passwd) > 254) { vty_out(vty, "Too long area password (>254)\n"); - return CMD_ERR_AMBIGUOUS; + return CMD_WARNING_CONFIG_FAILED; } type_set(area, level, passwd, snp_auth); diff --git a/isisd/isis_zebra.c b/isisd/isis_zebra.c index 8c6968f8ec..ed96bd31c2 100644 --- a/isisd/isis_zebra.c +++ b/isisd/isis_zebra.c @@ -245,260 +245,91 @@ static int isis_zebra_link_params(int command, struct zclient *zclient, return 0; } -static void isis_zebra_route_add_ipv4(struct prefix *prefix, - struct isis_route_info *route_info) +static void isis_zebra_route_add_route(struct prefix *prefix, + struct isis_route_info *route_info) { - u_char message; - u_int32_t flags; - int psize; - struct stream *stream; + struct zapi_route api; + struct zapi_nexthop *api_nh; struct isis_nexthop *nexthop; - struct listnode *node; - - if (CHECK_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED)) - return; - - if (vrf_bitmap_check(zclient->redist[AFI_IP][ZEBRA_ROUTE_ISIS], - VRF_DEFAULT)) { - message = 0; - flags = 0; - - SET_FLAG(message, ZAPI_MESSAGE_NEXTHOP); - SET_FLAG(message, ZAPI_MESSAGE_METRIC); -#if 0 - SET_FLAG (message, ZAPI_MESSAGE_DISTANCE); -#endif - - stream = zclient->obuf; - stream_reset(stream); - zclient_create_header(stream, ZEBRA_IPV4_ROUTE_ADD, - VRF_DEFAULT); - /* type */ - stream_putc(stream, ZEBRA_ROUTE_ISIS); - /* instance */ - stream_putw(stream, 0); - /* flags */ - stream_putl(stream, flags); - /* message */ - stream_putc(stream, message); - /* SAFI */ - stream_putw(stream, SAFI_UNICAST); - /* prefix information */ - psize = PSIZE(prefix->prefixlen); - stream_putc(stream, prefix->prefixlen); - stream_write(stream, (u_char *)&prefix->u.prefix4, psize); - - stream_putc(stream, listcount(route_info->nexthops)); - - /* Nexthop, ifindex, distance and metric information */ - for (ALL_LIST_ELEMENTS_RO(route_info->nexthops, node, - nexthop)) { - /* FIXME: can it be ? */ - if (nexthop->ip.s_addr != INADDR_ANY) { - stream_putc(stream, NEXTHOP_TYPE_IPV4_IFINDEX); - stream_put_in_addr(stream, &nexthop->ip); - stream_putl(stream, nexthop->ifindex); - } else { - stream_putc(stream, NEXTHOP_TYPE_IFINDEX); - stream_putl(stream, nexthop->ifindex); - } - } -#if 0 - if (CHECK_FLAG (message, ZAPI_MESSAGE_DISTANCE)) - stream_putc (stream, route_info->depth); -#endif - if (CHECK_FLAG(message, ZAPI_MESSAGE_METRIC)) - stream_putl(stream, route_info->cost); - - stream_putw_at(stream, 0, stream_get_endp(stream)); - zclient_send_message(zclient); - SET_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED); - UNSET_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_RESYNC); - } -} - -static void isis_zebra_route_del_ipv4(struct prefix *prefix, - struct isis_route_info *route_info) -{ - struct zapi_ipv4 api; - struct prefix_ipv4 prefix4; - - if (vrf_bitmap_check(zclient->redist[AFI_IP][ZEBRA_ROUTE_ISIS], - VRF_DEFAULT)) { - api.vrf_id = VRF_DEFAULT; - api.type = ZEBRA_ROUTE_ISIS; - api.instance = 0; - api.flags = 0; - api.message = 0; - api.safi = SAFI_UNICAST; - prefix4.family = AF_INET; - prefix4.prefixlen = prefix->prefixlen; - prefix4.prefix = prefix->u.prefix4; - zapi_ipv4_route(ZEBRA_IPV4_ROUTE_DELETE, zclient, &prefix4, - &api); - } - UNSET_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED); - - return; -} - -static void isis_zebra_route_add_ipv6(struct prefix *prefix, - struct isis_route_info *route_info) -{ - struct zapi_ipv6 api; - struct in6_addr **nexthop_list; - ifindex_t *ifindex_list; struct isis_nexthop6 *nexthop6; - int i, size; struct listnode *node; - struct prefix_ipv6 prefix6; + int count = 0; if (CHECK_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED)) return; + memset(&api, 0, sizeof(api)); api.vrf_id = VRF_DEFAULT; api.type = ZEBRA_ROUTE_ISIS; - api.instance = 0; - api.flags = 0; - api.message = 0; api.safi = SAFI_UNICAST; + api.prefix = *prefix; SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP); - SET_FLAG(api.message, ZAPI_MESSAGE_IFINDEX); SET_FLAG(api.message, ZAPI_MESSAGE_METRIC); api.metric = route_info->cost; #if 0 - SET_FLAG (api.message, ZAPI_MESSAGE_DISTANCE); - api.distance = route_info->depth; + SET_FLAG(api.message, ZAPI_MESSAGE_DISTANCE); + api.distance = route_info->depth; #endif - api.nexthop_num = listcount(route_info->nexthops6); - api.ifindex_num = listcount(route_info->nexthops6); - /* allocate memory for nexthop_list */ - size = sizeof(struct isis_nexthop6 *) - * listcount(route_info->nexthops6); - nexthop_list = (struct in6_addr **)XMALLOC(MTYPE_ISIS_TMP, size); - if (!nexthop_list) { - zlog_err("isis_zebra_add_route_ipv6: out of memory!"); - return; - } - - /* allocate memory for ifindex_list */ - size = sizeof(unsigned int) * listcount(route_info->nexthops6); - ifindex_list = (ifindex_t *)XMALLOC(MTYPE_ISIS_TMP, size); - if (!ifindex_list) { - zlog_err("isis_zebra_add_route_ipv6: out of memory!"); - XFREE(MTYPE_ISIS_TMP, nexthop_list); - return; - } - - /* for each nexthop */ - i = 0; - for (ALL_LIST_ELEMENTS_RO(route_info->nexthops6, node, nexthop6)) { - if (!IN6_IS_ADDR_LINKLOCAL(&nexthop6->ip6) - && !IN6_IS_ADDR_UNSPECIFIED(&nexthop6->ip6)) { - api.nexthop_num--; - api.ifindex_num--; - continue; + /* Nexthops */ + switch (prefix->family) { + case AF_INET: + for (ALL_LIST_ELEMENTS_RO(route_info->nexthops, node, + nexthop)) { + api_nh = &api.nexthops[count]; + /* FIXME: can it be ? */ + if (nexthop->ip.s_addr != INADDR_ANY) { + api_nh->type = NEXTHOP_TYPE_IPV4_IFINDEX; + api_nh->gate.ipv4 = nexthop->ip; + } else { + api_nh->type = NEXTHOP_TYPE_IFINDEX; + } + api_nh->ifindex = nexthop->ifindex; + count++; } + break; + case AF_INET6: + for (ALL_LIST_ELEMENTS_RO(route_info->nexthops6, node, + nexthop6)) { + if (!IN6_IS_ADDR_LINKLOCAL(&nexthop6->ip6) + && !IN6_IS_ADDR_UNSPECIFIED(&nexthop6->ip6)) { + continue; + } - nexthop_list[i] = &nexthop6->ip6; - ifindex_list[i] = nexthop6->ifindex; - i++; + api_nh = &api.nexthops[count]; + api_nh->gate.ipv6 = nexthop6->ip6; + api_nh->ifindex = nexthop6->ifindex; + api_nh->type = NEXTHOP_TYPE_IPV6_IFINDEX; + count++; + } + break; } + if (!count) + return; - api.nexthop = nexthop_list; - api.ifindex = ifindex_list; + api.nexthop_num = count; - if (api.nexthop_num && api.ifindex_num) { - prefix6.family = AF_INET6; - prefix6.prefixlen = prefix->prefixlen; - memcpy(&prefix6.prefix, &prefix->u.prefix6, - sizeof(struct in6_addr)); - zapi_ipv6_route(ZEBRA_IPV6_ROUTE_ADD, zclient, &prefix6, NULL, - &api); - SET_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED); - UNSET_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_RESYNC); - } - - XFREE(MTYPE_ISIS_TMP, nexthop_list); - XFREE(MTYPE_ISIS_TMP, ifindex_list); - - return; + zclient_route_send(ZEBRA_ROUTE_ADD, zclient, &api); + SET_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED); + UNSET_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_RESYNC); } -static void isis_zebra_route_del_ipv6(struct prefix *prefix, - struct isis_route_info *route_info) +static void isis_zebra_route_del_route(struct prefix *prefix, + struct isis_route_info *route_info) { - struct zapi_ipv6 api; - struct in6_addr **nexthop_list; - ifindex_t *ifindex_list; - struct isis_nexthop6 *nexthop6; - int i, size; - struct listnode *node; - struct prefix_ipv6 prefix6; + struct zapi_route api; if (!CHECK_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED)) return; + memset(&api, 0, sizeof(api)); api.vrf_id = VRF_DEFAULT; api.type = ZEBRA_ROUTE_ISIS; - api.instance = 0; - api.flags = 0; - api.message = 0; api.safi = SAFI_UNICAST; - SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP); - SET_FLAG(api.message, ZAPI_MESSAGE_IFINDEX); - api.nexthop_num = listcount(route_info->nexthops6); - api.ifindex_num = listcount(route_info->nexthops6); + api.prefix = *prefix; - /* allocate memory for nexthop_list */ - size = sizeof(struct isis_nexthop6 *) - * listcount(route_info->nexthops6); - nexthop_list = (struct in6_addr **)XMALLOC(MTYPE_ISIS_TMP, size); - if (!nexthop_list) { - zlog_err("isis_zebra_route_del_ipv6: out of memory!"); - return; - } - - /* allocate memory for ifindex_list */ - size = sizeof(unsigned int) * listcount(route_info->nexthops6); - ifindex_list = (ifindex_t *)XMALLOC(MTYPE_ISIS_TMP, size); - if (!ifindex_list) { - zlog_err("isis_zebra_route_del_ipv6: out of memory!"); - XFREE(MTYPE_ISIS_TMP, nexthop_list); - return; - } - - /* for each nexthop */ - i = 0; - for (ALL_LIST_ELEMENTS_RO(route_info->nexthops6, node, nexthop6)) { - if (!IN6_IS_ADDR_LINKLOCAL(&nexthop6->ip6) - && !IN6_IS_ADDR_UNSPECIFIED(&nexthop6->ip6)) { - api.nexthop_num--; - api.ifindex_num--; - continue; - } - - nexthop_list[i] = &nexthop6->ip6; - ifindex_list[i] = nexthop6->ifindex; - i++; - } - - api.nexthop = nexthop_list; - api.ifindex = ifindex_list; - - if (api.nexthop_num && api.ifindex_num) { - prefix6.family = AF_INET6; - prefix6.prefixlen = prefix->prefixlen; - memcpy(&prefix6.prefix, &prefix->u.prefix6, - sizeof(struct in6_addr)); - zapi_ipv6_route(ZEBRA_IPV6_ROUTE_DELETE, zclient, &prefix6, - NULL, &api); - UNSET_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED); - } - - XFREE(MTYPE_ISIS_TMP, nexthop_list); - XFREE(MTYPE_ISIS_TMP, ifindex_list); + zclient_route_send(ZEBRA_ROUTE_DELETE, zclient, &api); + UNSET_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED); } void isis_zebra_route_update(struct prefix *prefix, @@ -507,144 +338,38 @@ void isis_zebra_route_update(struct prefix *prefix, if (zclient->sock < 0) return; - if ((prefix->family == AF_INET - && !vrf_bitmap_check(zclient->redist[AFI_IP][ZEBRA_ROUTE_ISIS], - VRF_DEFAULT)) - || (prefix->family == AF_INET6 - && !vrf_bitmap_check(zclient->redist[AFI_IP6][ZEBRA_ROUTE_ISIS], - VRF_DEFAULT))) - return; - - if (CHECK_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ACTIVE)) { - if (prefix->family == AF_INET) - isis_zebra_route_add_ipv4(prefix, route_info); - else if (prefix->family == AF_INET6) - isis_zebra_route_add_ipv6(prefix, route_info); - } else { - if (prefix->family == AF_INET) - isis_zebra_route_del_ipv4(prefix, route_info); - else if (prefix->family == AF_INET6) - isis_zebra_route_del_ipv6(prefix, route_info); - } - return; -} - -static int isis_zebra_read_ipv4(int command, struct zclient *zclient, - zebra_size_t length, vrf_id_t vrf_id) -{ - struct stream *stream; - struct zapi_ipv4 api; - struct prefix_ipv4 p; - struct prefix *p_generic = (struct prefix *)&p; - - stream = zclient->ibuf; - memset(&api, 0, sizeof(api)); - memset(&p, 0, sizeof(struct prefix_ipv4)); - - api.type = stream_getc(stream); - api.instance = stream_getw(stream); - api.flags = stream_getl(stream); - api.message = stream_getc(stream); - - p.family = AF_INET; - p.prefixlen = MIN(IPV4_MAX_PREFIXLEN, stream_getc(stream)); - stream_get(&p.prefix, stream, PSIZE(p.prefixlen)); - - if (CHECK_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP)) { - api.nexthop_num = stream_getc(stream); - (void)stream_get_ipv4(stream); - } - if (CHECK_FLAG(api.message, ZAPI_MESSAGE_IFINDEX)) { - api.ifindex_num = stream_getc(stream); - stream_getl(stream); - } - if (CHECK_FLAG(api.message, ZAPI_MESSAGE_DISTANCE)) - api.distance = stream_getc(stream); - if (CHECK_FLAG(api.message, ZAPI_MESSAGE_METRIC)) - api.metric = stream_getl(stream); - - /* - * Avoid advertising a false default reachability. (A default - * route installed by IS-IS gets redistributed from zebra back - * into IS-IS causing us to start advertising default reachabity - * without this check) - */ - if (p.prefixlen == 0 && api.type == ZEBRA_ROUTE_ISIS) - command = ZEBRA_IPV4_ROUTE_DELETE; - - if (command == ZEBRA_REDISTRIBUTE_IPV4_ADD) - isis_redist_add(api.type, p_generic, api.distance, api.metric); + if (CHECK_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ACTIVE)) + isis_zebra_route_add_route(prefix, route_info); else - isis_redist_delete(api.type, p_generic); - - return 0; + isis_zebra_route_del_route(prefix, route_info); } -static int isis_zebra_read_ipv6(int command, struct zclient *zclient, - zebra_size_t length, vrf_id_t vrf_id) +static int isis_zebra_read(int command, struct zclient *zclient, + zebra_size_t length, vrf_id_t vrf_id) { - struct stream *stream; - struct zapi_ipv6 api; - struct prefix_ipv6 p; - struct prefix src_p; - struct prefix *p_generic = (struct prefix *)&p; - struct in6_addr nexthop; - unsigned long ifindex __attribute__((unused)); + struct zapi_route api; - stream = zclient->ibuf; - memset(&api, 0, sizeof(api)); - memset(&p, 0, sizeof(struct prefix_ipv6)); - memset(&nexthop, 0, sizeof(nexthop)); - ifindex = 0; + if (zapi_route_decode(zclient->ibuf, &api) < 0) + return -1; - api.type = stream_getc(stream); - api.instance = stream_getw(stream); - api.flags = stream_getl(stream); - api.message = stream_getc(stream); - - p.family = AF_INET6; - p.prefixlen = stream_getc(stream); - stream_get(&p.prefix, stream, PSIZE(p.prefixlen)); - - memset(&src_p, 0, sizeof(struct prefix)); - src_p.family = AF_INET6; - if (CHECK_FLAG(api.message, ZAPI_MESSAGE_SRCPFX)) { - src_p.prefixlen = stream_getc(stream); - stream_get(&src_p.u.prefix6, stream, PSIZE(src_p.prefixlen)); - } - - if (src_p.prefixlen) - /* we completely ignore srcdest routes for now. */ + /* we completely ignore srcdest routes for now. */ + if (CHECK_FLAG(api.message, ZAPI_MESSAGE_SRCPFX)) return 0; - if (CHECK_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP)) { - api.nexthop_num = stream_getc(stream); /* this is always 1 */ - stream_get(&nexthop, stream, sizeof(nexthop)); - } - if (CHECK_FLAG(api.message, ZAPI_MESSAGE_IFINDEX)) { - api.ifindex_num = stream_getc(stream); - ifindex = stream_getl(stream); - } - if (CHECK_FLAG(api.message, ZAPI_MESSAGE_DISTANCE)) - api.distance = stream_getc(stream); - if (CHECK_FLAG(api.message, ZAPI_MESSAGE_METRIC)) - api.metric = stream_getl(stream); - if (CHECK_FLAG(api.message, ZAPI_MESSAGE_TAG)) - api.tag = stream_getl(stream); - /* * Avoid advertising a false default reachability. (A default * route installed by IS-IS gets redistributed from zebra back * into IS-IS causing us to start advertising default reachabity * without this check) */ - if (p.prefixlen == 0 && api.type == ZEBRA_ROUTE_ISIS) - command = ZEBRA_IPV6_ROUTE_DELETE; + if (api.prefix.prefixlen == 0 && api.type == ZEBRA_ROUTE_ISIS) + command = ZEBRA_REDISTRIBUTE_ROUTE_DEL; - if (command == ZEBRA_REDISTRIBUTE_IPV6_ADD) - isis_redist_add(api.type, p_generic, api.distance, api.metric); + if (command == ZEBRA_REDISTRIBUTE_ROUTE_ADD) + isis_redist_add(api.type, &api.prefix, api.distance, + api.metric); else - isis_redist_delete(api.type, p_generic); + isis_redist_delete(api.type, &api.prefix); return 0; } @@ -692,10 +417,8 @@ void isis_zebra_init(struct thread_master *master) zclient->interface_address_add = isis_zebra_if_address_add; zclient->interface_address_delete = isis_zebra_if_address_del; zclient->interface_link_params = isis_zebra_link_params; - zclient->redistribute_route_ipv4_add = isis_zebra_read_ipv4; - zclient->redistribute_route_ipv4_del = isis_zebra_read_ipv4; - zclient->redistribute_route_ipv6_add = isis_zebra_read_ipv6; - zclient->redistribute_route_ipv6_del = isis_zebra_read_ipv6; + zclient->redistribute_route_add = isis_zebra_read; + zclient->redistribute_route_del = isis_zebra_read; return; } diff --git a/isisd/isisd.c b/isisd/isisd.c index dba34e8e35..3d39a1ed52 100644 --- a/isisd/isisd.c +++ b/isisd/isisd.c @@ -347,14 +347,14 @@ int area_net_title(struct vty *vty, const char *net_title) "area address must be at least 8..20 octets long (%d)\n", addr->addr_len); XFREE(MTYPE_ISIS_AREA_ADDR, addr); - return CMD_ERR_AMBIGUOUS; + return CMD_WARNING_CONFIG_FAILED; } if (addr->area_addr[addr->addr_len - 1] != 0) { vty_out(vty, "nsel byte (last byte) in area address must be 0\n"); XFREE(MTYPE_ISIS_AREA_ADDR, addr); - return CMD_ERR_AMBIGUOUS; + return CMD_WARNING_CONFIG_FAILED; } if (isis->sysid_set == 0) { @@ -374,7 +374,7 @@ int area_net_title(struct vty *vty, const char *net_title) vty_out(vty, "System ID must not change when defining additional area addresses\n"); XFREE(MTYPE_ISIS_AREA_ADDR, addr); - return CMD_ERR_AMBIGUOUS; + return CMD_WARNING_CONFIG_FAILED; } /* now we see that we don't already have this address */ @@ -419,7 +419,7 @@ int area_clear_net_title(struct vty *vty, const char *net_title) vty_out(vty, "Unsupported area address length %d, should be 8...20 \n", addr.addr_len); - return CMD_ERR_AMBIGUOUS; + return CMD_WARNING_CONFIG_FAILED; } memcpy(addr.area_addr, buff, (int)addr.addr_len); @@ -1260,8 +1260,8 @@ DEFUN (show_isis_spf_ietf, if (area->spf_timer[level - 1]) { struct timeval remain = thread_timer_remain( area->spf_timer[level - 1]); - vty_out(vty, "Pending, due in %ld msec\n", - remain.tv_sec * 1000 + vty_out(vty, "Pending, due in %lld msec\n", + (long long)remain.tv_sec * 1000 + remain.tv_usec / 1000); } else { vty_out(vty, "Not scheduled\n"); @@ -1405,7 +1405,7 @@ static int show_isis_database(struct vty *vty, const char *argv, int ui_level) (u_char)strtol((char *)number, NULL, 16); pos -= 4; if (strncmp(pos, ".", 1) != 0) - return CMD_ERR_AMBIGUOUS; + return CMD_WARNING; } if (strncmp(pos, ".", 1) == 0) { memcpy(number, ++pos, 2); @@ -1570,16 +1570,16 @@ DEFUN (isis_topology, if (area->oldmetric) { vty_out(vty, "Multi topology IS-IS can only be used with wide metrics\n"); - return CMD_ERR_AMBIGUOUS; + return CMD_WARNING_CONFIG_FAILED; } if (mtid == (uint16_t)-1) { vty_out(vty, "Don't know topology '%s'\n", arg); - return CMD_ERR_AMBIGUOUS; + return CMD_WARNING_CONFIG_FAILED; } if (mtid == ISIS_MT_IPV4_UNICAST) { vty_out(vty, "Cannot configure IPv4 unicast topology\n"); - return CMD_ERR_AMBIGUOUS; + return CMD_WARNING_CONFIG_FAILED; } area_set_mt_enabled(area, mtid, true); @@ -1603,16 +1603,16 @@ DEFUN (no_isis_topology, if (area->oldmetric) { vty_out(vty, "Multi topology IS-IS can only be used with wide metrics\n"); - return CMD_ERR_AMBIGUOUS; + return CMD_WARNING_CONFIG_FAILED; } if (mtid == (uint16_t)-1) { vty_out(vty, "Don't know topology '%s'\n", arg); - return CMD_ERR_AMBIGUOUS; + return CMD_WARNING_CONFIG_FAILED; } if (mtid == ISIS_MT_IPV4_UNICAST) { vty_out(vty, "Cannot configure IPv4 unicast topology\n"); - return CMD_ERR_AMBIGUOUS; + return CMD_WARNING_CONFIG_FAILED; } area_set_mt_enabled(area, mtid, false); diff --git a/ldpd/ldp_zebra.c b/ldpd/ldp_zebra.c index ecc7db8f2e..c50cc0fda2 100644 --- a/ldpd/ldp_zebra.c +++ b/ldpd/ldp_zebra.c @@ -396,19 +396,34 @@ static int ldp_zebra_read_route(int command, struct zclient *zclient, zebra_size_t length, vrf_id_t vrf_id) { - struct stream *s; - u_char type; - u_char message_flags; + struct zapi_route api; + struct zapi_nexthop *api_nh; struct kroute kr; - int nhnum = 0, nhlen; - size_t nhmark; - int add = 0; + int i, add = 0; + + if (zapi_route_decode(zclient->ibuf, &api) < 0) + return -1; + + /* we completely ignore srcdest routes for now. */ + if (CHECK_FLAG(api.message, ZAPI_MESSAGE_SRCPFX)) + return (0); memset(&kr, 0, sizeof(kr)); - s = zclient->ibuf; + kr.af = api.prefix.family; + switch (kr.af) { + case AF_INET: + kr.prefix.v4 = api.prefix.u.prefix4; + break; + case AF_INET6: + kr.prefix.v6 = api.prefix.u.prefix6; + break; + default: + break; + } + kr.prefixlen = api.prefix.prefixlen; + kr.priority = api.distance; - type = stream_getc(s); - switch (type) { + switch (api.type) { case ZEBRA_ROUTE_CONNECT: kr.flags |= F_CONNECTED; break; @@ -419,84 +434,38 @@ ldp_zebra_read_route(int command, struct zclient *zclient, zebra_size_t length, break; } - stream_getl(s); /* flags, unused */ - stream_getw(s); /* instance, unused */ - message_flags = stream_getc(s); - - switch (command) { - case ZEBRA_REDISTRIBUTE_IPV4_ADD: - case ZEBRA_REDISTRIBUTE_IPV4_DEL: - kr.af = AF_INET; - nhlen = sizeof(struct in_addr); - break; - case ZEBRA_REDISTRIBUTE_IPV6_ADD: - case ZEBRA_REDISTRIBUTE_IPV6_DEL: - kr.af = AF_INET6; - nhlen = sizeof(struct in6_addr); - break; - default: - fatalx("ldp_zebra_read_route: unknown command"); - } - kr.prefixlen = stream_getc(s); - stream_get(&kr.prefix, s, PSIZE(kr.prefixlen)); - if (bad_addr(kr.af, &kr.prefix) || (kr.af == AF_INET6 && IN6_IS_SCOPE_EMBED(&kr.prefix.v6))) return (0); - if (kr.af == AF_INET6 && - CHECK_FLAG(message_flags, ZAPI_MESSAGE_SRCPFX)) { - uint8_t src_prefixlen; - - src_prefixlen = stream_getc(s); - - /* we completely ignore srcdest routes for now. */ - if (src_prefixlen) - return (0); - } - - if (CHECK_FLAG(message_flags, ZAPI_MESSAGE_NEXTHOP)) { - nhnum = stream_getc(s); - nhmark = stream_get_getp(s); - stream_set_getp(s, nhmark + nhnum * (nhlen + 5)); - } - - if (CHECK_FLAG(message_flags, ZAPI_MESSAGE_DISTANCE)) - kr.priority = stream_getc(s); - if (CHECK_FLAG(message_flags, ZAPI_MESSAGE_METRIC)) - stream_getl(s); /* metric, not used */ - - if (CHECK_FLAG(message_flags, ZAPI_MESSAGE_NEXTHOP)) - stream_set_getp(s, nhmark); - - if (command == ZEBRA_REDISTRIBUTE_IPV4_ADD || - command == ZEBRA_REDISTRIBUTE_IPV6_ADD) + if (command == ZEBRA_REDISTRIBUTE_ROUTE_ADD) add = 1; - if (nhnum == 0) + if (api.nexthop_num == 0) debug_zebra_in("route %s %s/%d (%s)", (add) ? "add" : "delete", log_addr(kr.af, &kr.prefix), kr.prefixlen, - zebra_route_string(type)); + zebra_route_string(api.type)); /* loop through all the nexthops */ - for (; nhnum > 0; nhnum--) { + for (i = 0; i < api.nexthop_num; i++) { + api_nh = &api.nexthops[i]; + switch (kr.af) { case AF_INET: - kr.nexthop.v4.s_addr = stream_get_ipv4(s); + kr.nexthop.v4 = api_nh->gate.ipv4; break; case AF_INET6: - stream_get(&kr.nexthop.v6, s, sizeof(kr.nexthop.v6)); + kr.nexthop.v6 = api_nh->gate.ipv6; break; default: break; } - stream_getc(s); /* ifindex_num, unused. */ - kr.ifindex = stream_getl(s); + kr.ifindex = api_nh->ifindex;; debug_zebra_in("route %s %s/%d nexthop %s ifindex %u (%s)", (add) ? "add" : "delete", log_addr(kr.af, &kr.prefix), kr.prefixlen, log_addr(kr.af, &kr.nexthop), kr.ifindex, - zebra_route_string(type)); + zebra_route_string(api.type)); if (add) main_imsg_compose_lde(IMSG_NETWORK_ADD, 0, &kr, @@ -553,10 +522,8 @@ ldp_zebra_init(struct thread_master *master) zclient->interface_down = ldp_interface_status_change; zclient->interface_address_add = ldp_interface_address_add; zclient->interface_address_delete = ldp_interface_address_delete; - zclient->redistribute_route_ipv4_add = ldp_zebra_read_route; - zclient->redistribute_route_ipv4_del = ldp_zebra_read_route; - zclient->redistribute_route_ipv6_add = ldp_zebra_read_route; - zclient->redistribute_route_ipv6_del = ldp_zebra_read_route; + zclient->redistribute_route_add = ldp_zebra_read_route; + zclient->redistribute_route_del = ldp_zebra_read_route; zclient->pw_status_update = ldp_zebra_read_pw_status_update; } diff --git a/lib/command.c b/lib/command.c index 45b5593a3e..c86025a3bd 100644 --- a/lib/command.c +++ b/lib/command.c @@ -42,6 +42,7 @@ #include "command_graph.h" #include "qobj.h" #include "defaults.h" +#include "libfrr.h" DEFINE_MTYPE(LIB, HOST, "Host config") DEFINE_MTYPE(LIB, STRVEC, "String vector") @@ -359,21 +360,23 @@ void install_element(enum node_type ntype, struct cmd_element *cmd) return; } - cnode = vector_slot(cmdvec, ntype); + cnode = vector_lookup(cmdvec, ntype); if (cnode == NULL) { fprintf(stderr, - "Command node %d doesn't exist, please check it\n", - ntype); - fprintf(stderr, - "Have you called install_node before this install_element?\n"); + "%s[%s]:\n" + "\tnode %d (%s) does not exist.\n" + "\tplease call install_node() before install_element()\n", + cmd->name, cmd->string, ntype, node_names[ntype]); exit(EXIT_FAILURE); } if (hash_lookup(cnode->cmd_hash, cmd) != NULL) { fprintf(stderr, - "Multiple command installs to node %d of command:\n%s\n", - ntype, cmd->string); + "%s[%s]:\n" + "\tnode %d (%s) already has this command installed.\n" + "\tduplicate install_element call?\n", + cmd->name, cmd->string, ntype, node_names[ntype]); return; } @@ -406,21 +409,23 @@ void uninstall_element(enum node_type ntype, struct cmd_element *cmd) return; } - cnode = vector_slot(cmdvec, ntype); + cnode = vector_lookup(cmdvec, ntype); if (cnode == NULL) { fprintf(stderr, - "Command node %d doesn't exist, please check it\n", - ntype); - fprintf(stderr, - "Have you called install_node before this install_element?\n"); + "%s[%s]:\n" + "\tnode %d (%s) does not exist.\n" + "\tplease call install_node() before uninstall_element()\n", + cmd->name, cmd->string, ntype, node_names[ntype]); exit(EXIT_FAILURE); } if (hash_release(cnode->cmd_hash, cmd) == NULL) { fprintf(stderr, - "Trying to uninstall non-installed command (node %d):\n%s\n", - ntype, cmd->string); + "%s[%s]:\n" + "\tnode %d (%s) does not have this command installed.\n" + "\tduplicate uninstall_element call?\n", + cmd->name, cmd->string, ntype, node_names[ntype]); return; } @@ -555,6 +560,9 @@ static int config_write_host(struct vty *vty) else if (!host.motd) vty_out(vty, "no banner motd\n"); + if (debug_memstats_at_exit) + vty_out(vty, "!\ndebug memstats-at-exit\n"); + return 1; } @@ -2366,6 +2374,17 @@ DEFUN (no_config_log_timestamp_precision, return CMD_SUCCESS; } +DEFUN (debug_memstats, + debug_memstats_cmd, + "[no] debug memstats-at-exit", + NO_STR + DEBUG_STR + "Print memory type statistics at exit\n") +{ + debug_memstats_at_exit = !!strcmp(argv[0]->text, "no"); + return CMD_SUCCESS; +} + int cmd_banner_motd_file(const char *file) { int success = CMD_SUCCESS; @@ -2527,6 +2546,7 @@ void cmd_init(int terminal) /* Each node's basic commands. */ install_element(VIEW_NODE, &show_version_cmd); install_element(ENABLE_NODE, &show_startup_config_cmd); + install_element(ENABLE_NODE, &debug_memstats_cmd); if (terminal) { install_element(VIEW_NODE, &config_list_cmd); @@ -2560,6 +2580,7 @@ void cmd_init(int terminal) install_element(CONFIG_NODE, &hostname_cmd); install_element(CONFIG_NODE, &no_hostname_cmd); install_element(CONFIG_NODE, &frr_version_defaults_cmd); + install_element(CONFIG_NODE, &debug_memstats_cmd); if (terminal > 0) { install_element(CONFIG_NODE, &password_cmd); diff --git a/lib/command_match.c b/lib/command_match.c index f07448d716..ad3ec2492e 100644 --- a/lib/command_match.c +++ b/lib/command_match.c @@ -46,8 +46,9 @@ DEFINE_MTYPE_STATIC(LIB, CMD_MATCHSTACK, "Command Match Stack") static int add_nexthops(struct list *, struct graph_node *, struct graph_node **, size_t); -static struct list *command_match_r(struct graph_node *, vector, unsigned int, - struct graph_node **); +static enum matcher_rv command_match_r(struct graph_node *, vector, + unsigned int, struct graph_node **, + struct list **); static int score_precedence(enum cmd_token_type); @@ -80,14 +81,12 @@ static enum match_type match_variable(struct cmd_token *, const char *); static enum match_type match_mac(const char *, bool); -/* matching functions */ -static enum matcher_rv matcher_rv; - enum matcher_rv command_match(struct graph *cmdgraph, vector vline, struct list **argv, const struct cmd_element **el) { struct graph_node *stack[MAXDEPTH]; - matcher_rv = MATCHER_NO_MATCH; + enum matcher_rv status; + *argv = NULL; // prepend a dummy token to match that pesky start node vector vvline = vector_init(vline->alloced + 1); @@ -97,9 +96,8 @@ enum matcher_rv command_match(struct graph *cmdgraph, vector vline, vvline->active = vline->active + 1; struct graph_node *start = vector_slot(cmdgraph->nodes, 0); - if ((*argv = command_match_r(start, vvline, 0, - stack))) // successful match - { + status = command_match_r(start, vvline, 0, stack, argv); + if (status == MATCHER_OK) { // successful match struct listnode *head = listhead(*argv); struct listnode *tail = listtail(*argv); @@ -115,6 +113,9 @@ enum matcher_rv command_match(struct graph *cmdgraph, vector vline, // input, with each cmd_token->arg holding the corresponding // input assert(*el); + } else if (*argv) { + del_arglist(*argv); + *argv = NULL; } if (!*el) { @@ -129,7 +130,7 @@ enum matcher_rv command_match(struct graph *cmdgraph, vector vline, // free vector vector_free(vvline); - return matcher_rv; + return status; } /** @@ -183,11 +184,15 @@ enum matcher_rv command_match(struct graph *cmdgraph, vector vline, * * If no match was found, the return value is NULL. */ -static struct list *command_match_r(struct graph_node *start, vector vline, - unsigned int n, struct graph_node **stack) +static enum matcher_rv command_match_r(struct graph_node *start, vector vline, + unsigned int n, + struct graph_node **stack, + struct list **currbest) { assert(n < vector_active(vline)); + enum matcher_rv status = MATCHER_NO_MATCH; + // get the minimum match level that can count as a full match struct cmd_token *token = start->data; enum match_type minmatch = min_match_level(token->type); @@ -196,11 +201,11 @@ static struct list *command_match_r(struct graph_node *start, vector vline, * this disallows matching the same one more than once if there is a * circle in the graph (used for keyword arguments) */ if (n == MAXDEPTH) - return NULL; + return MATCHER_NO_MATCH; if (!token->allowrepeat) for (size_t s = 0; s < n; s++) if (stack[s] == start) - return NULL; + return MATCHER_NO_MATCH; // get the current operating input token char *input_token = vector_slot(vline, n); @@ -231,7 +236,7 @@ static struct list *command_match_r(struct graph_node *start, vector vline, // if we don't match this node, die if (match_token(token, input_token) < minmatch) - return NULL; + return MATCHER_NO_MATCH; stack[n] = start; @@ -244,86 +249,92 @@ static struct list *command_match_r(struct graph_node *start, vector vline, add_nexthops(next, start, NULL, 0); // determine the best match - int ambiguous = 0; - struct list *currbest = NULL; for (ALL_LIST_ELEMENTS_RO(next, ln, gn)) { // if we've matched all input we're looking for END_TKN if (n + 1 == vector_active(vline)) { struct cmd_token *tok = gn->data; if (tok->type == END_TKN) { - if (currbest) // there is more than one END_TKN - // in the follow set - { - ambiguous = 1; + // if more than one END_TKN in the follow set + if (*currbest) { + status = MATCHER_AMBIGUOUS; break; + } else { + status = MATCHER_OK; } - currbest = list_new(); + *currbest = list_new(); // node should have one child node with the // element struct graph_node *leaf = vector_slot(gn->to, 0); // last node in the list will hold the - // cmd_element; - // this is important because list_delete() - // expects - // that all nodes have the same data type, so - // when - // deleting this list the last node must be - // manually deleted + // cmd_element; this is important because + // list_delete() expects that all nodes have + // the same data type, so when deleting this + // list the last node must be manually deleted struct cmd_element *el = leaf->data; - listnode_add(currbest, el); - currbest->del = + listnode_add(*currbest, el); + (*currbest)->del = (void (*)(void *)) & cmd_token_del; // do not break immediately; continue walking - // through the follow set - // to ensure that there is exactly one END_TKN + // through the follow set to ensure that there + // is exactly one END_TKN } continue; } // else recurse on candidate child node - struct list *result = command_match_r(gn, vline, n + 1, stack); + struct list *result = NULL; + enum matcher_rv rstat = + command_match_r(gn, vline, n + 1, stack, &result); // save the best match - if (result && currbest) { + if (result && *currbest) { // pick the best of two matches struct list *newbest = - disambiguate(currbest, result, vline, n + 1); - // set ambiguity flag - ambiguous = - !newbest || (ambiguous && newbest == currbest); + disambiguate(*currbest, result, vline, n + 1); + + // current best and result are ambiguous + if (!newbest) + status = MATCHER_AMBIGUOUS; + // current best is still the best, but ambiguous + else if (newbest == *currbest + && status == MATCHER_AMBIGUOUS) + status = MATCHER_AMBIGUOUS; + // result is better, but also ambiguous + else if (newbest == result + && rstat == MATCHER_AMBIGUOUS) + status = MATCHER_AMBIGUOUS; + // one or the other is superior and not ambiguous + else + status = MATCHER_OK; + // delete the unnecessary result struct list *todelete = - ((newbest && newbest == result) ? currbest + ((newbest && newbest == result) ? *currbest : result); del_arglist(todelete); - currbest = newbest ? newbest : currbest; - } else if (result) - currbest = result; - } - - if (currbest) { - if (ambiguous) { - del_arglist(currbest); - currbest = NULL; - matcher_rv = MATCHER_AMBIGUOUS; - } else { - // copy token, set arg and prepend to currbest - struct cmd_token *token = start->data; - struct cmd_token *copy = cmd_token_dup(token); - copy->arg = XSTRDUP(MTYPE_CMD_ARG, input_token); - listnode_add_before(currbest, currbest->head, copy); - matcher_rv = MATCHER_OK; + *currbest = newbest ? newbest : *currbest; + } else if (result) { + status = rstat; + *currbest = result; + } else if (!*currbest) { + status = MAX(rstat, status); } - } else if (n + 1 == vector_active(vline) - && matcher_rv == MATCHER_NO_MATCH) - matcher_rv = MATCHER_INCOMPLETE; + } + if (*currbest) { + // copy token, set arg and prepend to currbest + struct cmd_token *token = start->data; + struct cmd_token *copy = cmd_token_dup(token); + copy->arg = XSTRDUP(MTYPE_CMD_ARG, input_token); + listnode_add_before(*currbest, (*currbest)->head, copy); + } else if (n + 1 == vector_active(vline) && status == MATCHER_NO_MATCH) + status = MATCHER_INCOMPLETE; // cleanup list_delete(next); - return currbest; + return status; } static void stack_del(void *val) @@ -432,12 +443,12 @@ enum matcher_rv command_complete(struct graph *graph, vector vline, * next = set of all nodes reachable from all nodes in `matched` */ - matcher_rv = idx == vector_active(vline) && next->count - ? MATCHER_OK - : MATCHER_NO_MATCH; + enum matcher_rv mrv = idx == vector_active(vline) && next->count + ? MATCHER_OK + : MATCHER_NO_MATCH; *completions = NULL; - if (!MATCHER_ERROR(matcher_rv)) { + if (!MATCHER_ERROR(mrv)) { // extract cmd_token into list *completions = list_new(); for (ALL_LIST_ELEMENTS_RO(next, node, gstack)) { @@ -448,7 +459,7 @@ enum matcher_rv command_complete(struct graph *graph, vector vline, list_delete(current); list_delete(next); - return matcher_rv; + return mrv; } /** diff --git a/lib/compiler.h b/lib/compiler.h new file mode 100644 index 0000000000..49a2f2a422 --- /dev/null +++ b/lib/compiler.h @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2015-2017 David Lamparter, for NetDEF, Inc. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _FRR_COMPILER_H +#define _FRR_COMPILER_H + +/* function attributes, use like + * void prototype(void) __attribute__((_CONSTRUCTOR(100))); + */ +#if defined(__clang__) +# if __clang_major__ > 3 || (__clang_major__ == 3 && __clang_minor__ >= 5) +# define _RET_NONNULL , returns_nonnull +# endif +# define _CONSTRUCTOR(x) constructor(x) +#elif defined(__GNUC__) +# if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 9) +# define _RET_NONNULL , returns_nonnull +# endif +# if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3) +# define _CONSTRUCTOR(x) constructor(x) +# define _DESTRUCTOR(x) destructor(x) +# define _ALLOC_SIZE(x) alloc_size(x) +# endif +#endif + +#ifdef __sun +/* Solaris doesn't do constructor priorities due to linker restrictions */ +# undef _CONSTRUCTOR +# undef _DESTRUCTOR +#endif + +/* fallback versions */ +#ifndef _RET_NONNULL +# define _RET_NONNULL +#endif +#ifndef _CONSTRUCTOR +# define _CONSTRUCTOR(x) constructor +#endif +#ifndef _DESTRUCTOR +# define _DESTRUCTOR(x) destructor +#endif +#ifndef _ALLOC_SIZE +# define _ALLOC_SIZE(x) +#endif + +/* + * for warnings on macros, put in the macro content like this: + * #define MACRO BLA CPP_WARN("MACRO has been deprecated") + */ +#define CPP_STR(X) #X + +#if defined(__ICC) +#define CPP_NOTICE(text) _Pragma(CPP_STR(message __FILE__ ": " text)) +#define CPP_WARN(text) CPP_NOTICE(text) + +#elif (defined(__GNUC__) \ + && (__GNUC__ >= 5 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8))) \ + || (defined(__clang__) \ + && (__clang_major__ >= 4 \ + || (__clang_major__ == 3 && __clang_minor__ >= 5))) +#define CPP_WARN(text) _Pragma(CPP_STR(GCC warning text)) +#define CPP_NOTICE(text) _Pragma(CPP_STR(message text)) + +#else +#define CPP_WARN(text) +#endif + +#endif /* _FRR_COMPILER_H */ diff --git a/lib/grammar_sandbox.c b/lib/grammar_sandbox.c index 96ecfa44d3..3c6396f347 100644 --- a/lib/grammar_sandbox.c +++ b/lib/grammar_sandbox.c @@ -404,7 +404,8 @@ DEFUN (grammar_findambig, nodegraph = cnode->cmdgraph; if (!nodegraph) continue; - vty_out(vty, "scanning node %d\n", scannode - 1); + vty_out(vty, "scanning node %d (%s)\n", + scannode - 1, node_names[scannode - 1]); } commands = cmd_graph_permutations(nodegraph); diff --git a/lib/libfrr.c b/lib/libfrr.c index 255f91ec71..9944fdd1e1 100644 --- a/lib/libfrr.c +++ b/lib/libfrr.c @@ -52,6 +52,8 @@ char frr_zclientpath[256]; static char pidfile_default[256]; static char vtypath_default[256]; +bool debug_memstats_at_exit = 0; + static char comb_optstr[256]; static struct option comb_lo[64]; static struct option *comb_next_lo = &comb_lo[0]; @@ -639,7 +641,10 @@ static void frr_daemon_wait(int fd) exit(0); /* child failed one way or another ... */ - if (WIFEXITED(exitstat)) + if (WIFEXITED(exitstat) && WEXITSTATUS(exitstat) == 0) + /* can happen in --terminal case if exit is fast enough */ + (void)0; + else if (WIFEXITED(exitstat)) fprintf(stderr, "%s failed to start, exited %d\n", di->name, WEXITSTATUS(exitstat)); else if (WIFSIGNALED(exitstat)) @@ -841,6 +846,10 @@ void frr_early_fini(void) void frr_fini(void) { + FILE *fp; + char filename[128]; + int have_leftovers; + hook_call(frr_fini); /* memory_init -> nothing needed */ @@ -851,4 +860,28 @@ void frr_fini(void) thread_master_free(master); closezlog(); /* frrmod_init -> nothing needed / hooks */ + + if (!debug_memstats_at_exit) + return; + + have_leftovers = log_memstats(stderr, di->name); + + /* in case we decide at runtime that we want exit-memstats for + * a daemon, but it has no stderr because it's daemonized + * (only do this if we actually have something to print though) + */ + if (!have_leftovers) + return; + + snprintf(filename, sizeof(filename), + "/tmp/frr-memstats-%s-%llu-%llu", + di->name, + (unsigned long long)getpid(), + (unsigned long long)time(NULL)); + + fp = fopen(filename, "w"); + if (fp) { + log_memstats(fp, di->name); + fclose(fp); + } } diff --git a/lib/libfrr.h b/lib/libfrr.h index 8a15d168a1..f7d69eecb3 100644 --- a/lib/libfrr.h +++ b/lib/libfrr.h @@ -121,4 +121,6 @@ extern const char frr_moduledir[]; extern char frr_protoname[]; extern char frr_protonameinst[]; +extern bool debug_memstats_at_exit; + #endif /* _ZEBRA_FRR_H */ diff --git a/lib/log.c b/lib/log.c index 5c89e7080e..ea2e804cda 100644 --- a/lib/log.c +++ b/lib/log.c @@ -701,7 +701,7 @@ void _zlog_assert_failed(const char *assertion, const char *file, assertion, file, line, (function ? function : "?")); zlog_backtrace(LOG_CRIT); zlog_thread_info(LOG_CRIT); - log_memstats_stderr("log"); + log_memstats(stderr, "log"); abort(); } @@ -867,6 +867,8 @@ static const struct zebra_desc_table command_types[] = { DESC_ENTRY(ZEBRA_INTERFACE_UP), DESC_ENTRY(ZEBRA_INTERFACE_DOWN), DESC_ENTRY(ZEBRA_INTERFACE_SET_MASTER), + DESC_ENTRY(ZEBRA_ROUTE_ADD), + DESC_ENTRY(ZEBRA_ROUTE_DELETE), DESC_ENTRY(ZEBRA_IPV4_ROUTE_ADD), DESC_ENTRY(ZEBRA_IPV4_ROUTE_DELETE), DESC_ENTRY(ZEBRA_IPV6_ROUTE_ADD), @@ -893,10 +895,8 @@ static const struct zebra_desc_table command_types[] = { DESC_ENTRY(ZEBRA_BFD_DEST_DEREGISTER), DESC_ENTRY(ZEBRA_BFD_DEST_UPDATE), DESC_ENTRY(ZEBRA_BFD_DEST_REPLAY), - DESC_ENTRY(ZEBRA_REDISTRIBUTE_IPV4_ADD), - DESC_ENTRY(ZEBRA_REDISTRIBUTE_IPV4_DEL), - DESC_ENTRY(ZEBRA_REDISTRIBUTE_IPV6_ADD), - DESC_ENTRY(ZEBRA_REDISTRIBUTE_IPV6_DEL), + DESC_ENTRY(ZEBRA_REDISTRIBUTE_ROUTE_ADD), + DESC_ENTRY(ZEBRA_REDISTRIBUTE_ROUTE_DEL), DESC_ENTRY(ZEBRA_VRF_UNREGISTER), DESC_ENTRY(ZEBRA_VRF_ADD), DESC_ENTRY(ZEBRA_VRF_DELETE), @@ -908,10 +908,6 @@ static const struct zebra_desc_table command_types[] = { DESC_ENTRY(ZEBRA_INTERFACE_LINK_PARAMS), DESC_ENTRY(ZEBRA_MPLS_LABELS_ADD), DESC_ENTRY(ZEBRA_MPLS_LABELS_DELETE), - DESC_ENTRY(ZEBRA_IPV4_NEXTHOP_ADD), - DESC_ENTRY(ZEBRA_IPV4_NEXTHOP_DELETE), - DESC_ENTRY(ZEBRA_IPV6_NEXTHOP_ADD), - DESC_ENTRY(ZEBRA_IPV6_NEXTHOP_DELETE), DESC_ENTRY(ZEBRA_IPMR_ROUTE_STATS), DESC_ENTRY(ZEBRA_LABEL_MANAGER_CONNECT), DESC_ENTRY(ZEBRA_GET_LABEL_CHUNK), diff --git a/lib/memory.c b/lib/memory.c index 0ccc204002..c684c7605c 100644 --- a/lib/memory.c +++ b/lib/memory.c @@ -104,6 +104,7 @@ int qmem_walk(qmem_walk_fn *func, void *arg) } struct exit_dump_args { + FILE *fp; const char *prefix; int error; }; @@ -113,7 +114,7 @@ static int qmem_exit_walker(void *arg, struct memgroup *mg, struct memtype *mt) struct exit_dump_args *eda = arg; if (!mt) { - fprintf(stderr, + fprintf(eda->fp, "%s: showing active allocations in " "memory group %s\n", eda->prefix, mg->name); @@ -122,15 +123,16 @@ static int qmem_exit_walker(void *arg, struct memgroup *mg, struct memtype *mt) char size[32]; eda->error++; snprintf(size, sizeof(size), "%10zu", mt->size); - fprintf(stderr, "%s: memstats: %-30s: %6zu * %s\n", + fprintf(eda->fp, "%s: memstats: %-30s: %6zu * %s\n", eda->prefix, mt->name, mt->n_alloc, mt->size == SIZE_VAR ? "(variably sized)" : size); } return 0; } -void log_memstats_stderr(const char *prefix) +int log_memstats(FILE *fp, const char *prefix) { - struct exit_dump_args eda = {.prefix = prefix, .error = 0}; + struct exit_dump_args eda = { .fp = fp, .prefix = prefix, .error = 0 }; qmem_walk(qmem_exit_walker, &eda); + return eda.error; } diff --git a/lib/memory.h b/lib/memory.h index d5facad583..6de370514a 100644 --- a/lib/memory.h +++ b/lib/memory.h @@ -18,7 +18,9 @@ #define _QUAGGA_MEMORY_H #include +#include #include +#include "compiler.h" #define array_size(ar) (sizeof(ar) / sizeof(ar[0])) @@ -36,41 +38,6 @@ struct memgroup { const char *name; }; -#if defined(__clang__) -#if __clang_major__ > 3 || (__clang_major__ == 3 && __clang_minor__ >= 5) -# define _RET_NONNULL , returns_nonnull -#endif -# define _CONSTRUCTOR(x) constructor(x) -#elif defined(__GNUC__) -#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 9) -# define _RET_NONNULL , returns_nonnull -#endif -#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3) -# define _CONSTRUCTOR(x) constructor(x) -# define _DESTRUCTOR(x) destructor(x) -# define _ALLOC_SIZE(x) alloc_size(x) -#endif -#endif - -#ifdef __sun -/* Solaris doesn't do constructor priorities due to linker restrictions */ -#undef _CONSTRUCTOR -#undef _DESTRUCTOR -#endif - -#ifndef _RET_NONNULL -# define _RET_NONNULL -#endif -#ifndef _CONSTRUCTOR -# define _CONSTRUCTOR(x) constructor -#endif -#ifndef _DESTRUCTOR -# define _DESTRUCTOR(x) destructor -#endif -#ifndef _ALLOC_SIZE -# define _ALLOC_SIZE(x) -#endif - /* macro usage: * * mydaemon.h @@ -194,7 +161,8 @@ static inline size_t mtype_stats_alloc(struct memtype *mt) * last value from qmem_walk_fn. */ typedef int qmem_walk_fn(void *arg, struct memgroup *mg, struct memtype *mt); extern int qmem_walk(qmem_walk_fn *func, void *arg); -extern void log_memstats_stderr(const char *); +extern int log_memstats(FILE *fp, const char *); +#define log_memstats_stderr(prefix) log_memstats(stderr, prefix) extern void memory_oom(size_t size, const char *name); diff --git a/lib/module.c b/lib/module.c index beef791093..b3ab91c4ea 100644 --- a/lib/module.c +++ b/lib/module.c @@ -42,8 +42,10 @@ static struct frrmod_info frrmod_default_info = { .description = "libfrr core module", }; union _frrmod_runtime_u frrmod_default = { - .r.info = &frrmod_default_info, - .r.finished_loading = 1, + .r = { + .info = &frrmod_default_info, + .finished_loading = 1, + }, }; // if defined(HAVE_SYS_WEAK_ALIAS_ATTRIBUTE) diff --git a/lib/mpls.h b/lib/mpls.h index 025770d479..bf98eecd81 100644 --- a/lib/mpls.h +++ b/lib/mpls.h @@ -44,6 +44,9 @@ #define MPLS_DEFAULT_MIN_SRGB_LABEL 16000 #define MPLS_DEFAULT_MAX_SRGB_LABEL 23999 +/* Maximum # labels that can be pushed. */ +#define MPLS_MAX_LABELS 16 + #define IS_MPLS_RESERVED_LABEL(label) \ (label >= MPLS_MIN_RESERVED_LABEL && label <= MPLS_MAX_RESERVED_LABEL) diff --git a/lib/plist.c b/lib/plist.c index b0cf42ca49..ebd628d724 100644 --- a/lib/plist.c +++ b/lib/plist.c @@ -122,6 +122,14 @@ const char *prefix_list_name(struct prefix_list *plist) return plist->name; } +afi_t prefix_list_afi(struct prefix_list *plist) +{ + if (plist->master == &prefix_master_ipv4 + || plist->master == &prefix_master_orf_v4) + return AFI_IP; + return AFI_IP6; +} + /* Lookup prefix_list from list of prefix_list by name. */ static struct prefix_list *prefix_list_lookup_do(afi_t afi, int orf, const char *name) diff --git a/lib/plist.h b/lib/plist.h index 73d8da509a..3eba3046ae 100644 --- a/lib/plist.h +++ b/lib/plist.h @@ -48,6 +48,7 @@ extern void prefix_list_add_hook(void (*func)(struct prefix_list *)); extern void prefix_list_delete_hook(void (*func)(struct prefix_list *)); extern const char *prefix_list_name(struct prefix_list *); +extern afi_t prefix_list_afi(struct prefix_list *); extern struct prefix_list *prefix_list_lookup(afi_t, const char *); extern enum prefix_list_type prefix_list_apply(struct prefix_list *, void *); diff --git a/lib/prefix.c b/lib/prefix.c index 2f61eb6e8b..10f77bda87 100644 --- a/lib/prefix.c +++ b/lib/prefix.c @@ -1263,5 +1263,6 @@ unsigned prefix_hash_key(void *pp) * padding and unused prefix bytes. */ memset(©, 0, sizeof(copy)); prefix_copy(©, (struct prefix *)pp); - return jhash(©, sizeof(copy), 0x55aa5a5a); + return jhash(©, offsetof(struct prefix, u.prefix) + + PSIZE(copy.prefixlen), 0x55aa5a5a); } diff --git a/lib/prefix.h b/lib/prefix.h index bc4abb492a..a27f46ba0a 100644 --- a/lib/prefix.h +++ b/lib/prefix.h @@ -33,28 +33,13 @@ #endif #include "sockunion.h" #include "ipaddr.h" +#include "compiler.h" #ifndef ETH_ALEN #define ETH_ALEN 6 #endif /* for compatibility */ -#if defined(__ICC) -#define CPP_WARN_STR(X) #X -#define CPP_WARN(text) _Pragma(CPP_WARN_STR(message __FILE__ ": " text)) - -#elif (defined(__GNUC__) \ - && (__GNUC__ >= 5 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8))) \ - || (defined(__clang__) \ - && (__clang_major__ >= 4 \ - || (__clang_major__ == 3 && __clang_minor__ >= 5))) -#define CPP_WARN_STR(X) #X -#define CPP_WARN(text) _Pragma(CPP_WARN_STR(GCC warning text)) - -#else -#define CPP_WARN(text) -#endif - #ifdef ETHER_ADDR_LEN #undef ETHER_ADDR_LEN #endif @@ -140,7 +125,7 @@ struct prefix { struct in_addr adv_router; } lp; struct ethaddr prefix_eth; /* AF_ETHERNET */ - u_char val[8]; + u_char val[16]; uintptr_t ptr; struct evpn_addr prefix_evpn; /* AF_EVPN */ } u __attribute__((aligned(8))); diff --git a/lib/sigevent.c b/lib/sigevent.c index 2a04fa23cb..d55f368dfb 100644 --- a/lib/sigevent.c +++ b/lib/sigevent.c @@ -245,7 +245,7 @@ core_handler(int signo #endif ); /* dump memory stats on core */ - log_memstats_stderr("core_handler"); + log_memstats(stderr, "core_handler"); abort(); } diff --git a/lib/spf_backoff.c b/lib/spf_backoff.c index d075e70d4e..92b7620eda 100644 --- a/lib/spf_backoff.c +++ b/lib/spf_backoff.c @@ -226,8 +226,9 @@ void spf_backoff_show(struct spf_backoff *backoff, struct vty *vty, if (backoff->t_holddown) { struct timeval remain = thread_timer_remain(backoff->t_holddown); - vty_out(vty, "%s Still runs for %ld msec\n", - prefix, remain.tv_sec * 1000 + remain.tv_usec / 1000); + vty_out(vty, "%s Still runs for %lld msec\n", + prefix, (long long)remain.tv_sec * 1000 + + remain.tv_usec / 1000); } else { vty_out(vty, "%s Inactive\n", prefix); } @@ -237,8 +238,9 @@ void spf_backoff_show(struct spf_backoff *backoff, struct vty *vty, if (backoff->t_timetolearn) { struct timeval remain = thread_timer_remain(backoff->t_timetolearn); - vty_out(vty, "%s Still runs for %ld msec\n", - prefix, remain.tv_sec * 1000 + remain.tv_usec / 1000); + vty_out(vty, "%s Still runs for %lld msec\n", + prefix, (long long)remain.tv_sec * 1000 + + remain.tv_usec / 1000); } else { vty_out(vty, "%s Inactive\n", prefix); } diff --git a/lib/subdir.am b/lib/subdir.am index 8545184228..d6349ba22d 100644 --- a/lib/subdir.am +++ b/lib/subdir.am @@ -85,6 +85,7 @@ pkginclude_HEADERS += \ lib/command.h \ lib/command_graph.h \ lib/command_match.h \ + lib/compiler.h \ lib/csv.h \ lib/distribute.h \ lib/event_counter.h \ diff --git a/lib/table.h b/lib/table.h index ece40d86b3..9637fec149 100644 --- a/lib/table.h +++ b/lib/table.h @@ -227,7 +227,7 @@ extern void route_table_iter_cleanup(route_table_iter_t *iter); /* Lock node. */ static inline struct route_node *route_lock_node(struct route_node *node) { - node->lock++; + (*(unsigned *)&node->lock)++; return node; } @@ -235,7 +235,7 @@ static inline struct route_node *route_lock_node(struct route_node *node) static inline void route_unlock_node(struct route_node *node) { assert(node->lock > 0); - node->lock--; + (*(unsigned *)&node->lock)--; if (node->lock == 0) route_node_delete(node); diff --git a/lib/termtable.c b/lib/termtable.c index f7aec43118..ba85962cc9 100644 --- a/lib/termtable.c +++ b/lib/termtable.c @@ -31,48 +31,60 @@ struct ttable_style ttable_styles[] = { .corner = '+', .rownums_on = false, .indent = 1, - .border.top = '-', - .border.bottom = '-', - .border.left = '|', - .border.right = '|', - .border.top_on = true, - .border.bottom_on = true, - .border.left_on = true, - .border.right_on = true, - .cell.lpad = 1, - .cell.rpad = 1, - .cell.align = LEFT, - .cell.border.bottom = '-', - .cell.border.bottom_on = true, - .cell.border.top = '-', - .cell.border.top_on = false, - .cell.border.right = '|', - .cell.border.right_on = true, - .cell.border.left = '|', - .cell.border.left_on = false, + .border = { + .top = '-', + .bottom = '-', + .left = '|', + .right = '|', + .top_on = true, + .bottom_on = true, + .left_on = true, + .right_on = true, + }, + .cell = { + .lpad = 1, + .rpad = 1, + .align = LEFT, + .border = { + .bottom = '-', + .bottom_on = true, + .top = '-', + .top_on = false, + .right = '|', + .right_on = true, + .left = '|', + .left_on = false, + }, + }, }, { // blank, suitable for plaintext alignment .corner = ' ', .rownums_on = false, .indent = 1, - .border.top = ' ', - .border.bottom = ' ', - .border.left = ' ', - .border.right = ' ', - .border.top_on = false, - .border.bottom_on = false, - .border.left_on = false, - .border.right_on = false, - .cell.lpad = 0, - .cell.rpad = 3, - .cell.align = LEFT, - .cell.border.bottom = ' ', - .cell.border.bottom_on = false, - .cell.border.top = ' ', - .cell.border.top_on = false, - .cell.border.right = ' ', - .cell.border.right_on = false, - .cell.border.left = ' ', - .cell.border.left_on = false, + .border = { + .top = ' ', + .bottom = ' ', + .left = ' ', + .right = ' ', + .top_on = false, + .bottom_on = false, + .left_on = false, + .right_on = false, + }, + .cell = { + .lpad = 0, + .rpad = 3, + .align = LEFT, + .border = { + .bottom = ' ', + .bottom_on = false, + .top = ' ', + .top_on = false, + .right = ' ', + .right_on = false, + .left = ' ', + .left_on = false, + }, + } } }; /* clang-format on */ diff --git a/lib/vty.h b/lib/vty.h index dcb8da225d..9acd62af3c 100644 --- a/lib/vty.h +++ b/lib/vty.h @@ -25,6 +25,7 @@ #include "log.h" #include "sockunion.h" #include "qobj.h" +#include "compiler.h" #define VTY_BUFSIZ 4096 #define VTY_MAXHIST 20 @@ -182,23 +183,11 @@ struct vty_arg { /* Integrated configuration file. */ #define INTEGRATE_DEFAULT_CONFIG "frr.conf" -/* for compatibility */ -#if defined(__ICC) -#define CPP_WARN_STR(X) #X -#define CPP_WARN(text) _Pragma(CPP_WARN_STR(message __FILE__ ": " text)) - -#elif (defined(__GNUC__) \ - && (__GNUC__ >= 5 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8))) \ - || (defined(__clang__) \ - && (__clang_major__ >= 4 \ - || (__clang_major__ == 3 && __clang_minor__ >= 5))) -#define CPP_WARN_STR(X) #X -#define CPP_WARN(text) _Pragma(CPP_WARN_STR(GCC warning text)) - -#else -#define CPP_WARN(text) +#if CONFDATE > 20180401 +CPP_NOTICE("It's probably time to remove VTY_NEWLINE compatibility foo.") #endif +/* for compatibility */ #define VNL "\n" CPP_WARN("VNL has been replaced with \\n.") #define VTYNL "\n" CPP_WARN("VTYNL has been replaced with \\n.") #define VTY_NEWLINE "\n" CPP_WARN("VTY_NEWLINE has been replaced with \\n.") diff --git a/lib/zclient.c b/lib/zclient.c index 24cb699196..72fa2679b3 100644 --- a/lib/zclient.c +++ b/lib/zclient.c @@ -352,10 +352,6 @@ void zclient_send_reg_requests(struct zclient *zclient, vrf_id_t vrf_id) int i; afi_t afi; - /* zclient is disabled. */ - if (!zclient->enable) - return; - /* If not connected to the zebra yet. */ if (zclient->sock < 0) return; @@ -418,10 +414,6 @@ void zclient_send_dereg_requests(struct zclient *zclient, vrf_id_t vrf_id) int i; afi_t afi; - /* zclient is disabled. */ - if (!zclient->enable) - return; - /* If not connected to the zebra yet. */ if (zclient->sock < 0) return; @@ -485,10 +477,6 @@ void zclient_send_interface_radv_req(struct zclient *zclient, vrf_id_t vrf_id, { struct stream *s; - /* zclient is disabled. */ - if (!zclient->enable) - return; - /* If not connected to the zebra yet. */ if (zclient->sock < 0) return; @@ -516,10 +504,6 @@ int zclient_start(struct zclient *zclient) if (zclient_debug) zlog_info("zclient_start is called"); - /* zclient is disabled. */ - if (!zclient->enable) - return 0; - /* If already connected to the zebra. */ if (zclient->sock >= 0) return 0; @@ -564,9 +548,6 @@ void zclient_init(struct zclient *zclient, int redist_default, u_short instance) { int afi, i; - /* Enable zebra client connection by default. */ - zclient->enable = 1; - /* Set -1 to the default socket value. */ zclient->sock = -1; @@ -911,24 +892,23 @@ int zapi_ipv6_route(u_char cmd, struct zclient *zclient, struct prefix_ipv6 *p, return zclient_send_message(zclient); } -int zapi_route(u_char cmd, struct zclient *zclient, struct prefix *p, - struct prefix_ipv6 *src_p, struct zapi_route *api) +int zclient_route_send(u_char cmd, struct zclient *zclient, + struct zapi_route *api) { + if (zapi_route_encode(cmd, zclient->obuf, api) < 0) + return -1; + return zclient_send_message(zclient); +} + +int zapi_route_encode(u_char cmd, struct stream *s, struct zapi_route *api) +{ + struct zapi_nexthop *api_nh; int i; int psize; - struct stream *s; - /* either we have !SRCPFX && src_p == NULL, or SRCPFX && src_p != NULL - */ - assert(!(api->message & ZAPI_MESSAGE_SRCPFX) == !src_p); - - /* Reset stream. */ - s = zclient->obuf; stream_reset(s); - zclient_create_header(s, cmd, api->vrf_id); - /* Put type and nexthop. */ stream_putc(s, api->type); stream_putw(s, api->instance); stream_putl(s, api->flags); @@ -936,72 +916,84 @@ int zapi_route(u_char cmd, struct zclient *zclient, struct prefix *p, stream_putw(s, api->safi); /* Put prefix information. */ - psize = PSIZE(p->prefixlen); - stream_putc(s, p->prefixlen); - stream_write(s, (u_char *)&p->u.prefix, psize); + stream_putc(s, api->prefix.family); + psize = PSIZE(api->prefix.prefixlen); + stream_putc(s, api->prefix.prefixlen); + stream_write(s, (u_char *)&api->prefix.u.prefix, psize); if (CHECK_FLAG(api->message, ZAPI_MESSAGE_SRCPFX)) { - psize = PSIZE(src_p->prefixlen); - stream_putc(s, src_p->prefixlen); - stream_write(s, (u_char *)&src_p->prefix, psize); + psize = PSIZE(api->src_prefix.prefixlen); + stream_putc(s, api->src_prefix.prefixlen); + stream_write(s, (u_char *)&api->src_prefix.prefix, psize); } - /* Nexthop, ifindex, distance and metric information. */ + /* Nexthops. */ if (CHECK_FLAG(api->message, ZAPI_MESSAGE_NEXTHOP)) { - stream_putc(s, api->nexthop_num); + /* limit the number of nexthops if necessary */ + if (api->nexthop_num > MULTIPATH_NUM) { + char buf[PREFIX2STR_BUFFER]; + + prefix2str(&api->prefix, buf, sizeof(buf)); + zlog_warn( + "%s: prefix %s: encoding %u nexthops out of %u", + __func__, buf, MULTIPATH_NUM, api->nexthop_num); + api->nexthop_num = MULTIPATH_NUM; + } + + stream_putw(s, api->nexthop_num); for (i = 0; i < api->nexthop_num; i++) { - stream_putc(s, api->nexthop[i]->type); - switch (api->nexthop[i]->type) { + api_nh = &api->nexthops[i]; + + stream_putc(s, api_nh->type); + switch (api_nh->type) { case NEXTHOP_TYPE_BLACKHOLE: break; case NEXTHOP_TYPE_IPV4: - stream_put_in_addr(s, - &api->nexthop[i]->gate.ipv4); - - /* For labeled-unicast, each nexthop is followed - * by label. */ - if (CHECK_FLAG(api->message, - ZAPI_MESSAGE_LABEL)) - stream_putl( - s, - api->nexthop[i] - ->nh_label->label[0]); + stream_put_in_addr(s, &api_nh->gate.ipv4); break; case NEXTHOP_TYPE_IPV4_IFINDEX: - stream_put_in_addr(s, - &api->nexthop[i]->gate.ipv4); - stream_putl(s, api->nexthop[i]->ifindex); + stream_put_in_addr(s, &api_nh->gate.ipv4); + stream_putl(s, api_nh->ifindex); break; case NEXTHOP_TYPE_IFINDEX: - stream_putl(s, api->nexthop[i]->ifindex); + stream_putl(s, api_nh->ifindex); break; case NEXTHOP_TYPE_IPV6: - stream_write( - s, - (u_char *)&api->nexthop[i]->gate.ipv6, - 16); - - /* For labeled-unicast, each nexthop is followed - * by label. */ - if (CHECK_FLAG(api->message, - ZAPI_MESSAGE_LABEL)) - stream_putl( - s, - api->nexthop[i] - ->nh_label->label[0]); + stream_write(s, (u_char *)&api_nh->gate.ipv6, + 16); break; case NEXTHOP_TYPE_IPV6_IFINDEX: - stream_write( - s, - (u_char *)&api->nexthop[i]->gate.ipv6, - 16); - stream_putl(s, api->nexthop[i]->ifindex); + stream_write(s, (u_char *)&api_nh->gate.ipv6, + 16); + stream_putl(s, api_nh->ifindex); break; } + + /* MPLS labels for BGP-LU or Segment Routing */ + if (CHECK_FLAG(api->message, ZAPI_MESSAGE_LABEL)) { + if (api_nh->label_num > MPLS_MAX_LABELS) { + char buf[PREFIX2STR_BUFFER]; + prefix2str(&api->prefix, buf, + sizeof(buf)); + zlog_err( + "%s: prefix %s: can't encode " + "%u labels (maximum is %u)", + __func__, buf, + api_nh->label_num, + MPLS_MAX_LABELS); + return -1; + } + + stream_putc(s, api_nh->label_num); + stream_put(s, &api_nh->labels[0], + api_nh->label_num + * sizeof(mpls_label_t)); + } } } + /* Attributes. */ if (CHECK_FLAG(api->message, ZAPI_MESSAGE_DISTANCE)) stream_putc(s, api->distance); if (CHECK_FLAG(api->message, ZAPI_MESSAGE_METRIC)) @@ -1014,7 +1006,110 @@ int zapi_route(u_char cmd, struct zclient *zclient, struct prefix *p, /* Put length at the first point of the stream. */ stream_putw_at(s, 0, stream_get_endp(s)); - return zclient_send_message(zclient); + return 0; +} + +int zapi_route_decode(struct stream *s, struct zapi_route *api) +{ + struct zapi_nexthop *api_nh; + int i; + + memset(api, 0, sizeof(*api)); + + /* Type, flags, message. */ + api->type = stream_getc(s); + api->instance = stream_getw(s); + api->flags = stream_getl(s); + api->message = stream_getc(s); + api->safi = stream_getw(s); + + /* Prefix. */ + api->prefix.family = stream_getc(s); + switch (api->prefix.family) { + case AF_INET: + api->prefix.prefixlen = MIN(IPV4_MAX_PREFIXLEN, stream_getc(s)); + break; + case AF_INET6: + api->prefix.prefixlen = MIN(IPV6_MAX_PREFIXLEN, stream_getc(s)); + break; + } + stream_get(&api->prefix.u.prefix, s, PSIZE(api->prefix.prefixlen)); + if (CHECK_FLAG(api->message, ZAPI_MESSAGE_SRCPFX)) { + api->src_prefix.family = AF_INET6; + api->src_prefix.prefixlen = stream_getc(s); + stream_get(&api->src_prefix.prefix, s, + PSIZE(api->src_prefix.prefixlen)); + + if (api->prefix.family != AF_INET6 + || api->src_prefix.prefixlen == 0) + UNSET_FLAG(api->message, ZAPI_MESSAGE_SRCPFX); + } + + /* Nexthops. */ + if (CHECK_FLAG(api->message, ZAPI_MESSAGE_NEXTHOP)) { + api->nexthop_num = stream_getw(s); + if (api->nexthop_num > MULTIPATH_NUM) { + zlog_warn("%s: invalid number of nexthops (%u)", + __func__, api->nexthop_num); + return -1; + } + + for (i = 0; i < api->nexthop_num; i++) { + api_nh = &api->nexthops[i]; + + api_nh->type = stream_getc(s); + switch (api_nh->type) { + case NEXTHOP_TYPE_BLACKHOLE: + break; + case NEXTHOP_TYPE_IPV4: + api_nh->gate.ipv4.s_addr = stream_get_ipv4(s); + break; + case NEXTHOP_TYPE_IPV4_IFINDEX: + api_nh->gate.ipv4.s_addr = stream_get_ipv4(s); + api_nh->ifindex = stream_getl(s); + break; + case NEXTHOP_TYPE_IFINDEX: + api_nh->ifindex = stream_getl(s); + break; + case NEXTHOP_TYPE_IPV6: + stream_get(&api_nh->gate.ipv6, s, 16); + break; + case NEXTHOP_TYPE_IPV6_IFINDEX: + stream_get(&api_nh->gate.ipv6, s, 16); + api_nh->ifindex = stream_getl(s); + break; + } + + /* MPLS labels for BGP-LU or Segment Routing */ + if (CHECK_FLAG(api->message, ZAPI_MESSAGE_LABEL)) { + api_nh->label_num = stream_getc(s); + + if (api_nh->label_num > MPLS_MAX_LABELS) { + zlog_warn( + "%s: invalid number of MPLS " + "labels (%u)", + __func__, api_nh->label_num); + return -1; + } + + stream_get(&api_nh->labels[0], s, + api_nh->label_num + * sizeof(mpls_label_t)); + } + } + } + + /* Attributes. */ + if (CHECK_FLAG(api->message, ZAPI_MESSAGE_DISTANCE)) + api->distance = stream_getc(s); + if (CHECK_FLAG(api->message, ZAPI_MESSAGE_METRIC)) + api->metric = stream_getl(s); + if (CHECK_FLAG(api->message, ZAPI_MESSAGE_TAG)) + api->tag = stream_getl(s); + if (CHECK_FLAG(api->message, ZAPI_MESSAGE_MTU)) + api->mtu = stream_getl(s); + + return 0; } /* @@ -2017,25 +2112,15 @@ static int zclient_read(struct thread *thread) (*zclient->bfd_dest_replay)(command, zclient, length, vrf_id); break; - case ZEBRA_REDISTRIBUTE_IPV4_ADD: - if (zclient->redistribute_route_ipv4_add) - (*zclient->redistribute_route_ipv4_add)( - command, zclient, length, vrf_id); + case ZEBRA_REDISTRIBUTE_ROUTE_ADD: + if (zclient->redistribute_route_add) + (*zclient->redistribute_route_add)(command, zclient, + length, vrf_id); break; - case ZEBRA_REDISTRIBUTE_IPV4_DEL: - if (zclient->redistribute_route_ipv4_del) - (*zclient->redistribute_route_ipv4_del)( - command, zclient, length, vrf_id); - break; - case ZEBRA_REDISTRIBUTE_IPV6_ADD: - if (zclient->redistribute_route_ipv6_add) - (*zclient->redistribute_route_ipv6_add)( - command, zclient, length, vrf_id); - break; - case ZEBRA_REDISTRIBUTE_IPV6_DEL: - if (zclient->redistribute_route_ipv6_del) - (*zclient->redistribute_route_ipv6_del)( - command, zclient, length, vrf_id); + case ZEBRA_REDISTRIBUTE_ROUTE_DEL: + if (zclient->redistribute_route_del) + (*zclient->redistribute_route_del)(command, zclient, + length, vrf_id); break; case ZEBRA_INTERFACE_LINK_PARAMS: if (zclient->interface_link_params) diff --git a/lib/zclient.h b/lib/zclient.h index 15d1858d84..7c4780201e 100644 --- a/lib/zclient.h +++ b/lib/zclient.h @@ -21,7 +21,7 @@ #ifndef _ZEBRA_ZCLIENT_H #define _ZEBRA_ZCLIENT_H -/* For struct zapi_ipv{4,6}. */ +/* For struct zapi_route. */ #include "prefix.h" /* For struct interface and struct connected. */ @@ -59,6 +59,8 @@ typedef enum { ZEBRA_INTERFACE_UP, ZEBRA_INTERFACE_DOWN, ZEBRA_INTERFACE_SET_MASTER, + ZEBRA_ROUTE_ADD, + ZEBRA_ROUTE_DELETE, ZEBRA_IPV4_ROUTE_ADD, ZEBRA_IPV4_ROUTE_DELETE, ZEBRA_IPV6_ROUTE_ADD, @@ -85,10 +87,8 @@ typedef enum { ZEBRA_BFD_DEST_DEREGISTER, ZEBRA_BFD_DEST_UPDATE, ZEBRA_BFD_DEST_REPLAY, - ZEBRA_REDISTRIBUTE_IPV4_ADD, - ZEBRA_REDISTRIBUTE_IPV4_DEL, - ZEBRA_REDISTRIBUTE_IPV6_ADD, - ZEBRA_REDISTRIBUTE_IPV6_DEL, + ZEBRA_REDISTRIBUTE_ROUTE_ADD, + ZEBRA_REDISTRIBUTE_ROUTE_DEL, ZEBRA_VRF_UNREGISTER, ZEBRA_VRF_ADD, ZEBRA_VRF_DELETE, @@ -100,10 +100,6 @@ typedef enum { ZEBRA_INTERFACE_LINK_PARAMS, ZEBRA_MPLS_LABELS_ADD, ZEBRA_MPLS_LABELS_DELETE, - ZEBRA_IPV4_NEXTHOP_ADD, - ZEBRA_IPV4_NEXTHOP_DELETE, - ZEBRA_IPV6_NEXTHOP_ADD, - ZEBRA_IPV6_NEXTHOP_DELETE, ZEBRA_IPMR_ROUTE_STATS, ZEBRA_LABEL_MANAGER_CONNECT, ZEBRA_GET_LABEL_CHUNK, @@ -141,10 +137,6 @@ struct zclient { /* Socket to zebra daemon. */ int sock; - /* Flag of communication to zebra is enabled or not. Default is on. - This flag is disabled by `no router zebra' statement. */ - int enable; - /* Connection failure count. */ int fail; @@ -194,14 +186,10 @@ struct zclient { int (*nexthop_update)(int, struct zclient *, uint16_t, vrf_id_t); int (*import_check_update)(int, struct zclient *, uint16_t, vrf_id_t); int (*bfd_dest_replay)(int, struct zclient *, uint16_t, vrf_id_t); - int (*redistribute_route_ipv4_add)(int, struct zclient *, uint16_t, - vrf_id_t); - int (*redistribute_route_ipv4_del)(int, struct zclient *, uint16_t, - vrf_id_t); - int (*redistribute_route_ipv6_add)(int, struct zclient *, uint16_t, - vrf_id_t); - int (*redistribute_route_ipv6_del)(int, struct zclient *, uint16_t, - vrf_id_t); + int (*redistribute_route_add)(int, struct zclient *, uint16_t, + vrf_id_t); + int (*redistribute_route_del)(int, struct zclient *, uint16_t, + vrf_id_t); int (*fec_update)(int, struct zclient *, uint16_t); int (*local_vni_add)(int, struct zclient *, uint16_t, vrf_id_t); int (*local_vni_del)(int, struct zclient *, uint16_t, vrf_id_t); @@ -212,13 +200,12 @@ struct zclient { /* Zebra API message flag. */ #define ZAPI_MESSAGE_NEXTHOP 0x01 -#define ZAPI_MESSAGE_IFINDEX 0x02 -#define ZAPI_MESSAGE_DISTANCE 0x04 -#define ZAPI_MESSAGE_METRIC 0x08 -#define ZAPI_MESSAGE_TAG 0x10 -#define ZAPI_MESSAGE_MTU 0x20 -#define ZAPI_MESSAGE_SRCPFX 0x40 -#define ZAPI_MESSAGE_LABEL 0x80 +#define ZAPI_MESSAGE_DISTANCE 0x02 +#define ZAPI_MESSAGE_METRIC 0x04 +#define ZAPI_MESSAGE_TAG 0x08 +#define ZAPI_MESSAGE_MTU 0x10 +#define ZAPI_MESSAGE_SRCPFX 0x20 +#define ZAPI_MESSAGE_LABEL 0x40 /* Zserv protocol message header */ struct zserv_header { @@ -232,6 +219,16 @@ struct zserv_header { uint16_t command; }; +struct zapi_nexthop { + enum nexthop_types_t type; + ifindex_t ifindex; + union g_addr gate; + + /* MPLS labels for BGP-LU or Segment Routing */ + uint8_t label_num; + mpls_label_t labels[MPLS_MAX_LABELS]; +}; + struct zapi_route { u_char type; u_short instance; @@ -242,8 +239,11 @@ struct zapi_route { safi_t safi; - u_char nexthop_num; - struct nexthop **nexthop; + struct prefix prefix; + struct prefix_ipv6 src_prefix; + + u_int16_t nexthop_num; + struct zapi_nexthop nexthops[MULTIPATH_NUM]; u_char distance; @@ -369,7 +369,7 @@ extern struct interface *zebra_interface_vrf_update_read(struct stream *s, extern void zebra_interface_if_set_value(struct stream *, struct interface *); extern void zebra_router_id_update_read(struct stream *s, struct prefix *rid); extern int zapi_ipv4_route(u_char, struct zclient *, struct prefix_ipv4 *, - struct zapi_ipv4 *); + struct zapi_ipv4 *) __attribute__((deprecated)); extern struct interface *zebra_interface_link_params_read(struct stream *); extern size_t zebra_interface_link_params_write(struct stream *, @@ -420,11 +420,13 @@ struct zapi_ipv6 { extern int zapi_ipv6_route(u_char cmd, struct zclient *zclient, struct prefix_ipv6 *p, struct prefix_ipv6 *src_p, - struct zapi_ipv6 *api); + struct zapi_ipv6 *api) __attribute__((deprecated)); extern int zapi_ipv4_route_ipv6_nexthop(u_char, struct zclient *, struct prefix_ipv4 *, - struct zapi_ipv6 *); -extern int zapi_route(u_char cmd, struct zclient *zclient, struct prefix *p, - struct prefix_ipv6 *src_p, struct zapi_route *api); + struct zapi_ipv6 *) + __attribute__((deprecated)); +extern int zclient_route_send(u_char, struct zclient *, struct zapi_route *); +extern int zapi_route_encode(u_char, struct stream *, struct zapi_route *); +extern int zapi_route_decode(struct stream *, struct zapi_route *); #endif /* _ZEBRA_ZCLIENT_H */ diff --git a/nhrpd/nhrp_route.c b/nhrpd/nhrp_route.c index c8a608c657..4b86bca5f7 100644 --- a/nhrpd/nhrp_route.c +++ b/nhrpd/nhrp_route.c @@ -86,14 +86,20 @@ void nhrp_route_update_nhrp(const struct prefix *p, struct interface *ifp) void nhrp_route_announce(int add, enum nhrp_cache_type type, const struct prefix *p, struct interface *ifp, const union sockunion *nexthop, uint32_t mtu) { - int flags = 0; + struct zapi_route api; + struct zapi_nexthop *api_nh; if (zclient->sock < 0) return; + memset(&api, 0, sizeof(api)); + api.type = ZEBRA_ROUTE_NHRP; + api.safi = SAFI_UNICAST; + api.prefix = *p; + switch (type) { case NHRP_CACHE_NEGATIVE: - SET_FLAG(flags, ZEBRA_FLAG_REJECT); + SET_FLAG(api.flags, ZEBRA_FLAG_REJECT); break; case NHRP_CACHE_DYNAMIC: case NHRP_CACHE_NHS: @@ -102,158 +108,106 @@ void nhrp_route_announce(int add, enum nhrp_cache_type type, const struct prefix * to other routing daemons */ break; default: - SET_FLAG(flags, ZEBRA_FLAG_FIB_OVERRIDE); + SET_FLAG(api.flags, ZEBRA_FLAG_FIB_OVERRIDE); break; } - SET_FLAG(flags, ZEBRA_FLAG_INTERNAL); + SET_FLAG(api.flags, ZEBRA_FLAG_INTERNAL); - if (p->family == AF_INET) { - struct in_addr *nexthop_ipv4; - struct zapi_ipv4 api; + SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP); + api.nexthop_num = 1; + api_nh = &api.nexthops[0]; - memset(&api, 0, sizeof(api)); - api.flags = flags; - api.type = ZEBRA_ROUTE_NHRP; - api.safi = SAFI_UNICAST; - - SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP); + switch (api.prefix.family) { + case AF_INET: if (nexthop) { - nexthop_ipv4 = (struct in_addr *) sockunion_get_addr(nexthop); - api.nexthop_num = 1; - api.nexthop = &nexthop_ipv4; + api_nh->gate.ipv4 = nexthop->sin.sin_addr; + api_nh->type = NEXTHOP_TYPE_IPV4; } if (ifp) { - SET_FLAG(api.message, ZAPI_MESSAGE_IFINDEX); - api.ifindex_num = 1; - api.ifindex = &ifp->ifindex; + api_nh->ifindex = ifp->ifindex; + if (api_nh->type == NEXTHOP_TYPE_IPV4) + api_nh->type = NEXTHOP_TYPE_IPV4_IFINDEX; + else + api_nh->type = NEXTHOP_TYPE_IFINDEX; } - if (mtu) { - SET_FLAG(api.message, ZAPI_MESSAGE_MTU); - api.mtu = mtu; - } - - if (unlikely(debug_flags & NHRP_DEBUG_ROUTE)) { - char buf[2][INET_ADDRSTRLEN]; - zlog_debug("Zebra send: IPv4 route %s %s/%d nexthop %s metric %u" - " count %d dev %s", - add ? "add" : "del", - inet_ntop(AF_INET, &p->u.prefix4, buf[0], sizeof(buf[0])), - p->prefixlen, - nexthop ? inet_ntop(AF_INET, api.nexthop[0], buf[1], sizeof(buf[1])) : "", - api.metric, api.nexthop_num, ifp->name); - } - - zapi_ipv4_route( - add ? ZEBRA_IPV4_ROUTE_ADD : ZEBRA_IPV4_ROUTE_DELETE, - zclient, (struct prefix_ipv4 *) p, &api); - } else if (p->family == AF_INET6) { - struct in6_addr *nexthop_ipv6; - struct zapi_ipv6 api; - - memset(&api, 0, sizeof(api)); - api.flags = flags; - api.type = ZEBRA_ROUTE_NHRP; - api.safi = SAFI_UNICAST; - - SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP); + break; + case AF_INET6: if (nexthop) { - nexthop_ipv6 = (struct in6_addr *) sockunion_get_addr(nexthop); - api.nexthop_num = 1; - api.nexthop = &nexthop_ipv6; + api_nh->gate.ipv6 = nexthop->sin6.sin6_addr; + api_nh->type = NEXTHOP_TYPE_IPV6; } if (ifp) { - SET_FLAG(api.message, ZAPI_MESSAGE_IFINDEX); - api.ifindex_num = 1; - api.ifindex = &ifp->ifindex; + api_nh->ifindex = ifp->ifindex; + if (api_nh->type == NEXTHOP_TYPE_IPV6) + api_nh->type = NEXTHOP_TYPE_IPV6_IFINDEX; + else + api_nh->type = NEXTHOP_TYPE_IFINDEX; } - if (mtu) { - SET_FLAG(api.message, ZAPI_MESSAGE_MTU); - api.mtu = mtu; - } - - if (unlikely(debug_flags & NHRP_DEBUG_ROUTE)) { - char buf[2][INET6_ADDRSTRLEN]; - zlog_debug("Zebra send: IPv6 route %s %s/%d nexthop %s metric %u" - " count %d dev %s", - add ? "add" : "del", - inet_ntop(AF_INET6, &p->u.prefix6, buf[0], sizeof(buf[0])), - p->prefixlen, - nexthop ? inet_ntop(AF_INET6, api.nexthop[0], buf[1], sizeof(buf[1])) : "", - api.metric, api.nexthop_num, ifp->name); - } - - zapi_ipv6_route( - add ? ZEBRA_IPV6_ROUTE_ADD : ZEBRA_IPV6_ROUTE_DELETE, - zclient, (struct prefix_ipv6 *) p, NULL, &api); + break; } + if (mtu) { + SET_FLAG(api.message, ZAPI_MESSAGE_MTU); + api.mtu = mtu; + } + + if (unlikely(debug_flags & NHRP_DEBUG_ROUTE)) { + char buf[2][PREFIX_STRLEN]; + + prefix2str(&api.prefix, buf[0], sizeof(buf[0])); + zlog_debug("Zebra send: route %s %s nexthop %s metric %u" + " count %d dev %s", + add ? "add" : "del", buf[0], + nexthop ? inet_ntop(api.prefix.family, &api_nh->gate, buf[1], sizeof(buf[1])) : "", + api.metric, api.nexthop_num, ifp->name); + } + + zclient_route_send(add ? ZEBRA_ROUTE_ADD : ZEBRA_ROUTE_DELETE, zclient, + &api); } int nhrp_route_read(int cmd, struct zclient *zclient, zebra_size_t length, vrf_id_t vrf_id) { - struct stream *s; + struct zapi_route api; + struct zapi_nexthop *api_nh; struct interface *ifp = NULL; - struct prefix prefix; union sockunion nexthop_addr; - unsigned char message, nexthop_num, ifindex_num; - unsigned ifindex; char buf[2][PREFIX_STRLEN]; - int i, afaddrlen, added; + int added; - s = zclient->ibuf; - memset(&prefix, 0, sizeof(prefix)); - sockunion_family(&nexthop_addr) = AF_UNSPEC; - - /* Type, flags, message. */ - /*type =*/ stream_getc(s); - /*instance =*/ stream_getw(s); - /*flags =*/ stream_getl(s); - message = stream_getc(s); - - /* Prefix */ - switch (cmd) { - case ZEBRA_REDISTRIBUTE_IPV4_ADD: - case ZEBRA_REDISTRIBUTE_IPV4_DEL: - prefix.family = AF_INET; - break; - case ZEBRA_REDISTRIBUTE_IPV6_ADD: - case ZEBRA_REDISTRIBUTE_IPV6_DEL: - prefix.family = AF_INET6; - break; - default: + if (zapi_route_decode(zclient->ibuf, &api) < 0) return -1; - } - afaddrlen = family2addrsize(prefix.family); - prefix.prefixlen = stream_getc(s); - stream_get(&prefix.u.val, s, PSIZE(prefix.prefixlen)); - /* Nexthop, ifindex, distance, metric. */ - if (CHECK_FLAG(message, ZAPI_MESSAGE_NEXTHOP|ZAPI_MESSAGE_IFINDEX)) { - nexthop_num = stream_getc(s); - for (i = 0; i < nexthop_num; i++) { - stream_get(buf[0], s, afaddrlen); - if (i == 0) sockunion_set(&nexthop_addr, prefix.family, (u_char*) buf[0], afaddrlen); - } - ifindex_num = stream_getc(s); - for (i = 0; i < ifindex_num; i++) { - ifindex = stream_getl(s); - if (i == 0 && ifindex != IFINDEX_INTERNAL) - ifp = if_lookup_by_index(ifindex, VRF_DEFAULT); - } - } - if (CHECK_FLAG(message, ZAPI_MESSAGE_DISTANCE)) - /*distance =*/ stream_getc(s); - if (CHECK_FLAG(message, ZAPI_MESSAGE_METRIC)) - /*metric =*/ stream_getl(s); + /* we completely ignore srcdest routes for now. */ + if (CHECK_FLAG(api.message, ZAPI_MESSAGE_SRCPFX)) + return 0; - added = (cmd == ZEBRA_REDISTRIBUTE_IPV4_ADD || cmd == ZEBRA_REDISTRIBUTE_IPV6_ADD); + sockunion_family(&nexthop_addr) = AF_UNSPEC; + if (CHECK_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP)) { + api_nh = &api.nexthops[0]; + + nexthop_addr.sa.sa_family = api.prefix.family; + switch (nexthop_addr.sa.sa_family) { + case AF_INET: + nexthop_addr.sin.sin_addr = api_nh->gate.ipv4; + break; + case AF_INET6: + nexthop_addr.sin6.sin6_addr = api_nh->gate.ipv6; + break; + } + + if (api_nh->ifindex != IFINDEX_INTERNAL) + ifp = if_lookup_by_index(api_nh->ifindex, VRF_DEFAULT); + } + + added = (cmd == ZEBRA_REDISTRIBUTE_ROUTE_ADD); debugf(NHRP_DEBUG_ROUTE, "if-route-%s: %s via %s dev %s", added ? "add" : "del", - prefix2str(&prefix, buf[0], sizeof buf[0]), + prefix2str(&api.prefix, buf[0], sizeof buf[0]), sockunion2str(&nexthop_addr, buf[1], sizeof buf[1]), ifp ? ifp->name : "(none)"); - nhrp_route_update_zebra(&prefix, &nexthop_addr, ifp); - nhrp_shortcut_prefix_change(&prefix, !added); + nhrp_route_update_zebra(&api.prefix, &nexthop_addr, ifp); + nhrp_shortcut_prefix_change(&api.prefix, !added); return 0; } @@ -366,10 +320,8 @@ void nhrp_zebra_init(void) zclient->interface_down = nhrp_interface_down; zclient->interface_address_add = nhrp_interface_address_add; zclient->interface_address_delete = nhrp_interface_address_delete; - zclient->redistribute_route_ipv4_add = nhrp_route_read; - zclient->redistribute_route_ipv4_del = nhrp_route_read; - zclient->redistribute_route_ipv6_add = nhrp_route_read; - zclient->redistribute_route_ipv6_del = nhrp_route_read; + zclient->redistribute_route_add = nhrp_route_read; + zclient->redistribute_route_del = nhrp_route_read; zclient_init(zclient, ZEBRA_ROUTE_NHRP, 0); } @@ -381,4 +333,3 @@ void nhrp_zebra_terminate(void) route_table_finish(zebra_rib[AFI_IP]); route_table_finish(zebra_rib[AFI_IP6]); } - diff --git a/ospf6d/ospf6_abr.c b/ospf6d/ospf6_abr.c index f198ac4af6..36528d063c 100644 --- a/ospf6d/ospf6_abr.c +++ b/ospf6d/ospf6_abr.c @@ -386,27 +386,20 @@ int ospf6_abr_originate_summary_to_area(struct ospf6_route *route, } /* Check filter-list */ - if (PREFIX_NAME_OUT(area)) { - if (PREFIX_LIST_OUT(area) == NULL) - PREFIX_LIST_OUT(area) = prefix_list_lookup( - AFI_IP6, PREFIX_NAME_OUT(area)); - - if (PREFIX_LIST_OUT(area)) - if (prefix_list_apply(PREFIX_LIST_OUT(area), - &route->prefix) - != PREFIX_PERMIT) { - if (is_debug) { - inet_ntop(AF_INET, - &(ADV_ROUTER_IN_PREFIX( - &route->prefix)), - buf, sizeof(buf)); - zlog_debug( - "prefix %s was denied by filter-list out", - buf); - } - return 0; + if (PREFIX_LIST_OUT(area)) + if (prefix_list_apply(PREFIX_LIST_OUT(area), &route->prefix) + != PREFIX_PERMIT) { + if (is_debug) { + inet_ntop(AF_INET, + &(ADV_ROUTER_IN_PREFIX( + &route->prefix)), + buf, sizeof(buf)); + zlog_debug( + "prefix %s was denied by filter-list out", + buf); } - } + return 0; + } /* the route is going to be originated. store it in area's summary_table */ @@ -873,22 +866,16 @@ void ospf6_abr_examin_summary(struct ospf6_lsa *lsa, struct ospf6_area *oa) } /* Check input prefix-list */ - if (PREFIX_NAME_IN(oa)) { - if (PREFIX_LIST_IN(oa) == NULL) - PREFIX_LIST_IN(oa) = - prefix_list_lookup(AFI_IP6, PREFIX_NAME_IN(oa)); - - if (PREFIX_LIST_IN(oa)) - if (prefix_list_apply(PREFIX_LIST_IN(oa), &prefix) - != PREFIX_PERMIT) { - if (is_debug) - zlog_debug( - "Prefix was denied by prefix-list"); - if (old) - ospf6_route_remove(old, table); - return; - } - } + if (PREFIX_LIST_IN(oa)) + if (prefix_list_apply(PREFIX_LIST_IN(oa), &prefix) + != PREFIX_PERMIT) { + if (is_debug) + zlog_debug( + "Prefix was denied by prefix-list"); + if (old) + ospf6_route_remove(old, table); + return; + } /* (5),(6): the path preference is handled by the sorting in the routing table. Always install the path by substituting diff --git a/ospf6d/ospf6_area.c b/ospf6d/ospf6_area.c index a4cc0bf420..649d7a1000 100644 --- a/ospf6d/ospf6_area.c +++ b/ospf6d/ospf6_area.c @@ -45,6 +45,8 @@ #include "ospf6_asbr.h" #include "ospf6d.h" +DEFINE_MTYPE_STATIC(OSPF6D, OSPF6_PLISTNAME, "Prefix list name") + int ospf6_area_cmp(void *va, void *vb) { struct ospf6_area *oa = (struct ospf6_area *)va; @@ -579,17 +581,15 @@ DEFUN (area_filter_list, plist = prefix_list_lookup(AFI_IP6, plistname); if (strmatch(inout, "in")) { PREFIX_LIST_IN(area) = plist; - if (PREFIX_NAME_IN(area)) - free(PREFIX_NAME_IN(area)); - - PREFIX_NAME_IN(area) = strdup(plistname); + XFREE(MTYPE_OSPF6_PLISTNAME, PREFIX_NAME_IN(area)); + PREFIX_NAME_IN(area) = XSTRDUP(MTYPE_OSPF6_PLISTNAME, + plistname); ospf6_abr_reimport(area); } else { PREFIX_LIST_OUT(area) = plist; - if (PREFIX_NAME_OUT(area)) - free(PREFIX_NAME_OUT(area)); - - PREFIX_NAME_OUT(area) = strdup(plistname); + XFREE(MTYPE_OSPF6_PLISTNAME, PREFIX_NAME_OUT(area)); + PREFIX_NAME_OUT(area) = XSTRDUP(MTYPE_OSPF6_PLISTNAME, + plistname); ospf6_abr_enable_area(area); } @@ -622,27 +622,34 @@ DEFUN (no_area_filter_list, return CMD_SUCCESS; PREFIX_LIST_IN(area) = NULL; - if (PREFIX_NAME_IN(area)) - free(PREFIX_NAME_IN(area)); - - PREFIX_NAME_IN(area) = NULL; + XFREE(MTYPE_OSPF6_PLISTNAME, PREFIX_NAME_IN(area)); ospf6_abr_reimport(area); } else { if (PREFIX_NAME_OUT(area)) if (!strmatch(PREFIX_NAME_OUT(area), plistname)) return CMD_SUCCESS; - PREFIX_LIST_OUT(area) = NULL; - if (PREFIX_NAME_OUT(area)) - free(PREFIX_NAME_OUT(area)); - - PREFIX_NAME_OUT(area) = NULL; + XFREE(MTYPE_OSPF6_PLISTNAME, PREFIX_NAME_OUT(area)); ospf6_abr_enable_area(area); } return CMD_SUCCESS; } +void ospf6_area_plist_update(struct prefix_list *plist, int add) +{ + struct ospf6_area *oa; + struct listnode *n; + const char *name = prefix_list_name(plist); + + for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, n, oa)) { + if (!strcmp(PREFIX_NAME_IN(oa), name)) + PREFIX_LIST_IN(oa) = add ? plist : NULL; + if (!strcmp(PREFIX_NAME_OUT(oa), name)) + PREFIX_LIST_OUT(oa) = add ? plist : NULL; + } +} + DEFUN (area_import_list, area_import_list_cmd, "area A.B.C.D import-list NAME", diff --git a/ospf6d/ospf6_area.h b/ospf6d/ospf6_area.h index 4bc24a6dd8..d212d92387 100644 --- a/ospf6d/ospf6_area.h +++ b/ospf6d/ospf6_area.h @@ -122,6 +122,7 @@ extern void ospf6_area_disable(struct ospf6_area *); extern void ospf6_area_show(struct vty *, struct ospf6_area *); +extern void ospf6_area_plist_update(struct prefix_list *plist, int add); extern void ospf6_area_config_write(struct vty *vty); extern void ospf6_area_init(void); diff --git a/ospf6d/ospf6_interface.c b/ospf6d/ospf6_interface.c index 1d17a1c233..bb63fb966e 100644 --- a/ospf6d/ospf6_interface.c +++ b/ospf6d/ospf6_interface.c @@ -1171,8 +1171,7 @@ DEFUN (ipv6_ospf6_cost, IP6_STR OSPF6_STR "Interface cost\n" - "Outgoing metric of this interface\n" - ) + "Outgoing metric of this interface\n") { VTY_DECLVAR_CONTEXT(interface, ifp); int idx_number = 3; @@ -1206,12 +1205,12 @@ DEFUN (ipv6_ospf6_cost, DEFUN (no_ipv6_ospf6_cost, no_ipv6_ospf6_cost_cmd, - "no ipv6 ospf6 cost", + "no ipv6 ospf6 cost [(1-65535)]", NO_STR IP6_STR OSPF6_STR "Calculate interface cost from bandwidth\n" - ) + "Outgoing metric of this interface\n") { VTY_DECLVAR_CONTEXT(interface, ifp); struct ospf6_interface *oi; @@ -1292,8 +1291,7 @@ DEFUN (ipv6_ospf6_hellointerval, IP6_STR OSPF6_STR "Time between HELLO packets\n" - SECONDS_STR - ) + SECONDS_STR) { VTY_DECLVAR_CONTEXT(interface, ifp); int idx_number = 3; @@ -1305,10 +1303,21 @@ DEFUN (ipv6_ospf6_hellointerval, oi = ospf6_interface_create(ifp); assert(oi); - oi->hello_interval = strtol(argv[idx_number]->arg, NULL, 10); + oi->hello_interval = strmatch(argv[0]->text, "no") + ? OSPF_HELLO_INTERVAL_DEFAULT + : strtoul(argv[idx_number]->arg, NULL, 10); return CMD_SUCCESS; } +ALIAS (ipv6_ospf6_hellointerval, + no_ipv6_ospf6_hellointerval_cmd, + "no ipv6 ospf6 hello-interval [(1-65535)]", + NO_STR + IP6_STR + OSPF6_STR + "Time between HELLO packets\n" + SECONDS_STR) + /* interface variable set command */ DEFUN (ipv6_ospf6_deadinterval, ipv6_ospf6_deadinterval_cmd, @@ -1316,8 +1325,7 @@ DEFUN (ipv6_ospf6_deadinterval, IP6_STR OSPF6_STR "Interval time after which a neighbor is declared down\n" - SECONDS_STR - ) + SECONDS_STR) { VTY_DECLVAR_CONTEXT(interface, ifp); int idx_number = 3; @@ -1329,10 +1337,21 @@ DEFUN (ipv6_ospf6_deadinterval, oi = ospf6_interface_create(ifp); assert(oi); - oi->dead_interval = strtol(argv[idx_number]->arg, NULL, 10); + oi->dead_interval = strmatch(argv[0]->arg, "no") + ? OSPF_ROUTER_DEAD_INTERVAL_DEFAULT + : strtoul(argv[idx_number]->arg, NULL, 10); return CMD_SUCCESS; } +ALIAS (ipv6_ospf6_deadinterval, + no_ipv6_ospf6_deadinterval_cmd, + "no ipv6 ospf6 dead-interval [(1-65535)]", + NO_STR + IP6_STR + OSPF6_STR + "Interval time after which a neighbor is declared down\n" + SECONDS_STR) + /* interface variable set command */ DEFUN (ipv6_ospf6_transmitdelay, ipv6_ospf6_transmitdelay_cmd, @@ -1352,10 +1371,21 @@ DEFUN (ipv6_ospf6_transmitdelay, oi = ospf6_interface_create(ifp); assert(oi); - oi->transdelay = strtol(argv[idx_number]->arg, NULL, 10); + oi->transdelay = strmatch(argv[0]->text, "no") + ? OSPF6_INTERFACE_TRANSDELAY + : strtoul(argv[idx_number]->arg, NULL, 10); return CMD_SUCCESS; } +ALIAS (ipv6_ospf6_transmitdelay, + no_ipv6_ospf6_transmitdelay_cmd, + "no ipv6 ospf6 transmit-delay [(1-3600)]", + NO_STR + IP6_STR + OSPF6_STR + "Link state transmit delay\n" + SECONDS_STR) + /* interface variable set command */ DEFUN (ipv6_ospf6_retransmitinterval, ipv6_ospf6_retransmitinterval_cmd, @@ -1363,8 +1393,7 @@ DEFUN (ipv6_ospf6_retransmitinterval, IP6_STR OSPF6_STR "Time between retransmitting lost link state advertisements\n" - SECONDS_STR - ) + SECONDS_STR) { VTY_DECLVAR_CONTEXT(interface, ifp); int idx_number = 3; @@ -1376,10 +1405,21 @@ DEFUN (ipv6_ospf6_retransmitinterval, oi = ospf6_interface_create(ifp); assert(oi); - oi->rxmt_interval = strtol(argv[idx_number]->arg, NULL, 10); + oi->rxmt_interval = strmatch(argv[0]->text, "no") + ? OSPF_RETRANSMIT_INTERVAL_DEFAULT + : strtoul(argv[idx_number]->arg, NULL, 10); return CMD_SUCCESS; } +ALIAS (ipv6_ospf6_retransmitinterval, + no_ipv6_ospf6_retransmitinterval_cmd, + "no ipv6 ospf6 retransmit-interval [(1-65535)]", + NO_STR + IP6_STR + OSPF6_STR + "Time between retransmitting lost link state advertisements\n" + SECONDS_STR) + /* interface variable set command */ DEFUN (ipv6_ospf6_priority, ipv6_ospf6_priority_cmd, @@ -1387,8 +1427,7 @@ DEFUN (ipv6_ospf6_priority, IP6_STR OSPF6_STR "Router priority\n" - "Priority value\n" - ) + "Priority value\n") { VTY_DECLVAR_CONTEXT(interface, ifp); int idx_number = 3; @@ -1400,7 +1439,9 @@ DEFUN (ipv6_ospf6_priority, oi = ospf6_interface_create(ifp); assert(oi); - oi->priority = strtol(argv[idx_number]->arg, NULL, 10); + oi->priority = strmatch(argv[0]->text, "no") + ? OSPF6_INTERFACE_PRIORITY + : strtoul(argv[idx_number]->arg, NULL, 10); if (oi->area && (oi->state == OSPF6_INTERFACE_DROTHER || oi->state == OSPF6_INTERFACE_BDR @@ -1410,14 +1451,22 @@ DEFUN (ipv6_ospf6_priority, return CMD_SUCCESS; } +ALIAS (ipv6_ospf6_priority, + no_ipv6_ospf6_priority_cmd, + "no ipv6 ospf6 priority [(0-255)]", + NO_STR + IP6_STR + OSPF6_STR + "Router priority\n" + "Priority value\n") + DEFUN (ipv6_ospf6_instance, ipv6_ospf6_instance_cmd, "ipv6 ospf6 instance-id (0-255)", IP6_STR OSPF6_STR "Instance ID for this interface\n" - "Instance ID value\n" - ) + "Instance ID value\n") { VTY_DECLVAR_CONTEXT(interface, ifp); int idx_number = 3; @@ -1429,10 +1478,21 @@ DEFUN (ipv6_ospf6_instance, oi = ospf6_interface_create(ifp); assert(oi); - oi->instance_id = strtol(argv[idx_number]->arg, NULL, 10); + oi->instance_id = strmatch(argv[0]->text, "no") + ? OSPF6_INTERFACE_INSTANCE_ID + : strtoul(argv[idx_number]->arg, NULL, 10); return CMD_SUCCESS; } +ALIAS (ipv6_ospf6_instance, + no_ipv6_ospf6_instance_cmd, + "no ipv6 ospf6 instance-id [(0-255)]", + NO_STR + IP6_STR + OSPF6_STR + "Instance ID for this interface\n" + "Instance ID value\n") + DEFUN (ipv6_ospf6_passive, ipv6_ospf6_passive_cmd, "ipv6 ospf6 passive", @@ -1576,13 +1636,13 @@ DEFUN (ipv6_ospf6_advertise_prefix_list, DEFUN (no_ipv6_ospf6_advertise_prefix_list, no_ipv6_ospf6_advertise_prefix_list_cmd, - "no ipv6 ospf6 advertise prefix-list", + "no ipv6 ospf6 advertise prefix-list [WORD]", NO_STR IP6_STR OSPF6_STR "Advertising options\n" "Filter prefix using prefix-list\n" - ) + "Prefix list name\n") { VTY_DECLVAR_CONTEXT(interface, ifp); struct ospf6_interface *oi; @@ -1593,10 +1653,8 @@ DEFUN (no_ipv6_ospf6_advertise_prefix_list, oi = ospf6_interface_create(ifp); assert(oi); - if (oi->plist_name) { + if (oi->plist_name) XFREE(MTYPE_CFG_PLIST_NAME, oi->plist_name); - oi->plist_name = NULL; - } ospf6_interface_connected_route_update(oi->interface); @@ -1654,11 +1712,13 @@ DEFUN (ipv6_ospf6_network, DEFUN (no_ipv6_ospf6_network, no_ipv6_ospf6_network_cmd, - "no ipv6 ospf6 network", + "no ipv6 ospf6 network []", NO_STR IP6_STR OSPF6_STR - "Set default network type\n") + "Set default network type\n" + "Specify OSPF6 broadcast network\n" + "Specify OSPF6 point-to-point network\n") { VTY_DECLVAR_CONTEXT(interface, ifp); struct ospf6_interface *oi; @@ -1772,12 +1832,19 @@ void ospf6_interface_init(void) install_element(INTERFACE_NODE, &no_ipv6_ospf6_cost_cmd); install_element(INTERFACE_NODE, &ipv6_ospf6_ifmtu_cmd); install_element(INTERFACE_NODE, &no_ipv6_ospf6_ifmtu_cmd); + install_element(INTERFACE_NODE, &ipv6_ospf6_deadinterval_cmd); install_element(INTERFACE_NODE, &ipv6_ospf6_hellointerval_cmd); install_element(INTERFACE_NODE, &ipv6_ospf6_priority_cmd); install_element(INTERFACE_NODE, &ipv6_ospf6_retransmitinterval_cmd); install_element(INTERFACE_NODE, &ipv6_ospf6_transmitdelay_cmd); install_element(INTERFACE_NODE, &ipv6_ospf6_instance_cmd); + install_element(INTERFACE_NODE, &no_ipv6_ospf6_deadinterval_cmd); + install_element(INTERFACE_NODE, &no_ipv6_ospf6_hellointerval_cmd); + install_element(INTERFACE_NODE, &no_ipv6_ospf6_priority_cmd); + install_element(INTERFACE_NODE, &no_ipv6_ospf6_retransmitinterval_cmd); + install_element(INTERFACE_NODE, &no_ipv6_ospf6_transmitdelay_cmd); + install_element(INTERFACE_NODE, &no_ipv6_ospf6_instance_cmd); install_element(INTERFACE_NODE, &ipv6_ospf6_passive_cmd); install_element(INTERFACE_NODE, &no_ipv6_ospf6_passive_cmd); diff --git a/ospf6d/ospf6_route.c b/ospf6d/ospf6_route.c index bfe583a911..e58eab2b15 100644 --- a/ospf6d/ospf6_route.c +++ b/ospf6d/ospf6_route.c @@ -285,8 +285,7 @@ void ospf6_add_nexthop(struct list *nh_list, int ifindex, struct in6_addr *addr) } void ospf6_route_zebra_copy_nexthops(struct ospf6_route *route, - ifindex_t *ifindexes, - struct in6_addr **nexthop_addr, + struct zapi_nexthop nexthops[], int entries) { struct ospf6_nexthop *nh; @@ -306,13 +305,16 @@ void ospf6_route_zebra_copy_nexthops(struct ospf6_route *route, zlog_debug(" nexthop: %s%%%.*s(%d)", buf, IFNAMSIZ, ifname, nh->ifindex); } - if (i < entries) { - nexthop_addr[i] = &nh->address; - ifindexes[i] = nh->ifindex; - i++; - } else { + if (i >= entries) return; - } + + nexthops[i].ifindex = nh->ifindex; + if (!IN6_IS_ADDR_UNSPECIFIED(&nh->address)) { + nexthops[i].gate.ipv6 = nh->address; + nexthops[i].type = NEXTHOP_TYPE_IPV6_IFINDEX; + } else + nexthops[i].type = NEXTHOP_TYPE_IFINDEX; + i++; } } } diff --git a/ospf6d/ospf6_route.h b/ospf6d/ospf6_route.h index 166074fb70..9eacadbdb7 100644 --- a/ospf6d/ospf6_route.h +++ b/ospf6d/ospf6_route.h @@ -22,6 +22,7 @@ #define OSPF6_ROUTE_H #include "command.h" +#include "zclient.h" #define OSPF6_MULTI_PATH_LIMIT 4 @@ -266,8 +267,7 @@ extern int ospf6_num_nexthops(struct list *nh_list); extern int ospf6_route_cmp_nexthops(struct ospf6_route *a, struct ospf6_route *b); extern void ospf6_route_zebra_copy_nexthops(struct ospf6_route *route, - ifindex_t *ifindices, - struct in6_addr **addr, + struct zapi_nexthop nexthops[], int entries); extern int ospf6_route_get_first_nh_index(struct ospf6_route *route); diff --git a/ospf6d/ospf6_zebra.c b/ospf6d/ospf6_zebra.c index d33f41730e..3443bc47b6 100644 --- a/ospf6d/ospf6_zebra.c +++ b/ospf6d/ospf6_zebra.c @@ -207,75 +207,30 @@ static int ospf6_zebra_if_address_update_delete(int command, return 0; } -static int ospf6_zebra_read_ipv6(int command, struct zclient *zclient, - zebra_size_t length, vrf_id_t vrf_id) +static int ospf6_zebra_read_route(int command, struct zclient *zclient, + zebra_size_t length, vrf_id_t vrf_id) { - struct stream *s; - struct zapi_ipv6 api; + struct zapi_route api; unsigned long ifindex; - struct prefix p, src_p; struct in6_addr *nexthop; if (ospf6 == NULL) return 0; - s = zclient->ibuf; - ifindex = 0; - nexthop = NULL; - memset(&api, 0, sizeof(api)); + if (zapi_route_decode(zclient->ibuf, &api) < 0) + return -1; - /* Type, flags, message. */ - api.type = stream_getc(s); - api.instance = stream_getw(s); - api.flags = stream_getl(s); - api.message = stream_getc(s); - - /* IPv6 prefix. */ - memset(&p, 0, sizeof(struct prefix)); - p.family = AF_INET6; - p.prefixlen = MIN(IPV6_MAX_PREFIXLEN, stream_getc(s)); - stream_get(&p.u.prefix6, s, PSIZE(p.prefixlen)); - - memset(&src_p, 0, sizeof(struct prefix)); - src_p.family = AF_INET6; - if (CHECK_FLAG(api.message, ZAPI_MESSAGE_SRCPFX)) { - src_p.prefixlen = stream_getc(s); - stream_get(&src_p.u.prefix6, s, PSIZE(src_p.prefixlen)); - } - - if (src_p.prefixlen) - /* we completely ignore srcdest routes for now. */ + /* we completely ignore srcdest routes for now. */ + if (CHECK_FLAG(api.message, ZAPI_MESSAGE_SRCPFX)) return 0; - /* Nexthop, ifindex, distance, metric. */ - if (CHECK_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP)) { - api.nexthop_num = stream_getc(s); - nexthop = (struct in6_addr *)malloc(api.nexthop_num - * sizeof(struct in6_addr)); - stream_get(nexthop, s, - api.nexthop_num * sizeof(struct in6_addr)); - } - if (CHECK_FLAG(api.message, ZAPI_MESSAGE_IFINDEX)) { - api.ifindex_num = stream_getc(s); - ifindex = stream_getl(s); - } - if (CHECK_FLAG(api.message, ZAPI_MESSAGE_DISTANCE)) - api.distance = stream_getc(s); - else - api.distance = 0; - if (CHECK_FLAG(api.message, ZAPI_MESSAGE_METRIC)) - api.metric = stream_getl(s); - else - api.metric = 0; - - if (CHECK_FLAG(api.message, ZAPI_MESSAGE_TAG)) - api.tag = stream_getl(s); - else - api.tag = 0; + ifindex = api.nexthops[0].ifindex; + nexthop = &api.nexthops[0].gate.ipv6; if (IS_OSPF6_DEBUG_ZEBRA(RECV)) { char prefixstr[PREFIX2STR_BUFFER], nexthopstr[128]; - prefix2str((struct prefix *)&p, prefixstr, sizeof(prefixstr)); + prefix2str((struct prefix *)&api.prefix, prefixstr, + sizeof(prefixstr)); if (nexthop) inet_ntop(AF_INET6, nexthop, nexthopstr, sizeof(nexthopstr)); @@ -284,20 +239,17 @@ static int ospf6_zebra_read_ipv6(int command, struct zclient *zclient, zlog_debug( "Zebra Receive route %s: %s %s nexthop %s ifindex %ld tag %" ROUTE_TAG_PRI, - (command == ZEBRA_REDISTRIBUTE_IPV6_ADD ? "add" - : "delete"), + (command == ZEBRA_REDISTRIBUTE_ROUTE_ADD ? "add" + : "delete"), zebra_route_string(api.type), prefixstr, nexthopstr, ifindex, api.tag); } - if (command == ZEBRA_REDISTRIBUTE_IPV6_ADD) - ospf6_asbr_redistribute_add(api.type, ifindex, &p, + if (command == ZEBRA_REDISTRIBUTE_ROUTE_ADD) + ospf6_asbr_redistribute_add(api.type, ifindex, &api.prefix, api.nexthop_num, nexthop, api.tag); else - ospf6_asbr_redistribute_remove(api.type, ifindex, &p); - - if (CHECK_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP)) - free(nexthop); + ospf6_asbr_redistribute_remove(api.type, ifindex, &api.prefix); return 0; } @@ -317,7 +269,7 @@ DEFUN (show_zebra, } vty_out(vty, "Zebra Infomation\n"); - vty_out(vty, " enable: %d fail: %d\n", zclient->enable, zclient->fail); + vty_out(vty, " fail: %d\n", zclient->fail); vty_out(vty, " redistribute default: %d\n", vrf_bitmap_check(zclient->default_information, VRF_DEFAULT)); vty_out(vty, " redistribute:"); @@ -329,38 +281,15 @@ DEFUN (show_zebra, return CMD_SUCCESS; } -/* Zebra configuration write function. */ -static int config_write_ospf6_zebra(struct vty *vty) -{ - if (!zclient->enable) { - vty_out(vty, "no router zebra\n"); - vty_out(vty, "!\n"); - } else if (!vrf_bitmap_check( - zclient->redist[AFI_IP6][ZEBRA_ROUTE_OSPF6], - VRF_DEFAULT)) { - vty_out(vty, "router zebra\n"); - vty_out(vty, " no redistribute ospf6\n"); - vty_out(vty, "!\n"); - } - return 0; -} - -/* Zebra node structure. */ -static struct cmd_node zebra_node = { - ZEBRA_NODE, "%s(config-zebra)# ", -}; - #define ADD 0 #define REM 1 static void ospf6_zebra_route_update(int type, struct ospf6_route *request) { - struct zapi_ipv6 api; + struct zapi_route api; char buf[PREFIX2STR_BUFFER]; int nhcount; - struct in6_addr **nexthops; - ifindex_t *ifindexes; int ret = 0; - struct prefix_ipv6 *dest; + struct prefix *dest; if (IS_OSPF6_DEBUG_ZEBRA(SEND)) { prefix2str(&request->prefix, buf, sizeof(buf)); @@ -408,36 +337,16 @@ static void ospf6_zebra_route_update(int type, struct ospf6_route *request) return; } - /* allocate memory for nexthop_list */ - nexthops = - XCALLOC(MTYPE_OSPF6_OTHER, nhcount * sizeof(struct in6_addr *)); - if (nexthops == NULL) { - zlog_warn("Can't send route to zebra: malloc failed"); - return; - } - - /* allocate memory for ifindex_list */ - ifindexes = XCALLOC(MTYPE_OSPF6_OTHER, nhcount * sizeof(ifindex_t)); - if (ifindexes == NULL) { - zlog_warn("Can't send route to zebra: malloc failed"); - XFREE(MTYPE_OSPF6_OTHER, nexthops); - return; - } - - ospf6_route_zebra_copy_nexthops(request, ifindexes, nexthops, nhcount); + dest = &request->prefix; + memset(&api, 0, sizeof(api)); api.vrf_id = VRF_DEFAULT; api.type = ZEBRA_ROUTE_OSPF6; - api.instance = 0; - api.flags = 0; - api.message = 0; api.safi = SAFI_UNICAST; + api.prefix = *dest; SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP); api.nexthop_num = nhcount; - api.nexthop = nexthops; - SET_FLAG(api.message, ZAPI_MESSAGE_IFINDEX); - api.ifindex_num = nhcount; - api.ifindex = ifindexes; + ospf6_route_zebra_copy_nexthops(request, api.nexthops, nhcount); SET_FLAG(api.message, ZAPI_MESSAGE_METRIC); api.metric = (request->path.metric_type == 2 ? request->path.u.cost_e2 : request->path.cost); @@ -446,195 +355,99 @@ static void ospf6_zebra_route_update(int type, struct ospf6_route *request) api.tag = request->path.tag; } - dest = (struct prefix_ipv6 *)&request->prefix; - SET_FLAG(api.message, ZAPI_MESSAGE_DISTANCE); - api.distance = ospf6_distance_apply(dest, request); + api.distance = + ospf6_distance_apply((struct prefix_ipv6 *)dest, request); if (type == REM) - ret = zapi_ipv6_route(ZEBRA_IPV6_ROUTE_DELETE, zclient, dest, - NULL, &api); + ret = zclient_route_send(ZEBRA_ROUTE_DELETE, zclient, &api); else - ret = zapi_ipv6_route(ZEBRA_IPV6_ROUTE_ADD, zclient, dest, NULL, - &api); + ret = zclient_route_send(ZEBRA_ROUTE_ADD, zclient, &api); if (ret < 0) - zlog_err("zapi_ipv6_route() %s failed: %s", + zlog_err("zclient_route_send() %s failed: %s", (type == REM ? "delete" : "add"), safe_strerror(errno)); - XFREE(MTYPE_OSPF6_OTHER, nexthops); - XFREE(MTYPE_OSPF6_OTHER, ifindexes); - return; } void ospf6_zebra_route_update_add(struct ospf6_route *request) { - if (!vrf_bitmap_check(zclient->redist[AFI_IP6][ZEBRA_ROUTE_OSPF6], - VRF_DEFAULT)) { - ospf6->route_table->hook_add = NULL; - ospf6->route_table->hook_remove = NULL; - return; - } ospf6_zebra_route_update(ADD, request); } void ospf6_zebra_route_update_remove(struct ospf6_route *request) { - if (!vrf_bitmap_check(zclient->redist[AFI_IP6][ZEBRA_ROUTE_OSPF6], - VRF_DEFAULT)) { - ospf6->route_table->hook_add = NULL; - ospf6->route_table->hook_remove = NULL; - return; - } ospf6_zebra_route_update(REM, request); } void ospf6_zebra_add_discard(struct ospf6_route *request) { - struct zapi_ipv6 api; + struct zapi_route api; char buf[INET6_ADDRSTRLEN]; - struct prefix_ipv6 *dest; + struct prefix *dest = &request->prefix; - if (vrf_bitmap_check(zclient->redist[AFI_IP6][ZEBRA_ROUTE_OSPF6], - VRF_DEFAULT)) { - if (!CHECK_FLAG(request->flag, OSPF6_ROUTE_BLACKHOLE_ADDED)) { - api.vrf_id = VRF_DEFAULT; - api.type = ZEBRA_ROUTE_OSPF6; - api.flags = ZEBRA_FLAG_BLACKHOLE; - api.instance = 0; - api.message = 0; - api.safi = SAFI_UNICAST; - SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP); - api.nexthop_num = 0; - api.ifindex_num = 0; + if (!CHECK_FLAG(request->flag, OSPF6_ROUTE_BLACKHOLE_ADDED)) { + memset(&api, 0, sizeof(api)); + api.vrf_id = VRF_DEFAULT; + api.type = ZEBRA_ROUTE_OSPF6; + api.flags = ZEBRA_FLAG_BLACKHOLE; + api.safi = SAFI_UNICAST; + api.prefix = *dest; - dest = (struct prefix_ipv6 *)&request->prefix; + zclient_route_send(ZEBRA_ROUTE_ADD, zclient, &api); - zapi_ipv6_route(ZEBRA_IPV6_ROUTE_ADD, zclient, dest, - NULL, &api); + if (IS_OSPF6_DEBUG_ZEBRA(SEND)) + zlog_debug("Zebra: Route add discard %s/%d", + inet_ntop(AF_INET6, &dest->u.prefix6, buf, + INET6_ADDRSTRLEN), + dest->prefixlen); - if (IS_OSPF6_DEBUG_ZEBRA(SEND)) - zlog_debug("Zebra: Route add discard %s/%d", - inet_ntop(AF_INET6, &dest->prefix, - buf, INET6_ADDRSTRLEN), - dest->prefixlen); - SET_FLAG(request->flag, OSPF6_ROUTE_BLACKHOLE_ADDED); - } else { - dest = (struct prefix_ipv6 *)&request->prefix; - - if (IS_OSPF6_DEBUG_ZEBRA(SEND)) - zlog_debug( - "Zebra: Blackhole route present already %s/%d", - inet_ntop(AF_INET6, &dest->prefix, buf, - INET6_ADDRSTRLEN), - dest->prefixlen); - } + SET_FLAG(request->flag, OSPF6_ROUTE_BLACKHOLE_ADDED); + } else { + if (IS_OSPF6_DEBUG_ZEBRA(SEND)) + zlog_debug( + "Zebra: Blackhole route present already %s/%d", + inet_ntop(AF_INET6, &dest->u.prefix6, buf, + INET6_ADDRSTRLEN), + dest->prefixlen); } } void ospf6_zebra_delete_discard(struct ospf6_route *request) { - struct zapi_ipv6 api; + struct zapi_route api; char buf[INET6_ADDRSTRLEN]; - struct prefix_ipv6 *dest; + struct prefix *dest = &request->prefix; - if (vrf_bitmap_check(zclient->redist[AFI_IP6][ZEBRA_ROUTE_OSPF6], - VRF_DEFAULT)) { - if (CHECK_FLAG(request->flag, OSPF6_ROUTE_BLACKHOLE_ADDED)) { - api.vrf_id = VRF_DEFAULT; - api.type = ZEBRA_ROUTE_OSPF6; - api.flags = ZEBRA_FLAG_BLACKHOLE; - api.instance = 0; - api.message = 0; - api.safi = SAFI_UNICAST; - SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP); - api.nexthop_num = 0; - api.ifindex_num = 0; + if (CHECK_FLAG(request->flag, OSPF6_ROUTE_BLACKHOLE_ADDED)) { + memset(&api, 0, sizeof(api)); + api.vrf_id = VRF_DEFAULT; + api.type = ZEBRA_ROUTE_OSPF6; + api.flags = ZEBRA_FLAG_BLACKHOLE; + api.safi = SAFI_UNICAST; + api.prefix = *dest; - dest = (struct prefix_ipv6 *)&request->prefix; + zclient_route_send(ZEBRA_ROUTE_DELETE, zclient, &api); - zapi_ipv6_route(ZEBRA_IPV6_ROUTE_DELETE, zclient, dest, - NULL, &api); + if (IS_OSPF6_DEBUG_ZEBRA(SEND)) + zlog_debug("Zebra: Route delete discard %s/%d", + inet_ntop(AF_INET6, &dest->u.prefix6, buf, + INET6_ADDRSTRLEN), + dest->prefixlen); - if (IS_OSPF6_DEBUG_ZEBRA(SEND)) - zlog_debug("Zebra: Route delete discard %s/%d", - inet_ntop(AF_INET6, &dest->prefix, - buf, INET6_ADDRSTRLEN), - dest->prefixlen); - UNSET_FLAG(request->flag, OSPF6_ROUTE_BLACKHOLE_ADDED); - } else { - dest = (struct prefix_ipv6 *)&request->prefix; - if (IS_OSPF6_DEBUG_ZEBRA(SEND)) - zlog_debug( - "Zebra: Blackhole route already deleted %s/%d", - inet_ntop(AF_INET6, &dest->prefix, buf, - INET6_ADDRSTRLEN), - dest->prefixlen); - } + UNSET_FLAG(request->flag, OSPF6_ROUTE_BLACKHOLE_ADDED); + } else { + if (IS_OSPF6_DEBUG_ZEBRA(SEND)) + zlog_debug( + "Zebra: Blackhole route already deleted %s/%d", + inet_ntop(AF_INET6, &dest->u.prefix6, buf, + INET6_ADDRSTRLEN), + dest->prefixlen); } } -DEFUN (redistribute_ospf6, - redistribute_ospf6_cmd, - "redistribute ospf6", - "Redistribute control\n" - "OSPF6 route\n") -{ - struct ospf6_route *route; - - if (vrf_bitmap_check(zclient->redist[AFI_IP6][ZEBRA_ROUTE_OSPF6], - VRF_DEFAULT)) - return CMD_SUCCESS; - - vrf_bitmap_set(zclient->redist[AFI_IP6][ZEBRA_ROUTE_OSPF6], - VRF_DEFAULT); - - if (ospf6 == NULL) - return CMD_SUCCESS; - - /* send ospf6 route to zebra route table */ - for (route = ospf6_route_head(ospf6->route_table); route; - route = ospf6_route_next(route)) - ospf6_zebra_route_update_add(route); - - ospf6->route_table->hook_add = ospf6_zebra_route_update_add; - ospf6->route_table->hook_remove = ospf6_zebra_route_update_remove; - - return CMD_SUCCESS; -} - -DEFUN (no_redistribute_ospf6, - no_redistribute_ospf6_cmd, - "no redistribute ospf6", - NO_STR - "Redistribute control\n" - "OSPF6 route\n") -{ - struct ospf6_route *route; - - if (!vrf_bitmap_check(zclient->redist[AFI_IP6][ZEBRA_ROUTE_OSPF6], - VRF_DEFAULT)) - return CMD_SUCCESS; - - vrf_bitmap_unset(zclient->redist[AFI_IP6][ZEBRA_ROUTE_OSPF6], - VRF_DEFAULT); - - if (ospf6 == NULL) - return CMD_SUCCESS; - - ospf6->route_table->hook_add = NULL; - ospf6->route_table->hook_remove = NULL; - - /* withdraw ospf6 route from zebra route table */ - for (route = ospf6_route_head(ospf6->route_table); route; - route = ospf6_route_next(route)) - ospf6_zebra_route_update_remove(route); - - return CMD_SUCCESS; -} - static struct ospf6_distance *ospf6_distance_new(void) { return XCALLOC(MTYPE_OSPF6_DISTANCE, sizeof(struct ospf6_distance)); @@ -785,24 +598,11 @@ void ospf6_zebra_init(struct thread_master *master) zclient->interface_address_add = ospf6_zebra_if_address_update_add; zclient->interface_address_delete = ospf6_zebra_if_address_update_delete; - zclient->redistribute_route_ipv4_add = NULL; - zclient->redistribute_route_ipv4_del = NULL; - zclient->redistribute_route_ipv6_add = ospf6_zebra_read_ipv6; - zclient->redistribute_route_ipv6_del = ospf6_zebra_read_ipv6; - - /* redistribute connected route by default */ - /* ospf6_zebra_redistribute (ZEBRA_ROUTE_CONNECT); */ - - /* Install zebra node. */ - install_node(&zebra_node, config_write_ospf6_zebra); + zclient->redistribute_route_add = ospf6_zebra_read_route; + zclient->redistribute_route_del = ospf6_zebra_read_route; /* Install command element for zebra node. */ install_element(VIEW_NODE, &show_ospf6_zebra_cmd); - install_default(ZEBRA_NODE); - install_element(ZEBRA_NODE, &redistribute_ospf6_cmd); - install_element(ZEBRA_NODE, &no_redistribute_ospf6_cmd); - - return; } /* Debug */ diff --git a/ospf6d/ospf6d.c b/ospf6d/ospf6d.c index f6b9e0ec14..84a56fb505 100644 --- a/ospf6d/ospf6d.c +++ b/ospf6d/ospf6d.c @@ -24,6 +24,7 @@ #include "linklist.h" #include "vty.h" #include "command.h" +#include "plist.h" #include "ospf6_proto.h" #include "ospf6_network.h" @@ -1139,6 +1140,20 @@ DEFUN (show_ipv6_ospf6_linkstate_detail, return CMD_SUCCESS; } +static void ospf6_plist_add(struct prefix_list *plist) +{ + if (prefix_list_afi(plist) != AFI_IP6) + return; + ospf6_area_plist_update(plist, 1); +} + +static void ospf6_plist_del(struct prefix_list *plist) +{ + if (prefix_list_afi(plist) != AFI_IP6) + return; + ospf6_area_plist_update(plist, 0); +} + /* Install ospf related commands. */ void ospf6_init(void) { @@ -1154,6 +1169,9 @@ void ospf6_init(void) ospf6_asbr_init(); ospf6_abr_init(); + prefix_list_add_hook(ospf6_plist_add); + prefix_list_delete_hook(ospf6_plist_del); + ospf6_bfd_init(); install_node(&debug_node, config_write_ospf6_debug); diff --git a/ospfd/ospf_vty.c b/ospfd/ospf_vty.c index 47c4d0078c..87aef1ea97 100644 --- a/ospfd/ospf_vty.c +++ b/ospfd/ospf_vty.c @@ -1897,7 +1897,8 @@ DEFUN (no_ospf_area_filter_list, DEFUN (ospf_area_authentication_message_digest, ospf_area_authentication_message_digest_cmd, - "area authentication message-digest", + "[no] area authentication message-digest", + NO_STR "OSPF area parameters\n" "OSPF area ID in IP address format\n" "OSPF area ID as a decimal value\n" @@ -1914,7 +1915,7 @@ DEFUN (ospf_area_authentication_message_digest, area = ospf_area_get(ospf, area_id); ospf_area_display_format_set(ospf, area, format); - area->auth_type = OSPF_AUTH_CRYPTOGRAPHIC; + area->auth_type = strmatch(argv[0]->text, "no") ? OSPF_AUTH_NULL : OSPF_AUTH_CRYPTOGRAPHIC; return CMD_SUCCESS; } @@ -6887,10 +6888,12 @@ DEFUN (no_ip_ospf_transmit_delay, DEFUN_HIDDEN (no_ospf_transmit_delay, no_ospf_transmit_delay_cmd, - "no ospf transmit-delay", + "no ospf transmit-delay [(1-65535) [A.B.C.D]]", NO_STR "OSPF interface commands\n" - "Link state transmit delay\n") + "Link state transmit delay\n" + "Seconds\n" + "Address of interface") { return no_ip_ospf_transmit_delay(self, vty, argc, argv); } diff --git a/ospfd/ospf_zebra.c b/ospfd/ospf_zebra.c index d615afc072..dcb392f1ad 100644 --- a/ospfd/ospf_zebra.c +++ b/ospfd/ospf_zebra.c @@ -333,272 +333,144 @@ static int ospf_interface_link_params(int command, struct zclient *zclient, void ospf_zebra_add(struct prefix_ipv4 *p, struct ospf_route * or) { - u_char message; + struct zapi_route api; + struct zapi_nexthop *api_nh; u_char distance; - u_int32_t flags; - int psize; - struct stream *s; struct ospf_path *path; struct listnode *node; struct ospf *ospf = ospf_lookup(); + int count = 0; - if ((ospf->instance - && redist_check_instance( - &zclient->mi_redist[AFI_IP][ZEBRA_ROUTE_OSPF], - ospf->instance)) - || vrf_bitmap_check(zclient->redist[AFI_IP][ZEBRA_ROUTE_OSPF], - VRF_DEFAULT)) { - message = 0; - flags = 0; + memset(&api, 0, sizeof(api)); + api.vrf_id = VRF_DEFAULT; + api.type = ZEBRA_ROUTE_OSPF; + api.instance = ospf->instance; + api.safi = SAFI_UNICAST; - /* OSPF pass nexthop and metric */ - SET_FLAG(message, ZAPI_MESSAGE_NEXTHOP); - SET_FLAG(message, ZAPI_MESSAGE_METRIC); + memcpy(&api.prefix, p, sizeof(*p)); + SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP); + api.nexthop_num = or->paths->count; - /* Distance value. */ - distance = ospf_distance_apply(p, or); - if (distance) - SET_FLAG(message, ZAPI_MESSAGE_DISTANCE); + /* Metric value. */ + SET_FLAG(api.message, ZAPI_MESSAGE_METRIC); + if (or->path_type == OSPF_PATH_TYPE1_EXTERNAL) + api.metric = or->cost + or->u.ext.type2_cost; + else if (or->path_type == OSPF_PATH_TYPE2_EXTERNAL) + api.metric = or->u.ext.type2_cost; + else + api.metric = or->cost; - /* Check if path type is ASE */ - if (((or->path_type == OSPF_PATH_TYPE1_EXTERNAL) - || (or->path_type == OSPF_PATH_TYPE2_EXTERNAL)) - && (or->u.ext.tag > 0) && (or->u.ext.tag <= ROUTE_TAG_MAX)) - SET_FLAG(message, ZAPI_MESSAGE_TAG); - - /* Make packet. */ - s = zclient->obuf; - stream_reset(s); - - /* Put command, type, flags, message. */ - zclient_create_header(s, ZEBRA_IPV4_ROUTE_ADD, VRF_DEFAULT); - stream_putc(s, ZEBRA_ROUTE_OSPF); - stream_putw(s, ospf->instance); - stream_putl(s, flags); - stream_putc(s, message); - stream_putw(s, SAFI_UNICAST); - - /* Put prefix information. */ - psize = PSIZE(p->prefixlen); - stream_putc(s, p->prefixlen); - stream_write(s, (u_char *)&p->prefix, psize); - - /* Nexthop count. */ - stream_putc(s, or->paths->count); - - /* Nexthop, ifindex, distance and metric information. */ - for (ALL_LIST_ELEMENTS_RO(or->paths, node, path)) { -#ifdef HAVE_NETLINK - if (path->unnumbered - || (path->nexthop.s_addr != INADDR_ANY - && path->ifindex != 0)) { - stream_putc(s, NEXTHOP_TYPE_IPV4_IFINDEX); - stream_put_in_addr(s, &path->nexthop); - stream_putl(s, path->ifindex); - } else if (path->nexthop.s_addr != INADDR_ANY) { - stream_putc(s, NEXTHOP_TYPE_IPV4); - stream_put_in_addr(s, &path->nexthop); - } else { - stream_putc(s, NEXTHOP_TYPE_IFINDEX); - if (path->ifindex) - stream_putl(s, path->ifindex); - else - stream_putl(s, 0); - } -#else /* HAVE_NETLINK */ - if (path->nexthop.s_addr != INADDR_ANY - && path->ifindex != 0) { - stream_putc(s, NEXTHOP_TYPE_IPV4_IFINDEX); - stream_put_in_addr(s, &path->nexthop); - stream_putl(s, path->ifindex); - } else if (path->nexthop.s_addr != INADDR_ANY) { - stream_putc(s, NEXTHOP_TYPE_IPV4); - stream_put_in_addr(s, &path->nexthop); - } else { - stream_putc(s, NEXTHOP_TYPE_IFINDEX); - if (path->ifindex) - stream_putl(s, path->ifindex); - else - stream_putl(s, 0); - } -#endif /* HAVE_NETLINK */ - - if (IS_DEBUG_OSPF(zebra, ZEBRA_REDISTRIBUTE)) { - char buf[2][INET_ADDRSTRLEN]; - zlog_debug( - "Zebra: Route add %s/%d nexthop %s, ifindex=%d", - inet_ntop(AF_INET, &p->prefix, buf[0], - sizeof(buf[0])), - p->prefixlen, - inet_ntop(AF_INET, &path->nexthop, - buf[1], sizeof(buf[1])), - path->ifindex); - } - } - - if (CHECK_FLAG(message, ZAPI_MESSAGE_DISTANCE)) - stream_putc(s, distance); - if (CHECK_FLAG(message, ZAPI_MESSAGE_METRIC)) { - if (or->path_type == OSPF_PATH_TYPE1_EXTERNAL) - stream_putl(s, or->cost + or->u.ext.type2_cost); - else if (or->path_type == OSPF_PATH_TYPE2_EXTERNAL) - stream_putl(s, or->u.ext.type2_cost); - else - stream_putl(s, or->cost); - } - - if (CHECK_FLAG(message, ZAPI_MESSAGE_TAG)) - stream_putl(s, or->u.ext.tag); - - stream_putw_at(s, 0, stream_get_endp(s)); - - zclient_send_message(zclient); + /* Check if path type is ASE */ + if (((or->path_type == OSPF_PATH_TYPE1_EXTERNAL) + || (or->path_type == OSPF_PATH_TYPE2_EXTERNAL)) + && (or->u.ext.tag > 0) && (or->u.ext.tag <= ROUTE_TAG_MAX)) { + SET_FLAG(api.message, ZAPI_MESSAGE_TAG); + api.tag = or->u.ext.tag; } + + /* Distance value. */ + distance = ospf_distance_apply(p, or); + if (distance) { + SET_FLAG(api.message, ZAPI_MESSAGE_DISTANCE); + api.distance = distance; + } + + /* Nexthop, ifindex, distance and metric information. */ + for (ALL_LIST_ELEMENTS_RO(or->paths, node, path)) { + api_nh = &api.nexthops[count]; +#ifdef HAVE_NETLINK + if (path->unnumbered || (path->nexthop.s_addr != INADDR_ANY + && path->ifindex != 0)) { +#else /* HAVE_NETLINK */ + if (path->nexthop.s_addr != INADDR_ANY && path->ifindex != 0) { +#endif /* HAVE_NETLINK */ + api_nh->gate.ipv4 = path->nexthop; + api_nh->ifindex = path->ifindex; + api_nh->type = NEXTHOP_TYPE_IPV4_IFINDEX; + } else if (path->nexthop.s_addr != INADDR_ANY) { + api_nh->gate.ipv4 = path->nexthop; + api_nh->type = NEXTHOP_TYPE_IPV4; + } else { + api_nh->ifindex = path->ifindex; + api_nh->type = NEXTHOP_TYPE_IFINDEX; + } + count++; + + if (IS_DEBUG_OSPF(zebra, ZEBRA_REDISTRIBUTE)) { + char buf[2][INET_ADDRSTRLEN]; + zlog_debug( + "Zebra: Route add %s/%d nexthop %s, ifindex=%d", + inet_ntop(AF_INET, &p->prefix, buf[0], + sizeof(buf[0])), + p->prefixlen, inet_ntop(AF_INET, &path->nexthop, + buf[1], sizeof(buf[1])), + path->ifindex); + } + } + + zclient_route_send(ZEBRA_ROUTE_ADD, zclient, &api); } void ospf_zebra_delete(struct prefix_ipv4 *p, struct ospf_route * or) { - u_char message; - u_char distance; - u_int32_t flags; - int psize; - struct stream *s; - struct ospf_path *path; - struct listnode *node; + struct zapi_route api; struct ospf *ospf = ospf_lookup(); - if ((ospf->instance - && redist_check_instance( - &zclient->mi_redist[AFI_IP][ZEBRA_ROUTE_OSPF], - ospf->instance)) - || vrf_bitmap_check(zclient->redist[AFI_IP][ZEBRA_ROUTE_OSPF], - VRF_DEFAULT)) { - message = 0; - flags = 0; - /* Distance value. */ - distance = ospf_distance_apply(p, or); - /* Make packet. */ - s = zclient->obuf; - stream_reset(s); + memset(&api, 0, sizeof(api)); + api.vrf_id = VRF_DEFAULT; + api.type = ZEBRA_ROUTE_OSPF; + api.instance = ospf->instance; + api.safi = SAFI_UNICAST; + memcpy(&api.prefix, p, sizeof(*p)); - /* Put command, type, flags, message. */ - zclient_create_header(s, ZEBRA_IPV4_ROUTE_DELETE, VRF_DEFAULT); - stream_putc(s, ZEBRA_ROUTE_OSPF); - stream_putw(s, ospf->instance); - stream_putl(s, flags); - stream_putc(s, message); - stream_putw(s, SAFI_UNICAST); - - /* Put prefix information. */ - psize = PSIZE(p->prefixlen); - stream_putc(s, p->prefixlen); - stream_write(s, (u_char *)&p->prefix, psize); - - /* Nexthop count. */ - stream_putc(s, or->paths->count); - - /* Nexthop, ifindex, distance and metric information. */ - for (ALL_LIST_ELEMENTS_RO(or->paths, node, path)) { - if (path->nexthop.s_addr != INADDR_ANY - && path->ifindex != 0) { - stream_putc(s, NEXTHOP_TYPE_IPV4_IFINDEX); - stream_put_in_addr(s, &path->nexthop); - stream_putl(s, path->ifindex); - } else if (path->nexthop.s_addr != INADDR_ANY) { - stream_putc(s, NEXTHOP_TYPE_IPV4); - stream_put_in_addr(s, &path->nexthop); - } else { - stream_putc(s, NEXTHOP_TYPE_IFINDEX); - stream_putl(s, path->ifindex); - } - - if (IS_DEBUG_OSPF(zebra, ZEBRA_REDISTRIBUTE)) { - char buf[2][INET_ADDRSTRLEN]; - zlog_debug( - "Zebra: Route delete %s/%d nexthop %s", - inet_ntop(AF_INET, &p->prefix, buf[0], - sizeof(buf[0])), - p->prefixlen, - inet_ntop(AF_INET, &path->nexthop, - buf[1], sizeof(buf[1]))); - } - } - - if (CHECK_FLAG(message, ZAPI_MESSAGE_DISTANCE)) - stream_putc(s, distance); - if (CHECK_FLAG(message, ZAPI_MESSAGE_METRIC)) { - if (or->path_type == OSPF_PATH_TYPE1_EXTERNAL) - stream_putl(s, or->cost + or->u.ext.type2_cost); - else if (or->path_type == OSPF_PATH_TYPE2_EXTERNAL) - stream_putl(s, or->u.ext.type2_cost); - else - stream_putl(s, or->cost); - } - - stream_putw_at(s, 0, stream_get_endp(s)); - - zclient_send_message(zclient); + if (IS_DEBUG_OSPF(zebra, ZEBRA_REDISTRIBUTE)) { + char buf[INET_ADDRSTRLEN]; + zlog_debug("Zebra: Route delete %s/%d", + inet_ntop(AF_INET, &p->prefix, buf, sizeof(buf[0])), + p->prefixlen); } + + zclient_route_send(ZEBRA_ROUTE_DELETE, zclient, &api); } void ospf_zebra_add_discard(struct prefix_ipv4 *p) { - struct zapi_ipv4 api; + struct zapi_route api; struct ospf *ospf = ospf_lookup(); - if ((ospf->instance - && redist_check_instance( - &zclient->mi_redist[AFI_IP][ZEBRA_ROUTE_OSPF], - ospf->instance)) - || vrf_bitmap_check(zclient->redist[AFI_IP][ZEBRA_ROUTE_OSPF], - VRF_DEFAULT)) { - api.vrf_id = VRF_DEFAULT; - api.type = ZEBRA_ROUTE_OSPF; - api.instance = ospf->instance; - api.flags = ZEBRA_FLAG_BLACKHOLE; - api.message = 0; - api.safi = SAFI_UNICAST; - SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP); - api.nexthop_num = 0; - api.ifindex_num = 0; - api.tag = 0; + memset(&api, 0, sizeof(api)); + api.vrf_id = VRF_DEFAULT; + api.type = ZEBRA_ROUTE_OSPF; + api.instance = ospf->instance; + api.flags = ZEBRA_FLAG_BLACKHOLE; + api.safi = SAFI_UNICAST; + memcpy(&api.prefix, p, sizeof(*p)); - zapi_ipv4_route(ZEBRA_IPV4_ROUTE_ADD, zclient, p, &api); + zclient_route_send(ZEBRA_ROUTE_ADD, zclient, &api); - if (IS_DEBUG_OSPF(zebra, ZEBRA_REDISTRIBUTE)) - zlog_debug("Zebra: Route add discard %s/%d", - inet_ntoa(p->prefix), p->prefixlen); - } + if (IS_DEBUG_OSPF(zebra, ZEBRA_REDISTRIBUTE)) + zlog_debug("Zebra: Route add discard %s/%d", + inet_ntoa(p->prefix), p->prefixlen); } void ospf_zebra_delete_discard(struct prefix_ipv4 *p) { - struct zapi_ipv4 api; + struct zapi_route api; struct ospf *ospf = ospf_lookup(); - if ((ospf->instance - && redist_check_instance( - &zclient->mi_redist[AFI_IP][ZEBRA_ROUTE_OSPF], - ospf->instance)) - || vrf_bitmap_check(zclient->redist[AFI_IP][ZEBRA_ROUTE_OSPF], - VRF_DEFAULT)) { - api.vrf_id = VRF_DEFAULT; - api.type = ZEBRA_ROUTE_OSPF; - api.instance = ospf->instance; - api.flags = ZEBRA_FLAG_BLACKHOLE; - api.message = 0; - api.safi = SAFI_UNICAST; - SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP); - api.nexthop_num = 0; - api.ifindex_num = 0; - api.tag = 0; + memset(&api, 0, sizeof(api)); + api.vrf_id = VRF_DEFAULT; + api.type = ZEBRA_ROUTE_OSPF; + api.instance = ospf->instance; + api.flags = ZEBRA_FLAG_BLACKHOLE; + api.safi = SAFI_UNICAST; + memcpy(&api.prefix, p, sizeof(*p)); - zapi_ipv4_route(ZEBRA_IPV4_ROUTE_DELETE, zclient, p, &api); + zclient_route_send(ZEBRA_ROUTE_DELETE, zclient, &api); - if (IS_DEBUG_OSPF(zebra, ZEBRA_REDISTRIBUTE)) - zlog_debug("Zebra: Route delete discard %s/%d", - inet_ntoa(p->prefix), p->prefixlen); - } + if (IS_DEBUG_OSPF(zebra, ZEBRA_REDISTRIBUTE)) + zlog_debug("Zebra: Route delete discard %s/%d", + inet_ntoa(p->prefix), p->prefixlen); } struct ospf_external *ospf_external_lookup(u_char type, u_short instance) @@ -1001,61 +873,32 @@ void ospf_routemap_unset(struct ospf_redist *red) } /* Zebra route add and delete treatment. */ -static int ospf_zebra_read_ipv4(int command, struct zclient *zclient, - zebra_size_t length, vrf_id_t vrf_id) +static int ospf_zebra_read_route(int command, struct zclient *zclient, + zebra_size_t length, vrf_id_t vrf_id) { - struct stream *s; - struct zapi_ipv4 api; + struct zapi_route api; + struct prefix_ipv4 p; unsigned long ifindex; struct in_addr nexthop; - struct prefix_ipv4 p; struct external_info *ei; struct ospf *ospf; int i; - s = zclient->ibuf; - ifindex = 0; - nexthop.s_addr = 0; - - /* Type, flags, message. */ - api.type = stream_getc(s); - api.instance = stream_getw(s); - api.flags = stream_getl(s); - api.message = stream_getc(s); - - /* IPv4 prefix. */ - memset(&p, 0, sizeof(struct prefix_ipv4)); - p.family = AF_INET; - p.prefixlen = MIN(IPV4_MAX_PREFIXLEN, stream_getc(s)); - stream_get(&p.prefix, s, PSIZE(p.prefixlen)); - - if (IPV4_NET127(ntohl(p.prefix.s_addr))) - return 0; - - /* Nexthop, ifindex, distance, metric. */ - if (CHECK_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP)) { - api.nexthop_num = stream_getc(s); - nexthop.s_addr = stream_get_ipv4(s); - } - if (CHECK_FLAG(api.message, ZAPI_MESSAGE_IFINDEX)) { - api.ifindex_num = stream_getc(s); - /* XXX assert(api.ifindex_num == 1); */ - ifindex = stream_getl(s); - } - if (CHECK_FLAG(api.message, ZAPI_MESSAGE_DISTANCE)) - api.distance = stream_getc(s); - if (CHECK_FLAG(api.message, ZAPI_MESSAGE_METRIC)) - api.metric = stream_getl(s); - if (CHECK_FLAG(api.message, ZAPI_MESSAGE_TAG)) - api.tag = stream_getl(s); - else - api.tag = 0; - ospf = ospf_lookup(); if (ospf == NULL) return 0; - if (command == ZEBRA_REDISTRIBUTE_IPV4_ADD) { + if (zapi_route_decode(zclient->ibuf, &api) < 0) + return -1; + + ifindex = api.nexthops[0].ifindex; + nexthop = api.nexthops[0].gate.ipv4; + + memcpy(&p, &api.prefix, sizeof(p)); + if (IPV4_NET127(ntohl(p.prefix.s_addr))) + return 0; + + if (command == ZEBRA_REDISTRIBUTE_ROUTE_ADD) { /* XXX|HACK|TODO|FIXME: * Maybe we should ignore reject/blackhole routes? Testing shows * that @@ -1070,7 +913,7 @@ static int ospf_zebra_read_ipv4(int command, struct zclient *zclient, * return 0; */ - /* Protocol tag overwrites all other tag value send by zebra */ + /* Protocol tag overwrites all other tag value sent by zebra */ if (ospf->dtag[api.type] > 0) api.tag = ospf->dtag[api.type]; @@ -1112,7 +955,7 @@ static int ospf_zebra_read_ipv4(int command, struct zclient *zclient, zebra, ZEBRA_REDISTRIBUTE)) zlog_debug( - "ospf_zebra_read_ipv4() : %s refreshing LSA", + "ospf_zebra_read_route() : %s refreshing LSA", inet_ntoa( p.prefix)); ospf_external_lsa_refresh( @@ -1122,7 +965,7 @@ static int ospf_zebra_read_ipv4(int command, struct zclient *zclient, } } } - } else /* if (command == ZEBRA_REDISTRIBUTE_IPV4_DEL) */ + } else /* if (command == ZEBRA_REDISTRIBUTE_ROUTE_DEL) */ { ospf_external_info_delete(api.type, api.instance, p); if (is_prefix_default(&p)) @@ -1538,8 +1381,8 @@ void ospf_zebra_init(struct thread_master *master, u_short instance) zclient->interface_address_delete = ospf_interface_address_delete; zclient->interface_link_params = ospf_interface_link_params; - zclient->redistribute_route_ipv4_add = ospf_zebra_read_ipv4; - zclient->redistribute_route_ipv4_del = ospf_zebra_read_ipv4; + zclient->redistribute_route_add = ospf_zebra_read_route; + zclient->redistribute_route_del = ospf_zebra_read_route; access_list_add_hook(ospf_filter_update); access_list_delete_hook(ospf_filter_update); diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index 9c79fd87e2..ae509f4a9b 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -1666,7 +1666,7 @@ static void pim_show_join_helper(struct vty *vty, json_row); } else { vty_out(vty, - "%-9s %-15s %-15s %-15s %-6s %8s %-6s %5s\n", + "%-9s %-15s %-15s %-15s %-10s %8s %-6s %5s\n", ch->interface->name, inet_ntoa(ifaddr), ch_src_str, ch_grp_str, pim_ifchannel_ifjoin_name(ch->ifjoin_state, @@ -1690,7 +1690,7 @@ static void pim_show_join(struct pim_instance *pim, struct vty *vty, u_char uj) json = json_object_new_object(); else vty_out(vty, - "Interface Address Source Group State Uptime Expire Prune\n"); + "Interface Address Source Group State Uptime Expire Prune\n"); for (ALL_LIST_ELEMENTS_RO(vrf_iflist(pim->vrf_id), if_node, ifp)) { pim_ifp = ifp->info; diff --git a/pimd/pim_ifchannel.c b/pimd/pim_ifchannel.c index 39f5f2cc4b..b5d6f04948 100644 --- a/pimd/pim_ifchannel.c +++ b/pimd/pim_ifchannel.c @@ -42,6 +42,7 @@ #include "pim_oil.h" #include "pim_upstream.h" #include "pim_ssm.h" +#include "pim_rp.h" RB_GENERATE(pim_ifchannel_rb, pim_ifchannel, pim_ifp_rb, pim_ifchannel_compare); @@ -348,7 +349,7 @@ const char *pim_ifchannel_ifjoin_name(enum pim_ifjoin_state ifjoin_state, switch (ifjoin_state) { case PIM_IFJOIN_NOINFO: if (PIM_IF_FLAG_TEST_S_G_RPT(flags)) - return "SGRpt"; + return "SGRpt(NI)"; else return "NOINFO"; break; @@ -356,16 +357,28 @@ const char *pim_ifchannel_ifjoin_name(enum pim_ifjoin_state ifjoin_state, return "JOIN"; break; case PIM_IFJOIN_PRUNE: - return "PRUNE"; + if (PIM_IF_FLAG_TEST_S_G_RPT(flags)) + return "SGRpt(P)"; + else + return "PRUNE"; break; case PIM_IFJOIN_PRUNE_PENDING: - return "PRUNEP"; + if (PIM_IF_FLAG_TEST_S_G_RPT(flags)) + return "SGRpt(PP)"; + else + return "PRUNEP"; break; case PIM_IFJOIN_PRUNE_TMP: - return "PRUNET"; + if (PIM_IF_FLAG_TEST_S_G_RPT(flags)) + return "SGRpt(P')"; + else + return "PRUNET"; break; case PIM_IFJOIN_PRUNE_PENDING_TMP: - return "PRUNEPT"; + if (PIM_IF_FLAG_TEST_S_G_RPT(flags)) + return "SGRpt(PP')"; + else + return "PRUNEPT"; break; } @@ -628,33 +641,34 @@ static int on_ifjoin_prune_pending_timer(struct thread *t) ch = THREAD_ARG(t); if (ch->ifjoin_state == PIM_IFJOIN_PRUNE_PENDING) { - /* Send PruneEcho(S,G) ? */ ifp = ch->interface; pim_ifp = ifp->info; - send_prune_echo = (listcount(pim_ifp->pim_neighbor_list) > 1); + if (!PIM_IF_FLAG_TEST_S_G_RPT(ch->flags)) { + /* Send PruneEcho(S,G) ? */ + send_prune_echo = + (listcount(pim_ifp->pim_neighbor_list) > 1); - if (send_prune_echo) { - struct pim_rpf rpf; + if (send_prune_echo) { + struct pim_rpf rpf; - rpf.source_nexthop.interface = ifp; - rpf.rpf_addr.u.prefix4 = pim_ifp->primary_address; - pim_jp_agg_single_upstream_send(&rpf, ch->upstream, 0); - } - /* If SGRpt flag is set on ifchannel, Trigger SGRpt - message on RP path upon prune timer expiry. - */ - if (PIM_IF_FLAG_TEST_S_G_RPT(ch->flags)) { + rpf.source_nexthop.interface = ifp; + rpf.rpf_addr.u.prefix4 = + pim_ifp->primary_address; + pim_jp_agg_single_upstream_send(&rpf, + ch->upstream, + 0); + } + + ifjoin_to_noinfo(ch, true); + } else { + /* If SGRpt flag is set on ifchannel, Trigger SGRpt + * message on RP path upon prune timer expiry. + */ + ch->ifjoin_state = PIM_IFJOIN_PRUNE; if (ch->upstream) pim_upstream_update_join_desired(pim_ifp->pim, ch->upstream); - /* - ch->ifjoin_state transition to NOINFO state - ch_del is set to 0 for not deleteing from here. - Holdtime expiry (ch_del set to 1) delete the entry. - */ - ifjoin_to_noinfo(ch, false); - } else - ifjoin_to_noinfo(ch, true); + } /* from here ch may have been deleted */ } else { zlog_warn( @@ -1104,7 +1118,6 @@ void pim_ifchannel_local_membership_del(struct interface *ifp, orig = ch = pim_ifchannel_find(ifp, sg); if (!ch) return; - ifmembership_set(ch, PIM_IFMEMBERSHIP_NOINFO); if (sg->src.s_addr == INADDR_ANY) { @@ -1311,11 +1324,12 @@ void pim_ifchannel_scan_forward_start(struct interface *new_ifp) * we get End of Message */ void pim_ifchannel_set_star_g_join_state(struct pim_ifchannel *ch, int eom, - uint8_t source_flags, uint8_t join, - uint8_t starg_alone) + uint8_t join) { struct pim_ifchannel *child; struct listnode *ch_node; + struct pim_instance *pim = + ((struct pim_interface *)ch->interface->info)->pim; if (PIM_DEBUG_PIM_TRACE) zlog_debug( @@ -1326,33 +1340,6 @@ void pim_ifchannel_set_star_g_join_state(struct pim_ifchannel *ch, int eom, return; for (ALL_LIST_ELEMENTS_RO(ch->sources, ch_node, child)) { - /* Only *,G Join received and no (SG-RPT) prune. - eom = 1, only (W,G) join_alone is true, WC and RPT are set. - Scan all S,G associated to G and if any SG-RPT - remove the SG-RPT flag. - */ - if (eom && starg_alone && (source_flags & PIM_RPT_BIT_MASK) - && (source_flags & PIM_WILDCARD_BIT_MASK)) { - if (PIM_IF_FLAG_TEST_S_G_RPT(child->flags)) { - struct pim_upstream *up = child->upstream; - - PIM_IF_FLAG_UNSET_S_G_RPT(child->flags); - if (up) { - if (PIM_DEBUG_TRACE) - zlog_debug( - "%s: SGRpt flag is cleared, add inherit oif to up %s", - __PRETTY_FUNCTION__, - up->sg_str); - pim_channel_add_oif( - up->channel_oil, ch->interface, - PIM_OIF_FLAG_PROTO_STAR); - pim_ifchannel_ifjoin_switch( - __PRETTY_FUNCTION__, child, - PIM_IFJOIN_JOIN); - } - } - } - if (!PIM_IF_FLAG_TEST_S_G_RPT(child->flags)) continue; @@ -1371,8 +1358,30 @@ void pim_ifchannel_set_star_g_join_state(struct pim_ifchannel *ch, int eom, break; case PIM_IFJOIN_PRUNE_TMP: case PIM_IFJOIN_PRUNE_PENDING_TMP: - if (eom) + if (eom) { + struct pim_upstream *parent = + child->upstream->parent; + + PIM_IF_FLAG_UNSET_S_G_RPT(child->flags); child->ifjoin_state = PIM_IFJOIN_NOINFO; + + if (I_am_RP(pim, child->sg.grp)) { + pim_channel_add_oif( + child->upstream->channel_oil, + ch->interface, + PIM_OIF_FLAG_PROTO_STAR); + pim_upstream_switch( + pim, child->upstream, + PIM_UPSTREAM_JOINED); + pim_jp_agg_single_upstream_send( + &child->upstream->rpf, + child->upstream, true); + } + if (parent) + pim_jp_agg_single_upstream_send( + &parent->rpf, + parent, true); + } break; } } diff --git a/pimd/pim_ifchannel.h b/pimd/pim_ifchannel.h index cef431c30d..0b1a8ea0e8 100644 --- a/pimd/pim_ifchannel.h +++ b/pimd/pim_ifchannel.h @@ -151,8 +151,7 @@ void pim_ifchannel_update_assert_tracking_desired(struct pim_ifchannel *ch); void pim_ifchannel_scan_forward_start(struct interface *new_ifp); void pim_ifchannel_set_star_g_join_state(struct pim_ifchannel *ch, int eom, - uint8_t source_flags, uint8_t join, - uint8_t starg_alone); + uint8_t join); int pim_ifchannel_compare(const struct pim_ifchannel *ch1, const struct pim_ifchannel *ch2); diff --git a/pimd/pim_join.c b/pimd/pim_join.c index c60e5a65aa..4f5e534010 100644 --- a/pimd/pim_join.c +++ b/pimd/pim_join.c @@ -231,7 +231,6 @@ int pim_joinprune_recv(struct interface *ifp, struct pim_neighbor *neigh, uint16_t msg_num_pruned_sources; int source; struct pim_ifchannel *starg_ch = NULL, *sg_ch = NULL; - uint8_t starg_alone = 0; memset(&sg, 0, sizeof(struct prefix_sg)); addr_offset = pim_parse_addr_group(&sg, buf, pastend - buf); @@ -289,12 +288,10 @@ int pim_joinprune_recv(struct interface *ifp, struct pim_neighbor *neigh, msg_source_flags); if (sg.src.s_addr == INADDR_ANY) { - starg_alone = 1; starg_ch = pim_ifchannel_find(ifp, &sg); if (starg_ch) pim_ifchannel_set_star_g_join_state( - starg_ch, 0, msg_source_flags, - 1, starg_alone); + starg_ch, 0, 1); } } @@ -307,7 +304,6 @@ int pim_joinprune_recv(struct interface *ifp, struct pim_neighbor *neigh, } buf += addr_offset; - starg_alone = 0; recv_prune(ifp, neigh, msg_holdtime, msg_upstream_addr.u.prefix4, &sg, msg_source_flags); @@ -340,8 +336,7 @@ int pim_joinprune_recv(struct interface *ifp, struct pim_neighbor *neigh, } } if (starg_ch) - pim_ifchannel_set_star_g_join_state( - starg_ch, 1, msg_source_flags, 0, starg_alone); + pim_ifchannel_set_star_g_join_state(starg_ch, 1, 0); starg_ch = NULL; } /* scan groups */ @@ -419,7 +414,7 @@ int pim_joinprune_send(struct pim_rpf *rpf, struct list *groups) struct pim_jp_agg_group *group; struct pim_interface *pim_ifp = NULL; struct pim_jp_groups *grp = NULL; - struct pim_jp *msg; + struct pim_jp *msg = NULL; struct listnode *node, *nnode; uint8_t pim_msg[10000]; uint8_t *curr_ptr = pim_msg; diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c index 1fc952fdf8..96b9568c61 100644 --- a/pimd/pim_upstream.c +++ b/pimd/pim_upstream.c @@ -1624,8 +1624,9 @@ static void pim_upstream_sg_running(void *arg) // No packet can have arrived here if this is the case if (!up->channel_oil->installed) { if (PIM_DEBUG_TRACE) - zlog_debug("%s: %s is not installed in mroute", - __PRETTY_FUNCTION__, up->sg_str); + zlog_debug("%s: %s[%s] is not installed in mroute", + __PRETTY_FUNCTION__, + up->sg_str, pim->vrf->name); return; } diff --git a/python/clidef.py b/python/clidef.py index 8e3c7595b7..6a69986323 100644 --- a/python/clidef.py +++ b/python/clidef.py @@ -36,12 +36,14 @@ class RenderHandler(object): deref = '' drop_str = False + canfail = True class StringHandler(RenderHandler): argtype = 'const char *' decl = Template('const char *$varname = NULL;') code = Template('$varname = argv[_i]->arg;') drop_str = True + canfail = False class LongHandler(RenderHandler): argtype = 'long' @@ -130,6 +132,10 @@ handlers = { } # core template invoked for each occurence of DEFPY. +# +# the "#if $..." bits are there to keep this template unified into one +# common form, without requiring a more advanced template engine (e.g. +# jinja2) templ = Template('''/* $fnname => "$cmddef" */ DEFUN_CMD_FUNC_DECL($fnname) #define funcdecl_$fnname static int ${fnname}_magic(\\ @@ -140,20 +146,31 @@ DEFUN_CMD_FUNC_DECL($fnname) funcdecl_$fnname; DEFUN_CMD_FUNC_TEXT($fnname) { +#if $nonempty /* anything to parse? */ int _i; +#if $canfail /* anything that can fail? */ unsigned _fail = 0, _failcnt = 0; +#endif $argdecls for (_i = 0; _i < argc; _i++) { if (!argv[_i]->varname) continue; - _fail = 0;$argblocks +#if $canfail /* anything that can fail? */ + _fail = 0; +#endif +$argblocks +#if $canfail /* anything that can fail? */ if (_fail) vty_out (vty, "%% invalid input for %s: %s\\n", argv[_i]->varname, argv[_i]->arg); _failcnt += _fail; +#endif } +#if $canfail /* anything that can fail? */ if (_failcnt) return CMD_WARNING; +#endif +#endif return ${fnname}_magic(self, vty, argc, argv$arglist); } @@ -196,6 +213,7 @@ def process_file(fn, ofd, dumpfd, all_defun): arglist = [] argblocks = [] doc = [] + canfail = 0 def do_add(handler, varname, attr = ''): argdefs.append(',\\\n\t%s %s%s' % (handler.argtype, varname, attr)) @@ -213,6 +231,8 @@ def process_file(fn, ofd, dumpfd, all_defun): if handler is None: continue do_add(handler, varname) code = handler.code.substitute({'varname': varname}).replace('\n', '\n\t\t\t') + if handler.canfail: + canfail = 1 strblock = '' if not handler.drop_str: do_add(StringHandler(None), '%s_str' % (varname), ' __attribute__ ((unused))') @@ -229,6 +249,8 @@ def process_file(fn, ofd, dumpfd, all_defun): params['argdecls'] = ''.join(argdecls) params['arglist'] = ''.join(arglist) params['argblocks'] = ''.join(argblocks) + params['canfail'] = canfail + params['nonempty'] = len(argblocks) ofd.write(templ.substitute(params)) if __name__ == '__main__': @@ -257,4 +279,4 @@ if __name__ == '__main__': process_file(args.cfile, ofd, dumpfd, args.all_defun) if args.o is not None: - clippy.wrdiff(args.o, ofd) + clippy.wrdiff(args.o, ofd, [args.cfile, os.path.realpath(__file__)]) diff --git a/python/clippy/__init__.py b/python/clippy/__init__.py index 82aa9495d4..41aeae6b4d 100644 --- a/python/clippy/__init__.py +++ b/python/clippy/__init__.py @@ -16,6 +16,7 @@ # with this program; see the file COPYING; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +import os, stat import _clippy from _clippy import parse, Graph, GraphNode @@ -47,7 +48,7 @@ def dump(graph): for i, depth in graph_iterate(graph): print('\t%s%s %r' % (' ' * (depth * 2), i.type, i.text)) -def wrdiff(filename, buf): +def wrdiff(filename, buf, reffiles = []): '''write buffer to file if contents changed''' expl = '' @@ -57,8 +58,16 @@ def wrdiff(filename, buf): try: old = open(filename, 'r').read() except: pass if old == buf: + for reffile in reffiles: + # ensure output timestamp is newer than inputs, for make + reftime = os.stat(reffile)[stat.ST_MTIME] + outtime = os.stat(filename)[stat.ST_MTIME] + if outtime <= reftime: + os.utime(filename, (reftime + 1, reftime + 1)) # sys.stderr.write('%s unchanged, not written\n' % (filename)) return - with open('.new.' + filename, 'w') as out: + + newname = '%s.new-%d' % (filename, os.getpid()) + with open(newname, 'w') as out: out.write(buf) - os.rename('.new.' + filename, filename) + os.rename(newname, filename) diff --git a/ripd/rip_zebra.c b/ripd/rip_zebra.c index 961a846db2..2140e8b110 100644 --- a/ripd/rip_zebra.c +++ b/ripd/rip_zebra.c @@ -39,155 +39,107 @@ struct zclient *zclient = NULL; /* Send ECMP routes to zebra. */ static void rip_zebra_ipv4_send(struct route_node *rp, u_char cmd) { - static struct in_addr **nexthops = NULL; - static unsigned int nexthops_len = 0; - struct list *list = (struct list *)rp->info; - struct zapi_ipv4 api; + struct zapi_route api; + struct zapi_nexthop *api_nh; struct listnode *listnode = NULL; struct rip_info *rinfo = NULL; int count = 0; - if (vrf_bitmap_check(zclient->redist[AFI_IP][ZEBRA_ROUTE_RIP], - VRF_DEFAULT)) { - api.vrf_id = VRF_DEFAULT; - api.type = ZEBRA_ROUTE_RIP; - api.instance = 0; - api.flags = 0; - api.message = 0; - api.safi = SAFI_UNICAST; + memset(&api, 0, sizeof(api)); + api.vrf_id = VRF_DEFAULT; + api.type = ZEBRA_ROUTE_RIP; + api.safi = SAFI_UNICAST; - if (nexthops_len < listcount(list)) { - nexthops_len = listcount(list); - nexthops = XREALLOC(MTYPE_TMP, nexthops, - nexthops_len - * sizeof(struct in_addr *)); - } - - SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP); - for (ALL_LIST_ELEMENTS_RO(list, listnode, rinfo)) { - nexthops[count++] = &rinfo->nexthop; - if (cmd == ZEBRA_IPV4_ROUTE_ADD) - SET_FLAG(rinfo->flags, RIP_RTF_FIB); - else - UNSET_FLAG(rinfo->flags, RIP_RTF_FIB); - } - - api.nexthop = nexthops; - api.nexthop_num = count; - api.ifindex_num = 0; - - rinfo = listgetdata(listhead(list)); - - SET_FLAG(api.message, ZAPI_MESSAGE_METRIC); - api.metric = rinfo->metric; - - if (rinfo->distance - && rinfo->distance != ZEBRA_RIP_DISTANCE_DEFAULT) { - SET_FLAG(api.message, ZAPI_MESSAGE_DISTANCE); - api.distance = rinfo->distance; - } - - if (rinfo->tag) { - SET_FLAG(api.message, ZAPI_MESSAGE_TAG); - api.tag = rinfo->tag; - } - - zapi_ipv4_route(cmd, zclient, (struct prefix_ipv4 *)&rp->p, - &api); - - if (IS_RIP_DEBUG_ZEBRA) { - if (rip->ecmp) - zlog_debug("%s: %s/%d nexthops %d", - (cmd == ZEBRA_IPV4_ROUTE_ADD) - ? "Install into zebra" - : "Delete from zebra", - inet_ntoa(rp->p.u.prefix4), - rp->p.prefixlen, count); - else - zlog_debug("%s: %s/%d", - (cmd == ZEBRA_IPV4_ROUTE_ADD) - ? "Install into zebra" - : "Delete from zebra", - inet_ntoa(rp->p.u.prefix4), - rp->p.prefixlen); - } - - rip_global_route_changes++; + SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP); + for (ALL_LIST_ELEMENTS_RO(list, listnode, rinfo)) { + api_nh = &api.nexthops[count]; + api_nh->gate.ipv4 = rinfo->nexthop; + api_nh->type = NEXTHOP_TYPE_IPV4; + if (cmd == ZEBRA_ROUTE_ADD) + SET_FLAG(rinfo->flags, RIP_RTF_FIB); + else + UNSET_FLAG(rinfo->flags, RIP_RTF_FIB); + count++; } + + api.prefix = rp->p; + api.nexthop_num = count; + + rinfo = listgetdata(listhead(list)); + + SET_FLAG(api.message, ZAPI_MESSAGE_METRIC); + api.metric = rinfo->metric; + + if (rinfo->distance && rinfo->distance != ZEBRA_RIP_DISTANCE_DEFAULT) { + SET_FLAG(api.message, ZAPI_MESSAGE_DISTANCE); + api.distance = rinfo->distance; + } + + if (rinfo->tag) { + SET_FLAG(api.message, ZAPI_MESSAGE_TAG); + api.tag = rinfo->tag; + } + + zclient_route_send(cmd, zclient, &api); + + if (IS_RIP_DEBUG_ZEBRA) { + if (rip->ecmp) + zlog_debug("%s: %s/%d nexthops %d", + (cmd == ZEBRA_ROUTE_ADD) + ? "Install into zebra" + : "Delete from zebra", + inet_ntoa(rp->p.u.prefix4), rp->p.prefixlen, + count); + else + zlog_debug("%s: %s/%d", + (cmd == ZEBRA_ROUTE_ADD) + ? "Install into zebra" + : "Delete from zebra", + inet_ntoa(rp->p.u.prefix4), rp->p.prefixlen); + } + + rip_global_route_changes++; } /* Add/update ECMP routes to zebra. */ void rip_zebra_ipv4_add(struct route_node *rp) { - rip_zebra_ipv4_send(rp, ZEBRA_IPV4_ROUTE_ADD); + rip_zebra_ipv4_send(rp, ZEBRA_ROUTE_ADD); } /* Delete ECMP routes from zebra. */ void rip_zebra_ipv4_delete(struct route_node *rp) { - rip_zebra_ipv4_send(rp, ZEBRA_IPV4_ROUTE_DELETE); + rip_zebra_ipv4_send(rp, ZEBRA_ROUTE_DELETE); } /* Zebra route add and delete treatment. */ -static int rip_zebra_read_ipv4(int command, struct zclient *zclient, - zebra_size_t length, vrf_id_t vrf_id) +static int rip_zebra_read_route(int command, struct zclient *zclient, + zebra_size_t length, vrf_id_t vrf_id) { - struct stream *s; - struct zapi_ipv4 api; - unsigned long ifindex; + struct zapi_route api; struct in_addr nexthop; - struct prefix_ipv4 p; + unsigned long ifindex; if (!rip) return 0; - s = zclient->ibuf; - ifindex = 0; - nexthop.s_addr = 0; + if (zapi_route_decode(zclient->ibuf, &api) < 0) + return -1; - /* Type, flags, message. */ - api.type = stream_getc(s); - api.instance = stream_getw(s); - api.flags = stream_getl(s); - api.message = stream_getc(s); - - /* IPv4 prefix. */ - memset(&p, 0, sizeof(struct prefix_ipv4)); - p.family = AF_INET; - p.prefixlen = MIN(IPV4_MAX_PREFIXLEN, stream_getc(s)); - stream_get(&p.prefix, s, PSIZE(p.prefixlen)); - - /* Nexthop, ifindex, distance, metric. */ - if (CHECK_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP)) { - api.nexthop_num = stream_getc(s); - nexthop.s_addr = stream_get_ipv4(s); - } - if (CHECK_FLAG(api.message, ZAPI_MESSAGE_IFINDEX)) { - api.ifindex_num = stream_getc(s); - ifindex = stream_getl(s); - } - if (CHECK_FLAG(api.message, ZAPI_MESSAGE_DISTANCE)) - api.distance = stream_getc(s); - else - api.distance = 255; - if (CHECK_FLAG(api.message, ZAPI_MESSAGE_METRIC)) - api.metric = stream_getl(s); - else - api.metric = 0; - - if (CHECK_FLAG(api.message, ZAPI_MESSAGE_TAG)) - api.tag = stream_getl(s); - else - api.tag = 0; + nexthop = api.nexthops[0].gate.ipv4; + ifindex = api.nexthops[0].ifindex; /* Then fetch IPv4 prefixes. */ - if (command == ZEBRA_REDISTRIBUTE_IPV4_ADD) - rip_redistribute_add(api.type, RIP_ROUTE_REDISTRIBUTE, &p, - ifindex, &nexthop, api.metric, - api.distance, api.tag); - else if (command == ZEBRA_REDISTRIBUTE_IPV4_DEL) - rip_redistribute_delete(api.type, RIP_ROUTE_REDISTRIBUTE, &p, + if (command == ZEBRA_REDISTRIBUTE_ROUTE_ADD) + rip_redistribute_add(api.type, RIP_ROUTE_REDISTRIBUTE, + (struct prefix_ipv4 *)&api.prefix, ifindex, + &nexthop, api.metric, api.distance, + api.tag); + else if (command == ZEBRA_REDISTRIBUTE_ROUTE_DEL) + rip_redistribute_delete(api.type, RIP_ROUTE_REDISTRIBUTE, + (struct prefix_ipv4 *)&api.prefix, ifindex); return 0; @@ -298,27 +250,6 @@ void rip_redistribute_clean(void) } } -DEFUN (rip_redistribute_rip, - rip_redistribute_rip_cmd, - "redistribute rip", - "Redistribute information from another routing protocol\n" - "Routing Information Protocol (RIP)\n") -{ - vrf_bitmap_set(zclient->redist[AFI_IP][ZEBRA_ROUTE_RIP], VRF_DEFAULT); - return CMD_SUCCESS; -} - -DEFUN (no_rip_redistribute_rip, - no_rip_redistribute_rip_cmd, - "no redistribute rip", - NO_STR - "Redistribute information from another routing protocol\n" - "Routing Information Protocol (RIP)\n") -{ - vrf_bitmap_unset(zclient->redist[AFI_IP][ZEBRA_ROUTE_RIP], VRF_DEFAULT); - return CMD_SUCCESS; -} - DEFUN (rip_redistribute_type, rip_redistribute_type_cmd, "redistribute " FRR_REDIST_STR_RIPD, @@ -604,66 +535,46 @@ DEFUN (no_rip_default_information_originate, return CMD_SUCCESS; } -/* RIP configuration write function. */ -static int config_write_zebra(struct vty *vty) -{ - if (!zclient->enable) { - vty_out(vty, "no router zebra\n"); - return 1; - } else if (!vrf_bitmap_check(zclient->redist[AFI_IP][ZEBRA_ROUTE_RIP], - VRF_DEFAULT)) { - vty_out(vty, "router zebra\n"); - vty_out(vty, " no redistribute rip\n"); - return 1; - } - return 0; -} - int config_write_rip_redistribute(struct vty *vty, int config_mode) { int i; - for (i = 0; i < ZEBRA_ROUTE_MAX; i++) - if (i != zclient->redist_default - && vrf_bitmap_check(zclient->redist[AFI_IP][i], - VRF_DEFAULT)) { - if (config_mode) { - if (rip->route_map[i].metric_config) { - if (rip->route_map[i].name) - vty_out(vty, - " redistribute %s metric %d route-map %s\n", - zebra_route_string(i), - rip->route_map[i] - .metric, - rip->route_map[i].name); - else - vty_out(vty, - " redistribute %s metric %d\n", - zebra_route_string(i), - rip->route_map[i] - .metric); - } else { - if (rip->route_map[i].name) - vty_out(vty, - " redistribute %s route-map %s\n", - zebra_route_string(i), - rip->route_map[i].name); - else - vty_out(vty, - " redistribute %s\n", - zebra_route_string(i)); - } - } else - vty_out(vty, " %s", zebra_route_string(i)); + for (i = 0; i < ZEBRA_ROUTE_MAX; i++) { + if (i == zclient->redist_default + || !vrf_bitmap_check(zclient->redist[AFI_IP][i], + VRF_DEFAULT)) + continue; + + if (!config_mode) { + vty_out(vty, " %s", zebra_route_string(i)); + continue; } + + if (rip->route_map[i].metric_config) { + if (rip->route_map[i].name) + vty_out(vty, + " redistribute %s metric %d route-map %s\n", + zebra_route_string(i), + rip->route_map[i].metric, + rip->route_map[i].name); + else + vty_out(vty, " redistribute %s metric %d\n", + zebra_route_string(i), + rip->route_map[i].metric); + } else { + if (rip->route_map[i].name) + vty_out(vty, " redistribute %s route-map %s\n", + zebra_route_string(i), + rip->route_map[i].name); + else + vty_out(vty, " redistribute %s\n", + zebra_route_string(i)); + } + } + return 0; } -/* Zebra node structure. */ -static struct cmd_node zebra_node = { - ZEBRA_NODE, "%s(config-router)# ", -}; - static void rip_zebra_connected(struct zclient *zclient) { zclient_send_reg_requests(zclient, VRF_DEFAULT); @@ -681,16 +592,8 @@ void rip_zclient_init(struct thread_master *master) zclient->interface_address_delete = rip_interface_address_delete; zclient->interface_up = rip_interface_up; zclient->interface_down = rip_interface_down; - zclient->redistribute_route_ipv4_add = rip_zebra_read_ipv4; - zclient->redistribute_route_ipv4_del = rip_zebra_read_ipv4; - - /* Install zebra node. */ - install_node(&zebra_node, config_write_zebra); - - /* Install command elements to zebra node. */ - install_default(ZEBRA_NODE); - install_element(ZEBRA_NODE, &rip_redistribute_rip_cmd); - install_element(ZEBRA_NODE, &no_rip_redistribute_rip_cmd); + zclient->redistribute_route_add = rip_zebra_read_route; + zclient->redistribute_route_del = rip_zebra_read_route; /* Install command elements to rip node. */ install_element(RIP_NODE, &rip_redistribute_type_cmd); diff --git a/ripngd/ripng_zebra.c b/ripngd/ripng_zebra.c index 386bee43b8..283d8691a3 100644 --- a/ripngd/ripng_zebra.c +++ b/ripngd/ripng_zebra.c @@ -39,162 +39,101 @@ struct zclient *zclient = NULL; /* Send ECMP routes to zebra. */ static void ripng_zebra_ipv6_send(struct route_node *rp, u_char cmd) { - static struct in6_addr **nexthops = NULL; - static ifindex_t *ifindexes = NULL; - static unsigned int nexthops_len = 0; - struct list *list = (struct list *)rp->info; - struct zapi_ipv6 api; + struct zapi_route api; + struct zapi_nexthop *api_nh; struct listnode *listnode = NULL; struct ripng_info *rinfo = NULL; int count = 0; - if (vrf_bitmap_check(zclient->redist[AFI_IP6][ZEBRA_ROUTE_RIPNG], - VRF_DEFAULT)) { - api.vrf_id = VRF_DEFAULT; - api.type = ZEBRA_ROUTE_RIPNG; - api.instance = 0; - api.flags = 0; - api.message = 0; - api.safi = SAFI_UNICAST; + memset(&api, 0, sizeof(api)); + api.vrf_id = VRF_DEFAULT; + api.type = ZEBRA_ROUTE_RIPNG; + api.safi = SAFI_UNICAST; + api.prefix = rp->p; - if (nexthops_len < listcount(list)) { - nexthops_len = listcount(list); - nexthops = XREALLOC( - MTYPE_TMP, nexthops, - nexthops_len * sizeof(struct in6_addr *)); - ifindexes = - XREALLOC(MTYPE_TMP, ifindexes, - nexthops_len * sizeof(unsigned int)); - } + SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP); + for (ALL_LIST_ELEMENTS_RO(list, listnode, rinfo)) { + api_nh = &api.nexthops[count]; + api_nh->gate.ipv6 = rinfo->nexthop; + api_nh->ifindex = rinfo->ifindex; + api_nh->type = NEXTHOP_TYPE_IPV6_IFINDEX; + count++; + if (cmd == ZEBRA_ROUTE_ADD) + SET_FLAG(rinfo->flags, RIPNG_RTF_FIB); + else + UNSET_FLAG(rinfo->flags, RIPNG_RTF_FIB); + } - SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP); - SET_FLAG(api.message, ZAPI_MESSAGE_IFINDEX); - for (ALL_LIST_ELEMENTS_RO(list, listnode, rinfo)) { - nexthops[count] = &rinfo->nexthop; - ifindexes[count] = rinfo->ifindex; - count++; - if (cmd == ZEBRA_IPV6_ROUTE_ADD) - SET_FLAG(rinfo->flags, RIPNG_RTF_FIB); - else - UNSET_FLAG(rinfo->flags, RIPNG_RTF_FIB); - } + api.nexthop_num = count; - api.nexthop = nexthops; - api.nexthop_num = count; - api.ifindex = ifindexes; - api.ifindex_num = count; + rinfo = listgetdata(listhead(list)); - rinfo = listgetdata(listhead(list)); + SET_FLAG(api.message, ZAPI_MESSAGE_METRIC); + api.metric = rinfo->metric; - SET_FLAG(api.message, ZAPI_MESSAGE_METRIC); - api.metric = rinfo->metric; + if (rinfo->tag) { + SET_FLAG(api.message, ZAPI_MESSAGE_TAG); + api.tag = rinfo->tag; + } - if (rinfo->tag) { - SET_FLAG(api.message, ZAPI_MESSAGE_TAG); - api.tag = rinfo->tag; - } + zclient_route_send(cmd, zclient, &api); - zapi_ipv6_route(cmd, zclient, (struct prefix_ipv6 *)&rp->p, - NULL, &api); - - if (IS_RIPNG_DEBUG_ZEBRA) { - if (ripng->ecmp) - zlog_debug("%s: %s/%d nexthops %d", - (cmd == ZEBRA_IPV6_ROUTE_ADD) - ? "Install into zebra" - : "Delete from zebra", - inet6_ntoa(rp->p.u.prefix6), - rp->p.prefixlen, count); - else - zlog_debug("%s: %s/%d", - (cmd == ZEBRA_IPV6_ROUTE_ADD) - ? "Install into zebra" - : "Delete from zebra", - inet6_ntoa(rp->p.u.prefix6), - rp->p.prefixlen); - } + if (IS_RIPNG_DEBUG_ZEBRA) { + if (ripng->ecmp) + zlog_debug("%s: %s/%d nexthops %d", + (cmd == ZEBRA_ROUTE_ADD) + ? "Install into zebra" + : "Delete from zebra", + inet6_ntoa(rp->p.u.prefix6), rp->p.prefixlen, + count); + else + zlog_debug( + "%s: %s/%d", + (cmd == ZEBRA_ROUTE_ADD) ? "Install into zebra" + : "Delete from zebra", + inet6_ntoa(rp->p.u.prefix6), rp->p.prefixlen); } } /* Add/update ECMP routes to zebra. */ void ripng_zebra_ipv6_add(struct route_node *rp) { - ripng_zebra_ipv6_send(rp, ZEBRA_IPV6_ROUTE_ADD); + ripng_zebra_ipv6_send(rp, ZEBRA_ROUTE_ADD); } /* Delete ECMP routes from zebra. */ void ripng_zebra_ipv6_delete(struct route_node *rp) { - ripng_zebra_ipv6_send(rp, ZEBRA_IPV6_ROUTE_DELETE); + ripng_zebra_ipv6_send(rp, ZEBRA_ROUTE_DELETE); } /* Zebra route add and delete treatment. */ -static int ripng_zebra_read_ipv6(int command, struct zclient *zclient, - zebra_size_t length, vrf_id_t vrf_id) +static int ripng_zebra_read_route(int command, struct zclient *zclient, + zebra_size_t length, vrf_id_t vrf_id) { - struct stream *s; - struct zapi_ipv6 api; - unsigned long ifindex; + struct zapi_route api; struct in6_addr nexthop; - struct prefix_ipv6 p, src_p; + unsigned long ifindex; - s = zclient->ibuf; - ifindex = 0; - memset(&nexthop, 0, sizeof(struct in6_addr)); + if (zapi_route_decode(zclient->ibuf, &api) < 0) + return -1; - /* Type, flags, message. */ - api.type = stream_getc(s); - api.instance = stream_getw(s); - api.flags = stream_getl(s); - api.message = stream_getc(s); - - /* IPv6 prefix. */ - memset(&p, 0, sizeof(struct prefix_ipv6)); - p.family = AF_INET6; - p.prefixlen = MIN(IPV6_MAX_PREFIXLEN, stream_getc(s)); - stream_get(&p.prefix, s, PSIZE(p.prefixlen)); - - memset(&src_p, 0, sizeof(struct prefix_ipv6)); - src_p.family = AF_INET6; - if (CHECK_FLAG(api.message, ZAPI_MESSAGE_SRCPFX)) { - src_p.prefixlen = stream_getc(s); - stream_get(&src_p.prefix, s, PSIZE(src_p.prefixlen)); - } - - if (src_p.prefixlen) - /* we completely ignore srcdest routes for now. */ + /* we completely ignore srcdest routes for now. */ + if (CHECK_FLAG(api.message, ZAPI_MESSAGE_SRCPFX)) return 0; - /* Nexthop, ifindex, distance, metric. */ - if (CHECK_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP)) { - api.nexthop_num = stream_getc(s); - stream_get(&nexthop, s, 16); - } - if (CHECK_FLAG(api.message, ZAPI_MESSAGE_IFINDEX)) { - api.ifindex_num = stream_getc(s); - ifindex = stream_getl(s); - } - if (CHECK_FLAG(api.message, ZAPI_MESSAGE_DISTANCE)) - api.distance = stream_getc(s); - else - api.distance = 0; - if (CHECK_FLAG(api.message, ZAPI_MESSAGE_METRIC)) - api.metric = stream_getl(s); - else - api.metric = 0; + nexthop = api.nexthops[0].gate.ipv6; + ifindex = api.nexthops[0].ifindex; - if (CHECK_FLAG(api.message, ZAPI_MESSAGE_TAG)) - api.tag = stream_getl(s); - else - api.tag = 0; - - if (command == ZEBRA_REDISTRIBUTE_IPV6_ADD) - ripng_redistribute_add(api.type, RIPNG_ROUTE_REDISTRIBUTE, &p, + if (command == ZEBRA_REDISTRIBUTE_ROUTE_ADD) + ripng_redistribute_add(api.type, RIPNG_ROUTE_REDISTRIBUTE, + (struct prefix_ipv6 *)&api.prefix, ifindex, &nexthop, api.tag); else ripng_redistribute_delete(api.type, RIPNG_ROUTE_REDISTRIBUTE, - &p, ifindex); + (struct prefix_ipv6 *)&api.prefix, + ifindex); return 0; } @@ -294,29 +233,6 @@ void ripng_redistribute_clean() } } -DEFUN (ripng_redistribute_ripng, - ripng_redistribute_ripng_cmd, - "redistribute ripng", - "Redistribute information from another routing protocol\n" - "RIPng route\n") -{ - vrf_bitmap_set(zclient->redist[AFI_IP6][ZEBRA_ROUTE_RIPNG], - VRF_DEFAULT); - return CMD_SUCCESS; -} - -DEFUN (no_ripng_redistribute_ripng, - no_ripng_redistribute_ripng_cmd, - "no redistribute ripng", - NO_STR - "Redistribute information from another routing protocol\n" - "RIPng route\n") -{ - vrf_bitmap_unset(zclient->redist[AFI_IP6][ZEBRA_ROUTE_RIPNG], - VRF_DEFAULT); - return CMD_SUCCESS; -} - DEFUN (ripng_redistribute_type, ripng_redistribute_type_cmd, "redistribute " FRR_REDIST_STR_RIPNGD, @@ -452,64 +368,40 @@ void ripng_redistribute_write(struct vty *vty, int config_mode) { int i; - for (i = 0; i < ZEBRA_ROUTE_MAX; i++) - if (i != zclient->redist_default - && vrf_bitmap_check(zclient->redist[AFI_IP6][i], - VRF_DEFAULT)) { - if (config_mode) { - if (ripng->route_map[i].metric_config) { - if (ripng->route_map[i].name) - vty_out(vty, - " redistribute %s metric %d route-map %s\n", - zebra_route_string(i), - ripng->route_map[i] - .metric, - ripng->route_map[i] - .name); - else - vty_out(vty, - " redistribute %s metric %d\n", - zebra_route_string(i), - ripng->route_map[i] - .metric); - } else { - if (ripng->route_map[i].name) - vty_out(vty, - " redistribute %s route-map %s\n", - zebra_route_string(i), - ripng->route_map[i] - .name); - else - vty_out(vty, - " redistribute %s\n", - zebra_route_string(i)); - } - } else - vty_out(vty, " %s", zebra_route_string(i)); + for (i = 0; i < ZEBRA_ROUTE_MAX; i++) { + if (i == zclient->redist_default + || !vrf_bitmap_check(zclient->redist[AFI_IP6][i], + VRF_DEFAULT)) + continue; + + if (!config_mode) { + vty_out(vty, " %s", zebra_route_string(i)); + continue; } -} -/* RIPng configuration write function. */ -static int zebra_config_write(struct vty *vty) -{ - if (!zclient->enable) { - vty_out(vty, "no router zebra\n"); - return 1; - } else if (!vrf_bitmap_check( - zclient->redist[AFI_IP6][ZEBRA_ROUTE_RIPNG], - VRF_DEFAULT)) { - vty_out(vty, "router zebra\n"); - vty_out(vty, " no redistribute ripng\n"); - return 1; + if (ripng->route_map[i].metric_config) { + if (ripng->route_map[i].name) + vty_out(vty, + " redistribute %s metric %d route-map %s\n", + zebra_route_string(i), + ripng->route_map[i].metric, + ripng->route_map[i].name); + else + vty_out(vty, " redistribute %s metric %d\n", + zebra_route_string(i), + ripng->route_map[i].metric); + } else { + if (ripng->route_map[i].name) + vty_out(vty, " redistribute %s route-map %s\n", + zebra_route_string(i), + ripng->route_map[i].name); + else + vty_out(vty, " redistribute %s\n", + zebra_route_string(i)); + } } - return 0; } -/* Zebra node structure. */ -static struct cmd_node zebra_node = { - ZEBRA_NODE, "%s(config-router)# ", -}; - static void ripng_zebra_connected(struct zclient *zclient) { zclient_send_reg_requests(zclient, VRF_DEFAULT); @@ -529,16 +421,8 @@ void zebra_init(struct thread_master *master) zclient->interface_delete = ripng_interface_delete; zclient->interface_address_add = ripng_interface_address_add; zclient->interface_address_delete = ripng_interface_address_delete; - zclient->redistribute_route_ipv6_add = ripng_zebra_read_ipv6; - zclient->redistribute_route_ipv6_del = ripng_zebra_read_ipv6; - - /* Install zebra node. */ - install_node(&zebra_node, zebra_config_write); - - /* Install command element for zebra node. */ - install_default(ZEBRA_NODE); - install_element(ZEBRA_NODE, &ripng_redistribute_ripng_cmd); - install_element(ZEBRA_NODE, &no_ripng_redistribute_ripng_cmd); + zclient->redistribute_route_add = ripng_zebra_read_route; + zclient->redistribute_route_del = ripng_zebra_read_route; /* Install command elements to ripng node */ install_element(RIPNG_NODE, &ripng_redistribute_type_cmd); diff --git a/tests/isisd/test_fuzz_isis_tlv.c b/tests/isisd/test_fuzz_isis_tlv.c index 6727e663f5..e61e9639ee 100644 --- a/tests/isisd/test_fuzz_isis_tlv.c +++ b/tests/isisd/test_fuzz_isis_tlv.c @@ -23,7 +23,7 @@ static bool atexit_registered; static void show_meminfo_at_exit(void) { - log_memstats_stderr("isis fuzztest"); + log_memstats(stderr, "isis fuzztest"); } static int comp_line(const void *p1, const void *p2) diff --git a/tests/lib/cli/common_cli.c b/tests/lib/cli/common_cli.c index 77f1610fe2..0fd2f80a39 100644 --- a/tests/lib/cli/common_cli.c +++ b/tests/lib/cli/common_cli.c @@ -53,7 +53,7 @@ static void vty_do_exit(int isexit) thread_master_free(master); closezlog(); - log_memstats_stderr("testcli"); + log_memstats(stderr, "testcli"); if (!isexit) exit(0); } diff --git a/zebra/kernel_socket.c b/zebra/kernel_socket.c index 84d01bca6f..e2a1deb9ac 100644 --- a/zebra/kernel_socket.c +++ b/zebra/kernel_socket.c @@ -88,13 +88,10 @@ extern struct zebra_privs_t zserv_privs; #if !defined(ROUNDUP) /* - * It's a bug for a platform not to define rounding/alignment for - * sockaddrs on the routing socket. This warning really is - * intentional, to provoke filing bug reports with operating systems - * that don't define RT_ROUNDUP or equivalent. + * If you're porting to a platform that changed RT_ROUNDUP but doesn't + * have it in its headers, this will break rather obviously and you'll + * have to fix it here. */ -#warning \ - "net/route.h does not define RT_ROUNDUP; making unwarranted assumptions!" /* OS X (Xcode as of 2014-12) is known not to define RT_ROUNDUP */ #ifdef __APPLE__ diff --git a/zebra/redistribute.c b/zebra/redistribute.c index ed27dc3e83..9b21eb4d8c 100644 --- a/zebra/redistribute.c +++ b/zebra/redistribute.c @@ -95,8 +95,8 @@ static void zebra_redistribute_default(struct zserv *client, vrf_id_t vrf_id) RNODE_FOREACH_RE(rn, newre) if (CHECK_FLAG(newre->flags, ZEBRA_FLAG_SELECTED) && newre->distance != DISTANCE_INFINITY) - zsend_redistribute_route(1, client, &rn->p, NULL, - newre); + zsend_redistribute_route(ZEBRA_REDISTRIBUTE_ROUTE_ADD, + client, &rn->p, NULL, newre); route_unlock_node(rn); } @@ -114,7 +114,7 @@ static void zebra_redistribute(struct zserv *client, int type, u_short instance, if (!table) return; - for (rn = route_top(table); rn; rn = route_next(rn)) + for (rn = route_top(table); rn; rn = srcdest_route_next(rn)) RNODE_FOREACH_RE(rn, newre) { struct prefix *dst_p, *src_p; @@ -141,8 +141,8 @@ static void zebra_redistribute(struct zserv *client, int type, u_short instance, if (!zebra_check_addr(dst_p)) continue; - zsend_redistribute_route(1, client, dst_p, src_p, - newre); + zsend_redistribute_route(ZEBRA_REDISTRIBUTE_ROUTE_ADD, + client, dst_p, src_p, newre); } } @@ -191,7 +191,8 @@ void redistribute_update(struct prefix *p, struct prefix *src_p, send_redistribute = 1; if (send_redistribute) { - zsend_redistribute_route(1, client, p, src_p, re); + zsend_redistribute_route(ZEBRA_REDISTRIBUTE_ROUTE_ADD, + client, p, src_p, re); } else if (prev_re && ((re->instance && redist_check_instance( @@ -201,7 +202,8 @@ void redistribute_update(struct prefix *p, struct prefix *src_p, || vrf_bitmap_check( client->redist[afi][prev_re->type], re->vrf_id))) { - zsend_redistribute_route(0, client, p, src_p, prev_re); + zsend_redistribute_route(ZEBRA_REDISTRIBUTE_ROUTE_DEL, + client, p, src_p, prev_re); } } } @@ -242,7 +244,8 @@ void redistribute_delete(struct prefix *p, struct prefix *src_p, re->instance)) || vrf_bitmap_check(client->redist[afi][re->type], re->vrf_id)) { - zsend_redistribute_route(0, client, p, src_p, re); + zsend_redistribute_route(ZEBRA_REDISTRIBUTE_ROUTE_DEL, + client, p, src_p, re); } } } diff --git a/zebra/rt_socket.c b/zebra/rt_socket.c index 4e4d726b46..32ae41b917 100644 --- a/zebra/rt_socket.c +++ b/zebra/rt_socket.c @@ -71,6 +71,27 @@ static int sin_masklen(struct in_addr mask) } #endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */ +#ifdef __OpenBSD__ +static int kernel_rtm_add_labels(struct nexthop_label *nh_label, + struct sockaddr_mpls *smpls) +{ + if (nh_label->num_labels > 1) { + zlog_warn( + "%s: can't push %u labels at " + "once (maximum is 1)", + __func__, nh_label->num_labels); + return -1; + } + + memset(smpls, 0, sizeof(*smpls)); + smpls->smpls_len = sizeof(*smpls); + smpls->smpls_family = AF_MPLS; + smpls->smpls_label = htonl(nh_label->label[0] << MPLS_LABEL_OFFSET); + + return 0; +} +#endif + /* Interface between zebra message and rtm message. */ static int kernel_rtm_ipv4(int cmd, struct prefix *p, struct route_entry *re) @@ -150,15 +171,11 @@ static int kernel_rtm_ipv4(int cmd, struct prefix *p, struct route_entry *re) } #ifdef __OpenBSD__ - if (nexthop->nh_label) { - memset(&smpls, 0, sizeof(smpls)); - smpls.smpls_len = sizeof(smpls); - smpls.smpls_family = AF_MPLS; - smpls.smpls_label = - htonl(nexthop->nh_label->label[0] - << MPLS_LABEL_OFFSET); - smplsp = (union sockunion *)&smpls; - } + if (nexthop->nh_label + && !kernel_rtm_add_labels(nexthop->nh_label, + &smpls)) + continue; + smplsp = (union sockunion *)&smpls; #endif error = rtm_write( @@ -266,6 +283,10 @@ static int kernel_rtm_ipv6(int cmd, struct prefix *p, struct route_entry *re) { struct sockaddr_in6 *mask; struct sockaddr_in6 sin_dest, sin_mask, sin_gate; +#ifdef __OpenBSD__ + struct sockaddr_mpls smpls; +#endif + union sockunion *smplsp = NULL; struct nexthop *nexthop; int nexthop_num = 0; ifindex_t ifindex = 0; @@ -338,10 +359,17 @@ static int kernel_rtm_ipv6(int cmd, struct prefix *p, struct route_entry *re) mask = &sin_mask; } +#ifdef __OpenBSD__ + if (nexthop->nh_label + && !kernel_rtm_add_labels(nexthop->nh_label, &smpls)) + continue; + smplsp = (union sockunion *)&smpls; +#endif + error = rtm_write(cmd, (union sockunion *)&sin_dest, (union sockunion *)mask, gate ? (union sockunion *)&sin_gate : NULL, - NULL, ifindex, re->flags, re->metric); + smplsp, ifindex, re->flags, re->metric); #if 0 if (error) diff --git a/zebra/zebra_fpm.c b/zebra/zebra_fpm.c index b88bce9e82..8c0700ac8b 100644 --- a/zebra/zebra_fpm.c +++ b/zebra/zebra_fpm.c @@ -1589,8 +1589,10 @@ static int fpm_remote_srv_write(struct vty *vty) in.s_addr = zfpm_g->fpm_server; - if (zfpm_g->fpm_server != FPM_DEFAULT_IP - || zfpm_g->fpm_port != FPM_DEFAULT_PORT) + if ((zfpm_g->fpm_server != FPM_DEFAULT_IP + && zfpm_g->fpm_server != INADDR_ANY) + || (zfpm_g->fpm_port != FPM_DEFAULT_PORT + && zfpm_g->fpm_port != 0)) vty_out(vty, "fpm connection ip %s port %d\n", inet_ntoa(in), zfpm_g->fpm_port); diff --git a/zebra/zebra_mpls.c b/zebra/zebra_mpls.c index 47cf7a3cbf..cee3a03858 100644 --- a/zebra/zebra_mpls.c +++ b/zebra/zebra_mpls.c @@ -1671,27 +1671,20 @@ int mpls_str2label(const char *label_str, u_int8_t *num_labels, char *mpls_label2str(u_int8_t num_labels, mpls_label_t *labels, char *buf, int len, int pretty) { - char *buf_ptr = buf; + char label_buf[BUFSIZ]; + int i; + buf[0] = '\0'; - - if (pretty) { - if (num_labels == 1) { - label2str(labels[0], buf, len); - } else if (num_labels == 2) { - label2str(labels[0], buf, len); - buf_ptr += strlen(buf); - - snprintf(buf_ptr, len, "/"); - buf_ptr++; - - label2str(labels[1], buf_ptr, len); - } - } else { - if (num_labels == 1) - snprintf(buf, len, "%u", labels[0]); - else if (num_labels == 2) - snprintf(buf, len, "%u/%u", labels[0], labels[1]); + for (i = 0; i < num_labels; i++) { + if (i != 0) + strlcat(buf, "/", len); + if (pretty) + label2str(labels[i], label_buf, sizeof(label_buf)); + else + snprintf(label_buf, sizeof(label_buf), "%u", labels[i]); + strlcat(buf, label_buf, len); } + return buf; } diff --git a/zebra/zebra_mpls.h b/zebra/zebra_mpls.h index c8dab39210..c8df8670f4 100644 --- a/zebra/zebra_mpls.h +++ b/zebra/zebra_mpls.h @@ -37,8 +37,6 @@ /* Definitions and macros. */ -#define MPLS_MAX_LABELS 2 /* Maximum # labels that can be pushed. */ - #define NHLFE_FAMILY(nhlfe) \ (((nhlfe)->nexthop->type == NEXTHOP_TYPE_IPV6 \ || (nhlfe)->nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX) \ diff --git a/zebra/zebra_mpls_openbsd.c b/zebra/zebra_mpls_openbsd.c index 119cd5b700..33f0d49d4d 100644 --- a/zebra/zebra_mpls_openbsd.c +++ b/zebra/zebra_mpls_openbsd.c @@ -256,6 +256,15 @@ static int kernel_lsp_cmd(int action, zebra_lsp_t *lsp) || (action == RTM_DELETE && (CHECK_FLAG(nhlfe->flags, NHLFE_FLAG_INSTALLED) && CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB)))) { + if (nhlfe->nexthop->nh_label->num_labels > 1) { + zlog_warn( + "%s: can't push %u labels at once " + "(maximum is 1)", + __func__, + nhlfe->nexthop->nh_label->num_labels); + continue; + } + nexthop_num++; switch (NHLFE_FAMILY(nhlfe)) { diff --git a/zebra/zebra_static.h b/zebra/zebra_static.h index 6ab47094a1..ff9f0f59e7 100644 --- a/zebra/zebra_static.h +++ b/zebra/zebra_static.h @@ -22,11 +22,13 @@ #ifndef __ZEBRA_STATIC_H__ #define __ZEBRA_STATIC_H__ +#include "zebra/zebra_mpls.h" + /* Static route label information */ struct static_nh_label { u_int8_t num_labels; u_int8_t reserved[3]; - mpls_label_t label[2]; + mpls_label_t label[MPLS_MAX_LABELS]; }; typedef enum { diff --git a/zebra/zebra_vty.c b/zebra/zebra_vty.c index f01f037ed5..9f887e8401 100644 --- a/zebra/zebra_vty.c +++ b/zebra/zebra_vty.c @@ -1705,16 +1705,14 @@ static int static_config(struct vty *vty, afi_t afi, safi_t safi, inet_ntop(AF_INET, &si->addr.ipv4, buf, sizeof buf), - ifindex2ifname(si->ifindex, - si->vrf_id)); + si->ifname); break; case STATIC_IPV6_GATEWAY_IFNAME: vty_out(vty, " %s %s", inet_ntop(AF_INET6, &si->addr.ipv6, buf, sizeof buf), - ifindex2ifname(si->ifindex, - si->vrf_id)); + si->ifname); break; } diff --git a/zebra/zserv.c b/zebra/zserv.c index cd893b5670..0e0cc78bbe 100644 --- a/zebra/zserv.c +++ b/zebra/zserv.c @@ -592,193 +592,76 @@ int zsend_interface_update(int cmd, struct zserv *client, struct interface *ifp) return zebra_server_send_message(client); } -/* - * This is the new function to announce and withdraw redistributed routes, used - * by Zebra. This is the old zsend_route_multipath() function. That function - * was duplicating code to send a lot of information that was essentially thrown - * away or ignored by the receiver. This is the leaner function that is not a - * duplicate of the zapi_ipv4_route_add/del. - * - * The primary difference is that this function merely sends a single NH instead - * of - * all the nexthops. - */ -int zsend_redistribute_route(int add, struct zserv *client, struct prefix *p, +int zsend_redistribute_route(int cmd, struct zserv *client, struct prefix *p, struct prefix *src_p, struct route_entry *re) { - afi_t afi; - int cmd; - int psize; - struct stream *s; + struct zapi_route api; + struct zapi_nexthop *api_nh; struct nexthop *nexthop; - unsigned long nhnummark = 0, messmark = 0; - int nhnum = 0; - u_char zapi_flags = 0; - struct nexthop dummy_nh; + int count = 0; - afi = family2afi(p->family); - if (add) { - switch (afi) { - case AFI_IP: - cmd = ZEBRA_REDISTRIBUTE_IPV4_ADD; - client->redist_v4_add_cnt++; - break; - case AFI_IP6: - cmd = ZEBRA_REDISTRIBUTE_IPV6_ADD; - client->redist_v6_add_cnt++; - break; - default: - return -1; - } - } else { - switch (afi) { - case AFI_IP: - cmd = ZEBRA_REDISTRIBUTE_IPV4_DEL; - client->redist_v4_del_cnt++; - break; - case AFI_IP6: - cmd = ZEBRA_REDISTRIBUTE_IPV6_DEL; - client->redist_v6_del_cnt++; - break; - default: - return -1; - } - } - - s = client->obuf; - stream_reset(s); - memset(&dummy_nh, 0, sizeof(struct nexthop)); - - zserv_create_header(s, cmd, re->vrf_id); - - /* Put type and nexthop. */ - stream_putc(s, re->type); - stream_putw(s, re->instance); - stream_putl(s, re->flags); - - /* marker for message flags field */ - messmark = stream_get_endp(s); - stream_putc(s, 0); + memset(&api, 0, sizeof(api)); + api.vrf_id = VRF_DEFAULT; + api.type = re->type; + api.instance = re->instance; + api.flags = re->flags; /* Prefix. */ - psize = PSIZE(p->prefixlen); - stream_putc(s, p->prefixlen); - stream_write(s, (u_char *)&p->u.prefix, psize); - + api.prefix = *p; if (src_p) { - SET_FLAG(zapi_flags, ZAPI_MESSAGE_SRCPFX); - psize = PSIZE(src_p->prefixlen); - stream_putc(s, src_p->prefixlen); - stream_write(s, (u_char *)&src_p->u.prefix, psize); + SET_FLAG(api.message, ZAPI_MESSAGE_SRCPFX); + memcpy(&api.src_prefix, src_p, sizeof(api.src_prefix)); } + /* Nexthops. */ + if (re->nexthop_active_num) { + SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP); + api.nexthop_num = re->nexthop_active_num; + } for (nexthop = re->nexthop; nexthop; nexthop = nexthop->next) { - /* We don't send any nexthops when there's a multipath */ - if (re->nexthop_active_num > 1 - && client->proto != ZEBRA_ROUTE_LDP) { - SET_FLAG(zapi_flags, ZAPI_MESSAGE_NEXTHOP); - SET_FLAG(zapi_flags, ZAPI_MESSAGE_IFINDEX); + if (!CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE)) + continue; - stream_putc(s, 1); - if (p->family == AF_INET) { - stream_put_in_addr(s, &dummy_nh.gate.ipv4); - } else if (p->family == AF_INET6) { - stream_write(s, (u_char *)&dummy_nh.gate.ipv6, - 16); - } else { - /* We don't handle anything else now, abort */ - zlog_err( - "%s: Unable to redistribute route of unknown family, %d\n", - __func__, p->family); - return -1; - } - stream_putc(s, 1); - stream_putl(s, 0); /* dummy ifindex */ + api_nh = &api.nexthops[count]; + api_nh->type = nexthop->type; + switch (nexthop->type) { + case NEXTHOP_TYPE_BLACKHOLE: break; + case NEXTHOP_TYPE_IPV4: + api_nh->gate.ipv4 = nexthop->gate.ipv4; + break; + case NEXTHOP_TYPE_IPV4_IFINDEX: + api_nh->gate.ipv4 = nexthop->gate.ipv4; + api_nh->ifindex = nexthop->ifindex; + break; + case NEXTHOP_TYPE_IFINDEX: + api_nh->ifindex = nexthop->ifindex; + break; + case NEXTHOP_TYPE_IPV6: + api_nh->gate.ipv6 = nexthop->gate.ipv6; + break; + case NEXTHOP_TYPE_IPV6_IFINDEX: + api_nh->gate.ipv6 = nexthop->gate.ipv6; + api_nh->ifindex = nexthop->ifindex; } - - if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE)) { - SET_FLAG(zapi_flags, ZAPI_MESSAGE_NEXTHOP); - SET_FLAG(zapi_flags, ZAPI_MESSAGE_IFINDEX); - if (nhnummark == 0) { - nhnummark = stream_get_endp(s); - stream_putc(s, 1); /* placeholder */ - } - nhnum++; - - switch (nexthop->type) { - case NEXTHOP_TYPE_IPV4: - case NEXTHOP_TYPE_IPV4_IFINDEX: - stream_put_in_addr(s, &nexthop->gate.ipv4); - break; - case NEXTHOP_TYPE_IPV6: - case NEXTHOP_TYPE_IPV6_IFINDEX: - /* Only BGP supports IPv4 prefix with IPv6 NH, - * so kill this */ - if (p->family == AF_INET) - stream_put_in_addr(s, - &dummy_nh.gate.ipv4); - else - stream_write( - s, - (u_char *)&nexthop->gate.ipv6, - 16); - break; - default: - if (cmd == ZEBRA_REDISTRIBUTE_IPV4_ADD - || cmd == ZEBRA_REDISTRIBUTE_IPV4_DEL) { - struct in_addr empty; - memset(&empty, 0, - sizeof(struct in_addr)); - stream_write(s, (u_char *)&empty, - IPV4_MAX_BYTELEN); - } else { - struct in6_addr empty; - memset(&empty, 0, - sizeof(struct in6_addr)); - stream_write(s, (u_char *)&empty, - IPV6_MAX_BYTELEN); - } - } - - /* Interface index. */ - stream_putc(s, 1); - stream_putl(s, nexthop->ifindex); - - /* ldpd needs all nexthops */ - if (client->proto != ZEBRA_ROUTE_LDP) - break; - } + count++; } - /* Distance */ - SET_FLAG(zapi_flags, ZAPI_MESSAGE_DISTANCE); - stream_putc(s, re->distance); - - /* Metric */ - SET_FLAG(zapi_flags, ZAPI_MESSAGE_METRIC); - stream_putl(s, re->metric); - - /* Tag */ + /* Attributes. */ + SET_FLAG(api.message, ZAPI_MESSAGE_DISTANCE); + api.distance = re->distance; + SET_FLAG(api.message, ZAPI_MESSAGE_METRIC); + api.metric = re->metric; if (re->tag) { - SET_FLAG(zapi_flags, ZAPI_MESSAGE_TAG); - stream_putl(s, re->tag); + SET_FLAG(api.message, ZAPI_MESSAGE_TAG); + api.tag = re->tag; } + SET_FLAG(api.message, ZAPI_MESSAGE_MTU); + api.mtu = re->mtu; - /* MTU */ - SET_FLAG(zapi_flags, ZAPI_MESSAGE_MTU); - stream_putl(s, re->mtu); - - /* write real message flags value */ - stream_putc_at(s, messmark, zapi_flags); - - /* Write next-hop number */ - if (nhnummark) - stream_putc_at(s, nhnummark, nhnum); - - /* Write packet size. */ - stream_putw_at(s, 0, stream_get_endp(s)); - + /* Encode route and send. */ + if (zapi_route_encode(cmd, client->obuf, &api) < 0) + return -1; return zebra_server_send_message(client); } @@ -1157,6 +1040,145 @@ void zserv_nexthop_num_warn(const char *caller, const struct prefix *p, } } +static int zread_route_add(struct zserv *client, u_short length, + struct zebra_vrf *zvrf) +{ + struct stream *s; + struct zapi_route api; + struct zapi_nexthop *api_nh; + afi_t afi; + struct prefix_ipv6 *src_p = NULL; + struct route_entry *re; + struct nexthop *nexthop = NULL; + int i, ret; + + s = client->ibuf; + if (zapi_route_decode(s, &api) < 0) + return -1; + + /* Allocate new route. */ + re = XCALLOC(MTYPE_RE, sizeof(struct route_entry)); + re->type = api.type; + re->instance = api.instance; + re->flags = api.flags; + re->uptime = time(NULL); + re->vrf_id = zvrf_id(zvrf); + re->table = zvrf->table_id; + + if (CHECK_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP)) { + for (i = 0; i < api.nexthop_num; i++) { + api_nh = &api.nexthops[i]; + + switch (api_nh->type) { + case NEXTHOP_TYPE_IFINDEX: + route_entry_nexthop_ifindex_add( + re, api_nh->ifindex); + break; + case NEXTHOP_TYPE_IPV4: + nexthop = route_entry_nexthop_ipv4_add( + re, &api_nh->gate.ipv4, NULL); + break; + case NEXTHOP_TYPE_IPV4_IFINDEX: + nexthop = route_entry_nexthop_ipv4_ifindex_add( + re, &api_nh->gate.ipv4, NULL, + api_nh->ifindex); + break; + case NEXTHOP_TYPE_IPV6: + nexthop = route_entry_nexthop_ipv6_add( + re, &api_nh->gate.ipv6); + break; + case NEXTHOP_TYPE_IPV6_IFINDEX: + nexthop = route_entry_nexthop_ipv6_ifindex_add( + re, &api_nh->gate.ipv6, + api_nh->ifindex); + break; + case NEXTHOP_TYPE_BLACKHOLE: + route_entry_nexthop_blackhole_add(re); + break; + } + + /* MPLS labels for BGP-LU or Segment Routing */ + if (CHECK_FLAG(api.message, ZAPI_MESSAGE_LABEL) + && api_nh->type != NEXTHOP_TYPE_IFINDEX + && api_nh->type != NEXTHOP_TYPE_BLACKHOLE) { + enum lsp_types_t label_type; + + label_type = + lsp_type_from_re_type(client->proto); + nexthop_add_labels(nexthop, label_type, + api_nh->label_num, + &api_nh->labels[0]); + } + } + } + + if (CHECK_FLAG(api.message, ZAPI_MESSAGE_DISTANCE)) + re->distance = api.distance; + if (CHECK_FLAG(api.message, ZAPI_MESSAGE_METRIC)) + re->metric = api.metric; + if (CHECK_FLAG(api.message, ZAPI_MESSAGE_TAG)) + re->tag = api.tag; + if (CHECK_FLAG(api.message, ZAPI_MESSAGE_MTU)) + re->mtu = api.mtu; + + afi = family2afi(api.prefix.family); + if (CHECK_FLAG(api.message, ZAPI_MESSAGE_SRCPFX)) + src_p = &api.src_prefix; + + ret = rib_add_multipath(afi, api.safi, &api.prefix, src_p, re); + + /* Stats */ + switch (api.prefix.family) { + case AF_INET: + if (ret > 0) + client->v4_route_add_cnt++; + else if (ret < 0) + client->v4_route_upd8_cnt++; + break; + case AF_INET6: + if (ret > 0) + client->v6_route_add_cnt++; + else if (ret < 0) + client->v6_route_upd8_cnt++; + break; + } + + return 0; +} + +static int zread_route_del(struct zserv *client, u_short length, + struct zebra_vrf *zvrf) +{ + struct stream *s; + struct zapi_route api; + afi_t afi; + struct prefix_ipv6 *src_p = NULL; + + s = client->ibuf; + if (zapi_route_decode(s, &api) < 0) + return -1; + + afi = family2afi(api.prefix.family); + if (CHECK_FLAG(api.message, ZAPI_MESSAGE_SRCPFX)) + src_p = &api.src_prefix; + + rib_delete(afi, api.safi, zvrf_id(zvrf), api.type, api.instance, + api.flags, &api.prefix, src_p, NULL, 0, zvrf->table_id, + api.metric); + + /* Stats */ + switch (api.prefix.family) { + case AF_INET: + client->v4_route_del_cnt++; + break; + case AF_INET6: + client->v6_route_del_cnt++; + break; + } + + return 0; +} + /* This function support multiple nexthop. */ /* * Parse the ZEBRA_IPV4_ROUTE_ADD sent from client. Update re and @@ -1176,6 +1198,7 @@ static int zread_ipv4_add(struct zserv *client, u_short length, ifindex_t ifindex; safi_t safi; int ret; + enum lsp_types_t label_type = ZEBRA_LSP_NONE; mpls_label_t label; struct nexthop *nexthop; @@ -1208,6 +1231,9 @@ static int zread_ipv4_add(struct zserv *client, u_short length, zserv_nexthop_num_warn(__func__, (const struct prefix *)&p, nexthop_num); + if (CHECK_FLAG(message, ZAPI_MESSAGE_LABEL)) + label_type = lsp_type_from_re_type(client->proto); + for (i = 0; i < nexthop_num; i++) { nexthop_type = stream_getc(s); @@ -1224,9 +1250,8 @@ static int zread_ipv4_add(struct zserv *client, u_short length, * by label. */ if (CHECK_FLAG(message, ZAPI_MESSAGE_LABEL)) { label = (mpls_label_t)stream_getl(s); - nexthop_add_labels( - nexthop, nexthop->nh_label_type, - 1, &label); + nexthop_add_labels(nexthop, label_type, + 1, &label); } break; case NEXTHOP_TYPE_IPV4_IFINDEX: @@ -1281,21 +1306,12 @@ static int zread_ipv4_add(struct zserv *client, u_short length, static int zread_ipv4_delete(struct zserv *client, u_short length, struct zebra_vrf *zvrf) { - int i; struct stream *s; struct zapi_ipv4 api; - struct in_addr nexthop; - union g_addr *nexthop_p; - unsigned long ifindex; struct prefix p; - u_char nexthop_num; - u_char nexthop_type; u_int32_t table_id; s = client->ibuf; - ifindex = 0; - nexthop.s_addr = 0; - nexthop_p = NULL; /* Type, flags, message. */ api.type = stream_getc(s); @@ -1310,63 +1326,10 @@ static int zread_ipv4_delete(struct zserv *client, u_short length, p.prefixlen = stream_getc(s); stream_get(&p.u.prefix4, s, PSIZE(p.prefixlen)); - /* Nexthop, ifindex, distance, metric. */ - if (CHECK_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP)) { - nexthop_num = stream_getc(s); - - for (i = 0; i < nexthop_num; i++) { - nexthop_type = stream_getc(s); - - switch (nexthop_type) { - case NEXTHOP_TYPE_IFINDEX: - ifindex = stream_getl(s); - break; - case NEXTHOP_TYPE_IPV4: - nexthop.s_addr = stream_get_ipv4(s); - /* For labeled-unicast, each nexthop is followed - * by label, but - * we don't care for delete. - */ - if (CHECK_FLAG(api.message, ZAPI_MESSAGE_LABEL)) - stream_forward_getp(s, - sizeof(u_int32_t)); - nexthop_p = (union g_addr *)&nexthop; - break; - case NEXTHOP_TYPE_IPV4_IFINDEX: - nexthop.s_addr = stream_get_ipv4(s); - nexthop_p = (union g_addr *)&nexthop; - ifindex = stream_getl(s); - break; - case NEXTHOP_TYPE_IPV6: - stream_forward_getp(s, IPV6_MAX_BYTELEN); - break; - } - } - } - - /* Distance. */ - if (CHECK_FLAG(api.message, ZAPI_MESSAGE_DISTANCE)) - api.distance = stream_getc(s); - else - api.distance = 0; - - /* Metric. */ - if (CHECK_FLAG(api.message, ZAPI_MESSAGE_METRIC)) - api.metric = stream_getl(s); - else - api.metric = 0; - - /* tag */ - if (CHECK_FLAG(api.message, ZAPI_MESSAGE_TAG)) - api.tag = stream_getl(s); - else - api.tag = 0; - table_id = zvrf->table_id; rib_delete(AFI_IP, api.safi, zvrf_id(zvrf), api.type, api.instance, - api.flags, &p, NULL, nexthop_p, ifindex, table_id, - api.metric); + api.flags, &p, NULL, NULL, 0, table_id, 0); client->v4_route_del_cnt++; return 0; } @@ -1401,6 +1364,7 @@ static int zread_ipv4_route_ipv6_nexthop_add(struct zserv *client, static unsigned int ifindices[MULTIPATH_NUM]; int ret; static mpls_label_t labels[MULTIPATH_NUM]; + enum lsp_types_t label_type = ZEBRA_LSP_NONE; mpls_label_t label; struct nexthop *nexthop; @@ -1441,6 +1405,10 @@ static int zread_ipv4_route_ipv6_nexthop_add(struct zserv *client, nexthop_num = stream_getc(s); zserv_nexthop_num_warn(__func__, (const struct prefix *)&p, nexthop_num); + + if (CHECK_FLAG(message, ZAPI_MESSAGE_LABEL)) + label_type = lsp_type_from_re_type(client->proto); + for (i = 0; i < nexthop_num; i++) { nexthop_type = stream_getc(s); @@ -1485,9 +1453,8 @@ static int zread_ipv4_route_ipv6_nexthop_add(struct zserv *client, re, &nexthops[i]); if (CHECK_FLAG(message, ZAPI_MESSAGE_LABEL)) - nexthop_add_labels( - nexthop, nexthop->nh_label_type, - 1, &labels[i]); + nexthop_add_labels(nexthop, label_type, + 1, &labels[i]); } else { if ((i < if_count) && ifindices[i]) route_entry_nexthop_ifindex_add( @@ -1534,6 +1501,7 @@ static int zread_ipv6_add(struct zserv *client, u_short length, unsigned int i; struct stream *s; struct in6_addr nhop_addr; + ifindex_t ifindex; struct route_entry *re; u_char message; u_char nexthop_num; @@ -1545,6 +1513,7 @@ static int zread_ipv6_add(struct zserv *client, u_short length, static unsigned int ifindices[MULTIPATH_NUM]; int ret; static mpls_label_t labels[MULTIPATH_NUM]; + enum lsp_types_t label_type = ZEBRA_LSP_NONE; mpls_label_t label; struct nexthop *nexthop; @@ -1591,6 +1560,10 @@ static int zread_ipv6_add(struct zserv *client, u_short length, nexthop_num = stream_getc(s); zserv_nexthop_num_warn(__func__, (const struct prefix *)&p, nexthop_num); + + if (CHECK_FLAG(message, ZAPI_MESSAGE_LABEL)) + label_type = lsp_type_from_re_type(client->proto); + for (i = 0; i < nexthop_num; i++) { nexthop_type = stream_getc(s); @@ -1609,6 +1582,12 @@ static int zread_ipv6_add(struct zserv *client, u_short length, nexthops[nh_count++] = nhop_addr; } break; + case NEXTHOP_TYPE_IPV6_IFINDEX: + stream_get(&nhop_addr, s, 16); + ifindex = stream_getl(s); + route_entry_nexthop_ipv6_ifindex_add( + re, &nhop_addr, ifindex); + break; case NEXTHOP_TYPE_IFINDEX: if (if_count < multipath_num) { ifindices[if_count++] = stream_getl(s); @@ -1633,9 +1612,8 @@ static int zread_ipv6_add(struct zserv *client, u_short length, nexthop = route_entry_nexthop_ipv6_add( re, &nexthops[i]); if (CHECK_FLAG(message, ZAPI_MESSAGE_LABEL)) - nexthop_add_labels( - nexthop, nexthop->nh_label_type, - 1, &labels[i]); + nexthop_add_labels(nexthop, label_type, + 1, &labels[i]); } else { if ((i < if_count) && ifindices[i]) route_entry_nexthop_ifindex_add( @@ -1681,18 +1659,12 @@ static int zread_ipv6_add(struct zserv *client, u_short length, static int zread_ipv6_delete(struct zserv *client, u_short length, struct zebra_vrf *zvrf) { - int i; struct stream *s; struct zapi_ipv6 api; - struct in6_addr nexthop; - union g_addr *pnexthop = NULL; - unsigned long ifindex; struct prefix p; struct prefix_ipv6 src_p, *src_pp; s = client->ibuf; - ifindex = 0; - memset(&nexthop, 0, sizeof(struct in6_addr)); /* Type, flags, message. */ api.type = stream_getc(s); @@ -1716,59 +1688,8 @@ static int zread_ipv6_delete(struct zserv *client, u_short length, } else src_pp = NULL; - /* Nexthop, ifindex, distance, metric. */ - if (CHECK_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP)) { - u_char nexthop_type; - - api.nexthop_num = stream_getc(s); - for (i = 0; i < api.nexthop_num; i++) { - nexthop_type = stream_getc(s); - - switch (nexthop_type) { - case NEXTHOP_TYPE_IPV6: - stream_get(&nexthop, s, 16); - /* For labeled-unicast, each nexthop is followed - * by label, but - * we don't care for delete. - */ - if (CHECK_FLAG(api.message, ZAPI_MESSAGE_LABEL)) - stream_forward_getp(s, - sizeof(u_int32_t)); - pnexthop = (union g_addr *)&nexthop; - break; - case NEXTHOP_TYPE_IFINDEX: - ifindex = stream_getl(s); - break; - } - } - } - - /* Distance. */ - if (CHECK_FLAG(api.message, ZAPI_MESSAGE_DISTANCE)) - api.distance = stream_getc(s); - else - api.distance = 0; - - /* Metric. */ - if (CHECK_FLAG(api.message, ZAPI_MESSAGE_METRIC)) - api.metric = stream_getl(s); - else - api.metric = 0; - - /* tag */ - if (CHECK_FLAG(api.message, ZAPI_MESSAGE_TAG)) - api.tag = stream_getl(s); - else - api.tag = 0; - - if (IN6_IS_ADDR_UNSPECIFIED(&nexthop)) - rib_delete(AFI_IP6, api.safi, zvrf_id(zvrf), api.type, - api.instance, api.flags, &p, src_pp, NULL, ifindex, - client->rtm_table, api.metric); - else - rib_delete(AFI_IP6, api.safi, zvrf_id(zvrf), api.type, - api.instance, api.flags, &p, src_pp, pnexthop, - ifindex, client->rtm_table, api.metric); + rib_delete(AFI_IP6, api.safi, zvrf_id(zvrf), api.type, api.instance, + api.flags, &p, src_pp, NULL, 0, client->rtm_table, 0); client->v6_route_del_cnt++; return 0; @@ -2435,6 +2356,12 @@ static int zebra_client_read(struct thread *thread) case ZEBRA_INTERFACE_DELETE: zread_interface_delete(client, length, zvrf); break; + case ZEBRA_ROUTE_ADD: + zread_route_add(client, length, zvrf); + break; + case ZEBRA_ROUTE_DELETE: + zread_route_del(client, length, zvrf); + break; case ZEBRA_IPV4_ROUTE_ADD: zread_ipv4_add(client, length, zvrf); break; @@ -2444,14 +2371,6 @@ static int zebra_client_read(struct thread *thread) case ZEBRA_IPV4_ROUTE_IPV6_NEXTHOP_ADD: zread_ipv4_route_ipv6_nexthop_add(client, length, zvrf); break; - case ZEBRA_IPV4_NEXTHOP_ADD: - zread_ipv4_add(client, length, - zvrf); /* LB: r1.0 merge - id was 1 */ - break; - case ZEBRA_IPV4_NEXTHOP_DELETE: - zread_ipv4_delete(client, length, - zvrf); /* LB: r1.0 merge - id was 1 */ - break; case ZEBRA_IPV6_ROUTE_ADD: zread_ipv6_add(client, length, zvrf); break;