diff options
-rw-r--r-- | alpine/APKBUILD.in | 8 | ||||
-rw-r--r-- | bgpd/bgp_rd.c | 7 | ||||
-rw-r--r-- | bgpd/bgp_route.c | 31 | ||||
-rw-r--r-- | bgpd/bgp_vty.c | 22 | ||||
-rwxr-xr-x | configure.ac | 11 | ||||
-rw-r--r-- | doc/user/overview.rst | 2 | ||||
-rw-r--r-- | docker/alpine/Dockerfile | 1 | ||||
-rwxr-xr-x | docker/centos-8/build.sh | 2 | ||||
-rw-r--r-- | lib/if.c | 7 | ||||
-rw-r--r-- | lib/zclient.c | 11 | ||||
-rw-r--r-- | pimd/pim_cmd.c | 40 | ||||
-rw-r--r-- | pimd/pim_igmp.c | 6 | ||||
-rw-r--r-- | pimd/pim_instance.h | 8 | ||||
-rw-r--r-- | pimd/pim_msdp.c | 4 | ||||
-rw-r--r-- | pimd/pim_nht.c | 5 | ||||
-rw-r--r-- | pimd/pim_oil.c | 53 | ||||
-rw-r--r-- | pimd/pim_oil.h | 9 | ||||
-rw-r--r-- | pimd/pim_rp.c | 14 | ||||
-rw-r--r-- | pimd/pim_upstream.c | 68 | ||||
-rw-r--r-- | pimd/pim_upstream.h | 8 | ||||
-rw-r--r-- | pimd/pim_zebra.c | 5 | ||||
-rw-r--r-- | redhat/frr.spec.in | 2 | ||||
-rw-r--r-- | zebra/if_netlink.c | 4 | ||||
-rw-r--r-- | zebra/kernel_netlink.c | 8 | ||||
-rw-r--r-- | zebra/rt_netlink.c | 32 | ||||
-rw-r--r-- | zebra/zapi_msg.c | 49 | ||||
-rw-r--r-- | zebra/zebra_pbr.c | 13 |
27 files changed, 184 insertions, 246 deletions
diff --git a/alpine/APKBUILD.in b/alpine/APKBUILD.in index 1c579a8e7..f740a3458 100644 --- a/alpine/APKBUILD.in +++ b/alpine/APKBUILD.in @@ -17,7 +17,7 @@ makedepends="ncurses-dev net-snmp-dev gawk texinfo perl linux-headers lzip lzo m4 make mkinitfs mpc1 mpfr4 mtools musl-dev ncurses-libs ncurses-terminfo ncurses-terminfo-base patch pax-utils pcre perl pkgconf python2 python2-dev readline readline-dev sqlite-libs - squashfs-tools sudo tar texinfo xorriso xz-libs py-pip py-sphinx rtrlib + squashfs-tools sudo tar texinfo xorriso xz-libs py-pip rtrlib rtrlib-dev" checkdepends="pytest py-setuptools" install="$pkgname.pre-install $pkgname.pre-deinstall $pkgname.post-deinstall" @@ -34,6 +34,12 @@ _user=frr build() { cd "$builddir" + + _localpythondir=$PWD/.python + pip2 install --prefix $_localpythondir sphinx + export PATH=${_localpythondir}/bin:$PATH + export PYTHONPATH=${_localpythondir}/lib/python2.7/site-packages + ./configure \ --prefix=/usr \ --sbindir=$_sbindir \ diff --git a/bgpd/bgp_rd.c b/bgpd/bgp_rd.c index 571139a49..be950dfa5 100644 --- a/bgpd/bgp_rd.c +++ b/bgpd/bgp_rd.c @@ -174,15 +174,16 @@ char *prefix_rd2str(struct prefix_rd *prd, char *buf, size_t size) if (type == RD_TYPE_AS) { decode_rd_as(pnt + 2, &rd_as); - snprintf(buf, size, "%u:%d", rd_as.as, rd_as.val); + snprintf(buf, size, "%u:%" PRIu32, rd_as.as, rd_as.val); return buf; } else if (type == RD_TYPE_AS4) { decode_rd_as4(pnt + 2, &rd_as); - snprintf(buf, size, "%u:%d", rd_as.as, rd_as.val); + snprintf(buf, size, "%u:%" PRIu32, rd_as.as, rd_as.val); return buf; } else if (type == RD_TYPE_IP) { decode_rd_ip(pnt + 2, &rd_ip); - snprintf(buf, size, "%s:%d", inet_ntoa(rd_ip.ip), rd_ip.val); + snprintf(buf, size, "%s:%" PRIu16, inet_ntoa(rd_ip.ip), + rd_ip.val); return buf; } #if ENABLE_BGP_VNC diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index 64d7ce9e9..21d737fb3 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -9147,7 +9147,8 @@ 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, struct bgp *bgp, const char *regstr, - afi_t afi, safi_t safi, enum bgp_show_type type); + afi_t afi, safi_t safi, enum bgp_show_type type, + bool use_json); static int bgp_show_community(struct vty *vty, struct bgp *bgp, const char *comstr, int exact, afi_t afi, safi_t safi, bool use_json); @@ -9438,7 +9439,8 @@ static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi, vty_out(vty, ",\"%s\": ", buf2); } vty_out(vty, "%s", - json_object_to_json_string(json_paths)); + json_object_to_json_string_ext( + json_paths, JSON_C_TO_STRING_PRETTY)); json_object_free(json_paths); json_paths = NULL; first = 0; @@ -10464,7 +10466,7 @@ DEFUN (show_ip_bgp_route, DEFUN (show_ip_bgp_regexp, show_ip_bgp_regexp_cmd, - "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] regexp REGEX...", + "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] regexp REGEX [json]", SHOW_STR IP_STR BGP_STR @@ -10472,11 +10474,14 @@ DEFUN (show_ip_bgp_regexp, BGP_AFI_HELP_STR BGP_SAFI_WITH_LABEL_HELP_STR "Display routes matching the AS path regular expression\n" - "A regular-expression (1234567890_^|[,{}() ]$*+.?-\\) to match the BGP AS paths\n") + "A regular-expression (1234567890_^|[,{}() ]$*+.?-\\) to match the BGP AS paths\n" + JSON_STR) { afi_t afi = AFI_IP6; safi_t safi = SAFI_UNICAST; struct bgp *bgp = NULL; + bool uj = use_json(argc, argv); + char *regstr = NULL; int idx = 0; bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi, @@ -10485,14 +10490,11 @@ DEFUN (show_ip_bgp_regexp, return CMD_WARNING; // get index of regex - argv_find(argv, argc, "regexp", &idx); - idx++; + if (argv_find(argv, argc, "REGEX", &idx)) + regstr = argv[idx]->arg; - char *regstr = argv_concat(argv, argc, idx); - int rc = bgp_show_regexp(vty, bgp, (const char *)regstr, afi, safi, - bgp_show_type_regexp); - XFREE(MTYPE_TMP, regstr); - return rc; + return bgp_show_regexp(vty, bgp, (const char *)regstr, afi, safi, + bgp_show_type_regexp, uj); } DEFUN (show_ip_bgp_instance_all, @@ -10525,13 +10527,14 @@ DEFUN (show_ip_bgp_instance_all, } 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) + afi_t afi, safi_t safi, enum bgp_show_type type, + bool use_json) { regex_t *regex; int rc; if (!config_bgp_aspath_validate(regstr)) { - vty_out(vty, "Invalid character in as-path access-list %s\n", + vty_out(vty, "Invalid character in REGEX %s\n", regstr); return CMD_WARNING_CONFIG_FAILED; } @@ -10542,7 +10545,7 @@ static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr, return CMD_WARNING; } - rc = bgp_show(vty, bgp, afi, safi, type, regex, 0); + rc = bgp_show(vty, bgp, afi, safi, type, regex, use_json); bgp_regex_free(regex); return rc; } diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index e875c4111..53d973295 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -2692,7 +2692,7 @@ DEFUN (bgp_listen_limit, "bgp listen limit (1-5000)", "BGP specific commands\n" "BGP Dynamic Neighbors listen commands\n" - "maximum number of BGP Dynamic Neighbors that can be created\n" + "Maximum number of BGP Dynamic Neighbors that can be created\n" "Configure Dynamic Neighbors listen limit value\n") { VTY_DECLVAR_CONTEXT(bgp, bgp); @@ -2712,8 +2712,7 @@ DEFUN (no_bgp_listen_limit, NO_STR "BGP specific commands\n" "BGP Dynamic Neighbors listen commands\n" - "unset maximum number of BGP Dynamic Neighbors that can be created\n" - "Configure Dynamic Neighbors listen limit value to default\n" + "Maximum number of BGP Dynamic Neighbors that can be created\n" "Configure Dynamic Neighbors listen limit value\n") { VTY_DECLVAR_CONTEXT(bgp, bgp); @@ -9712,23 +9711,6 @@ static void bgp_show_peer(struct vty *vty, struct peer *p, bool use_json, uptime -= p->uptime; epoch_tbuf = time(NULL) - uptime; -#if CONFDATE > 20200101 - CPP_NOTICE( - "bgpTimerUp should be deprecated and can be removed now"); -#endif - /* - * bgpTimerUp was miliseconds that was accurate - * up to 1 day, then the value returned - * became garbage. So in order to provide - * some level of backwards compatability, - * we still provde the data, but now - * we are returning the correct value - * and also adding a new bgpTimerUpMsec - * which will allow us to deprecate - * this eventually - */ - json_object_int_add(json_neigh, "bgpTimerUp", - uptime * 1000); json_object_int_add(json_neigh, "bgpTimerUpMsec", uptime * 1000); json_object_string_add(json_neigh, "bgpTimerUpString", diff --git a/configure.ac b/configure.ac index 0bfcc833f..0694e3ed2 100755 --- a/configure.ac +++ b/configure.ac @@ -331,7 +331,14 @@ if test "$enable_memory_sanitizer" = "yes"; then AC_C_FLAG([-fsanitize=memory -fPIE -pie], [ AC_MSG_ERROR([$CC does not support Memory Sanitizer.]) ], [ - SAN_FLAGS="-fsanitize=memory -fPIE -pie" + SAN_FLAGS="$SAN_FLAGS -fsanitize=memory -fPIE -pie" + ]) +fi +if test "$enable_undefined_sanitizer" = "yes"; then + AC_C_FLAG([-fsanitize=undefined], [ + AC_MSG_ERROR([$CC does not support UndefinedBehaviorSanitizer.]) + ], [ + SAN_FLAGS="$SAN_FLAGS -fsanitize=undefined" ]) fi AC_SUBST([SAN_FLAGS]) @@ -576,6 +583,8 @@ AC_ARG_ENABLE([thread-sanitizer], AS_HELP_STRING([--enable-thread-sanitizer], [enable ThreadSanitizer support for detecting data races])) AC_ARG_ENABLE([memory-sanitizer], AS_HELP_STRING([--enable-memory-sanitizer], [enable MemorySanitizer support for detecting uninitialized memory reads])) +AC_ARG_ENABLE([undefined-sanitizer], + AS_HELP_STRING([--undefined-sanitizer], [enable UndefinedBehaviorSanitizer support for detecting undefined behavior])) AC_ARG_WITH([crypto], AS_HELP_STRING([--with-crypto=<internal|openssl>], [choose between different implementations of cryptographic functions(default value is --with-crypto=internal)])) diff --git a/doc/user/overview.rst b/doc/user/overview.rst index 2b2ffdf0f..262c0117d 100644 --- a/doc/user/overview.rst +++ b/doc/user/overview.rst @@ -310,6 +310,8 @@ BGP :t:`BGP Large Communities Attribute. J. Heitz, Ed., J. Snijders, Ed, K. Patel, I. Bagdonas, N. Hilliard. February 2017` - :rfc:`8195` :t:`Use of BGP Large Communities. J. Snijders, J. Heasley, M. Schmidt, June 2017` +- :rfc:`8212` + :t:`Default External BGP (EBGP) Route Propagation Behavior without Policies. J. Mauch, J. Snijders, G. Hankins. July 2017` - :rfc:`8277` :t:`Using BGP to Bind MPLS Labels to Address Prefixes. E. Rosen. October 2017` diff --git a/docker/alpine/Dockerfile b/docker/alpine/Dockerfile index 88c8f88f8..ed6453e2b 100644 --- a/docker/alpine/Dockerfile +++ b/docker/alpine/Dockerfile @@ -42,6 +42,7 @@ USER builder RUN cd /dist \ && abuild-keygen -a -n \ && abuild checksum \ + && git init \ && abuild -r -P /pkgs/apk # This stage installs frr from the apk diff --git a/docker/centos-8/build.sh b/docker/centos-8/build.sh index 968d5fe6c..4a9918486 100755 --- a/docker/centos-8/build.sh +++ b/docker/centos-8/build.sh @@ -17,7 +17,7 @@ docker build \ . # Copy RPM package from container to host -CONTAINER_ID="$(docker create "frr:centos-builder-8-$GITREV")" +CONTAINER_ID="$(docker create "frr:centos-8-builder-$GITREV")" docker cp "${CONTAINER_ID}:/rpmbuild/RPMS/x86_64/" docker/centos-8/pkgs docker rm "${CONTAINER_ID}" @@ -137,7 +137,12 @@ static int if_cmp_func(const struct interface *ifp1, static int if_cmp_index_func(const struct interface *ifp1, const struct interface *ifp2) { - return ifp1->ifindex - ifp2->ifindex; + if (ifp1->ifindex == ifp2->ifindex) + return 0; + else if (ifp1->ifindex > ifp2->ifindex) + return 1; + else + return -1; } static void ifp_connected_free(void *arg) diff --git a/lib/zclient.c b/lib/zclient.c index 6982d287a..fd1b181e5 100644 --- a/lib/zclient.c +++ b/lib/zclient.c @@ -2679,6 +2679,17 @@ int zapi_labels_decode(struct stream *s, struct zapi_labels *zl) } STREAM_GETW(s, zl->nexthop_num); + + if (zl->nexthop_num > MULTIPATH_NUM) { + flog_warn( + EC_LIB_ZAPI_ENCODE, + "%s: Prefix %pFX has %d nexthops, but we can only use the first %d", + __func__, &zl->route.prefix, zl->nexthop_num, + MULTIPATH_NUM); + } + + zl->nexthop_num = MIN(MULTIPATH_NUM, zl->nexthop_num); + for (int i = 0; i < zl->nexthop_num; i++) { znh = &zl->nexthops[i]; diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index d165cca08..01bebebd2 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -914,7 +914,6 @@ static void pim_show_interfaces_single(struct pim_instance *pim, struct in_addr ifaddr; struct interface *ifp; struct listnode *neighnode; - struct listnode *upnode; struct pim_interface *pim_ifp; struct pim_neighbor *neigh; struct pim_upstream *up; @@ -1052,8 +1051,7 @@ static void pim_show_interfaces_single(struct pim_instance *pim, pim_ifp->pim_dr_election_changes); // FHR - for (ALL_LIST_ELEMENTS_RO(pim->upstream_list, upnode, - up)) { + frr_each (rb_pim_upstream, &pim->upstream_head, up) { if (ifp != up->rpf.source_nexthop.interface) continue; @@ -1215,8 +1213,7 @@ static void pim_show_interfaces_single(struct pim_instance *pim, // FHR print_header = 1; - for (ALL_LIST_ELEMENTS_RO(pim->upstream_list, upnode, - up)) { + frr_each (rb_pim_upstream, &pim->upstream_head, up) { if (!up->rpf.source_nexthop.interface) continue; @@ -1386,7 +1383,6 @@ static void pim_show_interfaces(struct pim_instance *pim, struct vty *vty, bool uj) { struct interface *ifp; - struct listnode *upnode; struct pim_interface *pim_ifp; struct pim_upstream *up; int fhr = 0; @@ -1408,7 +1404,7 @@ static void pim_show_interfaces(struct pim_instance *pim, struct vty *vty, pim_ifchannels = pim_if_ifchannel_count(pim_ifp); fhr = 0; - for (ALL_LIST_ELEMENTS_RO(pim->upstream_list, upnode, up)) + frr_each (rb_pim_upstream, &pim->upstream_head, up) if (ifp == up->rpf.source_nexthop.interface) if (up->flags & PIM_UPSTREAM_FLAG_MASK_FHR) fhr++; @@ -1975,7 +1971,6 @@ static void pim_show_state(struct pim_instance *pim, struct vty *vty, const char *src_or_group, const char *group, bool uj) { struct channel_oil *c_oil; - struct listnode *node; json_object *json = NULL; json_object *json_group = NULL; json_object *json_ifp_in = NULL; @@ -1994,7 +1989,7 @@ static void pim_show_state(struct pim_instance *pim, struct vty *vty, "\nActive Source Group RPT IIF OIL\n"); } - for (ALL_LIST_ELEMENTS_RO(pim->channel_oil_list, node, c_oil)) { + frr_each (rb_pim_oil, &pim->channel_oil_head, c_oil) { char grp_str[INET_ADDRSTRLEN]; char src_str[INET_ADDRSTRLEN]; char in_ifname[INTERFACE_NAMSIZ + 1]; @@ -2429,7 +2424,6 @@ static const char *pim_reg_state2brief_str(enum pim_reg_state reg_state, static void pim_show_upstream(struct pim_instance *pim, struct vty *vty, struct prefix_sg *sg, bool uj) { - struct listnode *upnode; struct pim_upstream *up; time_t now; json_object *json = NULL; @@ -2444,7 +2438,7 @@ static void pim_show_upstream(struct pim_instance *pim, struct vty *vty, vty_out(vty, "Iif Source Group State Uptime JoinTimer RSTimer KATimer RefCnt\n"); - for (ALL_LIST_ELEMENTS_RO(pim->upstream_list, upnode, up)) { + frr_each (rb_pim_upstream, &pim->upstream_head, up) { char src_str[INET_ADDRSTRLEN]; char grp_str[INET_ADDRSTRLEN]; char uptime[10]; @@ -2716,7 +2710,6 @@ static void pim_show_join_desired_helper(struct pim_instance *pim, static void pim_show_join_desired(struct pim_instance *pim, struct vty *vty, bool uj) { - struct listnode *upnode; struct pim_upstream *up; json_object *json = NULL; @@ -2727,7 +2720,7 @@ static void pim_show_join_desired(struct pim_instance *pim, struct vty *vty, vty_out(vty, "Source Group EvalJD\n"); - for (ALL_LIST_ELEMENTS_RO(pim->upstream_list, upnode, up)) { + frr_each (rb_pim_upstream, &pim->upstream_head, up) { /* scan all interfaces */ pim_show_join_desired_helper(pim, vty, up, json, uj); @@ -2743,7 +2736,6 @@ static void pim_show_join_desired(struct pim_instance *pim, struct vty *vty, static void pim_show_upstream_rpf(struct pim_instance *pim, struct vty *vty, bool uj) { - struct listnode *upnode; struct pim_upstream *up; json_object *json = NULL; json_object *json_group = NULL; @@ -2755,7 +2747,7 @@ static void pim_show_upstream_rpf(struct pim_instance *pim, struct vty *vty, vty_out(vty, "Source Group RpfIface RibNextHop RpfAddress \n"); - for (ALL_LIST_ELEMENTS_RO(pim->upstream_list, upnode, up)) { + frr_each (rb_pim_upstream, &pim->upstream_head, up) { char src_str[INET_ADDRSTRLEN]; char grp_str[INET_ADDRSTRLEN]; char rpf_nexthop_str[PREFIX_STRLEN]; @@ -2876,7 +2868,6 @@ static void show_scan_oil_stats(struct pim_instance *pim, struct vty *vty, static void pim_show_rpf(struct pim_instance *pim, struct vty *vty, bool uj) { - struct listnode *up_node; struct pim_upstream *up; time_t now = pim_time_monotonic_sec(); json_object *json = NULL; @@ -2893,7 +2884,7 @@ static void pim_show_rpf(struct pim_instance *pim, struct vty *vty, bool uj) "Source Group RpfIface RpfAddress RibNextHop Metric Pref\n"); } - for (ALL_LIST_ELEMENTS_RO(pim->upstream_list, up_node, up)) { + frr_each (rb_pim_upstream, &pim->upstream_head, up) { char src_str[INET_ADDRSTRLEN]; char grp_str[INET_ADDRSTRLEN]; char rpf_addr_str[PREFIX_STRLEN]; @@ -3933,11 +3924,8 @@ static void clear_mroute(struct pim_instance *pim) } /* clean up all upstreams*/ - if (pim->upstream_list) { - while (pim->upstream_list->count) { - up = listnode_head(pim->upstream_list); - pim_upstream_del(pim, up, __PRETTY_FUNCTION__); - } + while ((up = rb_pim_upstream_first(&pim->upstream_head))) { + pim_upstream_del(pim, up, __PRETTY_FUNCTION__); } } @@ -5420,7 +5408,7 @@ static void show_mroute(struct pim_instance *pim, struct vty *vty, now = pim_time_monotonic_sec(); /* print list of PIM and IGMP routes */ - for (ALL_LIST_ELEMENTS_RO(pim->channel_oil_list, node, c_oil)) { + frr_each (rb_pim_oil, &pim->channel_oil_head, c_oil) { found_oif = 0; first = 1; if (!c_oil->installed && !uj) @@ -5828,7 +5816,7 @@ DEFUN (clear_ip_mroute_count, return CMD_WARNING; pim = vrf->info; - for (ALL_LIST_ELEMENTS_RO(pim->channel_oil_list, node, c_oil)) { + frr_each(rb_pim_oil, &pim->channel_oil_head, c_oil) { if (!c_oil->installed) continue; @@ -5863,7 +5851,7 @@ static void show_mroute_count(struct pim_instance *pim, struct vty *vty) "Source Group LastUsed Packets Bytes WrongIf \n"); /* Print PIM and IGMP route counts */ - for (ALL_LIST_ELEMENTS_RO(pim->channel_oil_list, node, c_oil)) { + frr_each (rb_pim_oil, &pim->channel_oil_head, c_oil) { char group_str[INET_ADDRSTRLEN]; char source_str[INET_ADDRSTRLEN]; @@ -5968,7 +5956,7 @@ static void show_mroute_summary(struct pim_instance *pim, struct vty *vty) vty_out(vty, "Mroute Type Installed/Total\n"); - for (ALL_LIST_ELEMENTS_RO(pim->channel_oil_list, node, c_oil)) { + frr_each (rb_pim_oil, &pim->channel_oil_head, c_oil) { if (!c_oil->installed) { if (c_oil->oil.mfcc_origin.s_addr == INADDR_ANY) starg_sw_mroute_cnt++; diff --git a/pimd/pim_igmp.c b/pimd/pim_igmp.c index 54ad17a99..39ef706f7 100644 --- a/pimd/pim_igmp.c +++ b/pimd/pim_igmp.c @@ -1113,8 +1113,10 @@ struct igmp_group *igmp_add_group_by_addr(struct igmp_sock *igmp, } if (pim_is_group_224_0_0_0_24(group_addr)) { - zlog_warn("%s: Group specified is part of 224.0.0.0/24", - __PRETTY_FUNCTION__); + if (PIM_DEBUG_IGMP_TRACE) + zlog_debug( + "%s: Group specified %s is part of 224.0.0.0/24", + __PRETTY_FUNCTION__, inet_ntoa(group_addr)); return NULL; } /* diff --git a/pimd/pim_instance.h b/pimd/pim_instance.h index dd3ac8fcb..da0c75dec 100644 --- a/pimd/pim_instance.h +++ b/pimd/pim_instance.h @@ -28,6 +28,8 @@ #include "pim_assert.h" #include "pim_bsm.h" #include "pim_vxlan_instance.h" +#include "pim_oil.h" +#include "pim_upstream.h" #if defined(HAVE_LINUX_MROUTE_H) #include <linux/mroute.h> @@ -107,8 +109,7 @@ struct pim_instance { struct list *static_routes; // Upstream vrf specific information - struct list *upstream_list; - struct hash *upstream_hash; + struct rb_pim_upstream_head upstream_head; struct timer_wheel *upstream_sg_wheel; /* @@ -119,8 +120,7 @@ struct pim_instance { int iface_vif_index[MAXVIFS]; - struct list *channel_oil_list; - struct hash *channel_oil_hash; + struct rb_pim_oil_head channel_oil_head; struct pim_msdp msdp; struct pim_vxlan_instance vxlan; diff --git a/pimd/pim_msdp.c b/pimd/pim_msdp.c index 8a18594fd..58ebc6ce6 100644 --- a/pimd/pim_msdp.c +++ b/pimd/pim_msdp.c @@ -565,11 +565,9 @@ void pim_msdp_sa_local_update(struct pim_upstream *up) static void pim_msdp_sa_local_setup(struct pim_instance *pim) { struct pim_upstream *up; - struct listnode *up_node; - for (ALL_LIST_ELEMENTS_RO(pim->upstream_list, up_node, up)) { + frr_each (rb_pim_upstream, &pim->upstream_head, up) pim_msdp_sa_local_update(up); - } } /* whenever the RP changes we need to re-evaluate the "local" SA-cache */ diff --git a/pimd/pim_nht.c b/pimd/pim_nht.c index bd8424b3e..5cb9492ec 100644 --- a/pimd/pim_nht.c +++ b/pimd/pim_nht.c @@ -177,7 +177,6 @@ void pim_delete_tracked_nexthop(struct pim_instance *pim, struct prefix *addr, struct pim_nexthop_cache *pnc = NULL; struct pim_nexthop_cache lookup; struct zclient *zclient = NULL; - struct listnode *upnode = NULL; struct pim_upstream *upstream = NULL; zclient = pim_zebra_zclient_get(); @@ -190,8 +189,8 @@ void pim_delete_tracked_nexthop(struct pim_instance *pim, struct prefix *addr, /* Release the (*, G)upstream from pnc->upstream_hash, * whose Group belongs to the RP getting deleted */ - for (ALL_LIST_ELEMENTS_RO(pim->upstream_list, upnode, - upstream)) { + frr_each (rb_pim_upstream, &pim->upstream_head, + upstream) { struct prefix grp; struct rp_info *trp_info; diff --git a/pimd/pim_oil.c b/pimd/pim_oil.c index 65c6bdd2b..598988f88 100644 --- a/pimd/pim_oil.c +++ b/pimd/pim_oil.c @@ -64,8 +64,8 @@ char *pim_channel_oil_dump(struct channel_oil *c_oil, char *buf, size_t size) return buf; } -static int pim_channel_oil_compare(struct channel_oil *c1, - struct channel_oil *c2) +int pim_channel_oil_compare(const struct channel_oil *c1, + const struct channel_oil *c2) { if (ntohl(c1->oil.mfcc_mcastgrp.s_addr) < ntohl(c2->oil.mfcc_mcastgrp.s_addr)) @@ -86,48 +86,19 @@ static int pim_channel_oil_compare(struct channel_oil *c1, return 0; } -static bool pim_oil_equal(const void *arg1, const void *arg2) -{ - const struct channel_oil *c1 = (const struct channel_oil *)arg1; - const struct channel_oil *c2 = (const struct channel_oil *)arg2; - - if ((c1->oil.mfcc_mcastgrp.s_addr == c2->oil.mfcc_mcastgrp.s_addr) - && (c1->oil.mfcc_origin.s_addr == c2->oil.mfcc_origin.s_addr)) - return true; - - return false; -} - -static unsigned int pim_oil_hash_key(const void *arg) -{ - const struct channel_oil *oil = arg; - - return jhash_2words(oil->oil.mfcc_mcastgrp.s_addr, - oil->oil.mfcc_origin.s_addr, 0); -} - void pim_oil_init(struct pim_instance *pim) { - char hash_name[64]; - - snprintf(hash_name, 64, "PIM %s Oil Hash", pim->vrf->name); - pim->channel_oil_hash = hash_create_size(8192, pim_oil_hash_key, - pim_oil_equal, hash_name); - - pim->channel_oil_list = list_new(); - pim->channel_oil_list->del = (void (*)(void *))pim_channel_oil_free; - pim->channel_oil_list->cmp = - (int (*)(void *, void *))pim_channel_oil_compare; + rb_pim_oil_init(&pim->channel_oil_head); } void pim_oil_terminate(struct pim_instance *pim) { - if (pim->channel_oil_list) - list_delete(&pim->channel_oil_list); + struct channel_oil *c_oil; + + while ((c_oil = rb_pim_oil_pop(&pim->channel_oil_head))) + pim_channel_oil_free(c_oil); - if (pim->channel_oil_hash) - hash_free(pim->channel_oil_hash); - pim->channel_oil_hash = NULL; + rb_pim_oil_fini(&pim->channel_oil_head); } void pim_channel_oil_free(struct channel_oil *c_oil) @@ -144,7 +115,7 @@ struct channel_oil *pim_find_channel_oil(struct pim_instance *pim, lookup.oil.mfcc_mcastgrp = sg->grp; lookup.oil.mfcc_origin = sg->src; - c_oil = hash_lookup(pim->channel_oil_hash, &lookup); + c_oil = rb_pim_oil_find(&pim->channel_oil_head, &lookup); return c_oil; } @@ -187,7 +158,6 @@ struct channel_oil *pim_channel_oil_add(struct pim_instance *pim, c_oil->oil.mfcc_mcastgrp = sg->grp; c_oil->oil.mfcc_origin = sg->src; - c_oil = hash_get(pim->channel_oil_hash, c_oil, hash_alloc_intern); c_oil->oil.mfcc_parent = MAXVIFS; c_oil->oil_ref_count = 1; @@ -195,7 +165,7 @@ struct channel_oil *pim_channel_oil_add(struct pim_instance *pim, c_oil->up = pim_upstream_find(pim, sg); c_oil->pim = pim; - listnode_add_sort(pim->channel_oil_list, c_oil); + rb_pim_oil_add(&pim->channel_oil_head, c_oil); if (PIM_DEBUG_MROUTE) zlog_debug("%s(%s): c_oil %s add", @@ -224,8 +194,7 @@ struct channel_oil *pim_channel_oil_del(struct channel_oil *c_oil, * called by list_delete_all_node() */ c_oil->up = NULL; - listnode_delete(c_oil->pim->channel_oil_list, c_oil); - hash_release(c_oil->pim->channel_oil_hash, c_oil); + rb_pim_oil_del(&c_oil->pim->channel_oil_head, c_oil); pim_channel_oil_free(c_oil); return NULL; diff --git a/pimd/pim_oil.h b/pimd/pim_oil.h index de7fde05d..788ddaa16 100644 --- a/pimd/pim_oil.h +++ b/pimd/pim_oil.h @@ -90,10 +90,13 @@ struct channel_counts { installed: indicate if this entry is installed in the kernel. */ +PREDECL_RBTREE_UNIQ(rb_pim_oil) struct channel_oil { struct pim_instance *pim; + struct rb_pim_oil_item oil_rb; + struct mfcctl oil; int installed; int oil_inherited_rescan; @@ -106,6 +109,12 @@ struct channel_oil { time_t mroute_creation; }; +extern int pim_channel_oil_compare(const struct channel_oil *c1, + const struct channel_oil *c2); +DECLARE_RBTREE_UNIQ(rb_pim_oil, struct channel_oil, oil_rb, + pim_channel_oil_compare) + + extern struct list *pim_channel_oil_list; void pim_oil_init(struct pim_instance *pim); diff --git a/pimd/pim_rp.c b/pimd/pim_rp.c index bd295b0fe..2db39bac4 100644 --- a/pimd/pim_rp.c +++ b/pimd/pim_rp.c @@ -446,7 +446,6 @@ int pim_rp_new(struct pim_instance *pim, struct in_addr rp_addr, struct prefix nht_p; struct route_node *rn; struct pim_upstream *up; - struct listnode *upnode; if (rp_addr.s_addr == INADDR_ANY || rp_addr.s_addr == INADDR_NONE) @@ -554,8 +553,7 @@ int pim_rp_new(struct pim_instance *pim, struct in_addr rp_addr, __PRETTY_FUNCTION__, buf, buf1); } - for (ALL_LIST_ELEMENTS_RO(pim->upstream_list, upnode, - up)) { + frr_each (rb_pim_upstream, &pim->upstream_head, up) { /* Find (*, G) upstream whose RP is not * configured yet */ @@ -650,7 +648,7 @@ int pim_rp_new(struct pim_instance *pim, struct in_addr rp_addr, rn->lock); } - for (ALL_LIST_ELEMENTS_RO(pim->upstream_list, upnode, up)) { + frr_each (rb_pim_upstream, &pim->upstream_head, up) { if (up->sg.src.s_addr == INADDR_ANY) { struct prefix grp; struct rp_info *trp_info; @@ -723,7 +721,6 @@ int pim_rp_del(struct pim_instance *pim, struct in_addr rp_addr, bool was_plist = false; struct rp_info *trp_info; struct pim_upstream *up; - struct listnode *upnode; struct bsgrp_node *bsgrp = NULL; struct bsm_rpinfo *bsrp = NULL; char grp_str[PREFIX2STR_BUFFER]; @@ -800,7 +797,7 @@ int pim_rp_del(struct pim_instance *pim, struct in_addr rp_addr, rp_all = pim_rp_find_match_group(pim, &g_all); if (rp_all == rp_info) { - for (ALL_LIST_ELEMENTS_RO(pim->upstream_list, upnode, up)) { + frr_each (rb_pim_upstream, &pim->upstream_head, up) { /* Find the upstream (*, G) whose upstream address is * same as the deleted RP */ @@ -852,7 +849,7 @@ int pim_rp_del(struct pim_instance *pim, struct in_addr rp_addr, pim_rp_refresh_group_to_rp_mapping(pim); - for (ALL_LIST_ELEMENTS_RO(pim->upstream_list, upnode, up)) { + frr_each (rb_pim_upstream, &pim->upstream_head, up) { /* Find the upstream (*, G) whose upstream address is same as * the deleted RP */ @@ -893,7 +890,6 @@ int pim_rp_change(struct pim_instance *pim, struct in_addr new_rp_addr, int result = 0; struct rp_info *rp_info = NULL; struct pim_upstream *up; - struct listnode *upnode; rn = route_node_lookup(pim->rp_table, &group); if (!rn) { @@ -942,7 +938,7 @@ int pim_rp_change(struct pim_instance *pim, struct in_addr new_rp_addr, listnode_add_sort(pim->rp_list, rp_info); - for (ALL_LIST_ELEMENTS_RO(pim->upstream_list, upnode, up)) { + frr_each (rb_pim_upstream, &pim->upstream_head, up) { if (up->sg.src.s_addr == INADDR_ANY) { struct prefix grp; struct rp_info *trp_info; diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c index a0387cdd4..afd10bd3d 100644 --- a/pimd/pim_upstream.c +++ b/pimd/pim_upstream.c @@ -98,7 +98,6 @@ static void pim_upstream_find_new_children(struct pim_instance *pim, struct pim_upstream *up) { struct pim_upstream *child; - struct listnode *ch_node; if ((up->sg.src.s_addr != INADDR_ANY) && (up->sg.grp.s_addr != INADDR_ANY)) @@ -108,7 +107,7 @@ static void pim_upstream_find_new_children(struct pim_instance *pim, && (up->sg.grp.s_addr == INADDR_ANY)) return; - for (ALL_LIST_ELEMENTS_RO(pim->upstream_list, ch_node, child)) { + frr_each (rb_pim_upstream, &pim->upstream_head, child) { if ((up->sg.grp.s_addr != INADDR_ANY) && (child->sg.grp.s_addr == up->sg.grp.s_addr) && (child != up)) { @@ -191,9 +190,8 @@ struct pim_upstream *pim_upstream_del(struct pim_instance *pim, return up; if (PIM_DEBUG_TRACE) - zlog_debug( - "pim_upstream free vrf:%s %s flags 0x%x", - pim->vrf->name, up->sg_str, up->flags); + zlog_debug("pim_upstream free vrf:%s %s flags 0x%x", + pim->vrf->name, up->sg_str, up->flags); THREAD_OFF(up->t_ka_timer); THREAD_OFF(up->t_rs_timer); @@ -235,8 +233,7 @@ struct pim_upstream *pim_upstream_del(struct pim_instance *pim, listnode_delete(up->parent->sources, up); up->parent = NULL; - listnode_delete(pim->upstream_list, up); - hash_release(pim->upstream_hash, up); + rb_pim_upstream_del(&pim->upstream_head, up); if (notify_msdp) { pim_msdp_up_del(pim, &up->sg); @@ -533,10 +530,9 @@ static int pim_upstream_could_register(struct pim_upstream *up) * we re-revaluate register setup for existing upstream entries */ void pim_upstream_register_reevaluate(struct pim_instance *pim) { - struct listnode *upnode; struct pim_upstream *up; - for (ALL_LIST_ELEMENTS_RO(pim->upstream_list, upnode, up)) { + frr_each (rb_pim_upstream, &pim->upstream_head, up) { /* If FHR is set CouldRegister is True. Also check if the flow * is actually active; if it is not kat setup will trigger * source @@ -639,9 +635,8 @@ void pim_upstream_update_use_rpt(struct pim_upstream *up, void pim_upstream_reeval_use_rpt(struct pim_instance *pim) { struct pim_upstream *up; - struct listnode *node; - for (ALL_LIST_ELEMENTS_RO(pim->upstream_list, node, up)) { + frr_each (rb_pim_upstream, &pim->upstream_head, up) { if (up->sg.src.s_addr == INADDR_ANY) continue; @@ -756,11 +751,9 @@ void pim_upstream_switch(struct pim_instance *pim, struct pim_upstream *up, } } -int pim_upstream_compare(void *arg1, void *arg2) +int pim_upstream_compare(const struct pim_upstream *up1, + const struct pim_upstream *up2) { - const struct pim_upstream *up1 = (const struct pim_upstream *)arg1; - const struct pim_upstream *up2 = (const struct pim_upstream *)arg2; - if (ntohl(up1->sg.grp.s_addr) < ntohl(up2->sg.grp.s_addr)) return -1; @@ -811,7 +804,7 @@ static struct pim_upstream *pim_upstream_new(struct pim_instance *pim, if (ch) ch->upstream = up; - up = hash_get(pim->upstream_hash, up, hash_alloc_intern); + rb_pim_upstream_add(&pim->upstream_head, up); /* Set up->upstream_addr as INADDR_ANY, if RP is not * configured and retain the upstream data structure */ @@ -825,7 +818,8 @@ static struct pim_upstream *pim_upstream_new(struct pim_instance *pim, up->parent = pim_upstream_find_parent(pim, up); if (up->sg.src.s_addr == INADDR_ANY) { up->sources = list_new(); - up->sources->cmp = pim_upstream_compare; + up->sources->cmp = + (int (*)(void *, void *))pim_upstream_compare; } else up->sources = NULL; @@ -889,8 +883,6 @@ static struct pim_upstream *pim_upstream_new(struct pim_instance *pim, } } - listnode_add_sort(pim->upstream_list, up); - if (PIM_DEBUG_PIM_TRACE) { zlog_debug( "%s: Created Upstream %s upstream_addr %s ref count %d increment", @@ -908,7 +900,7 @@ struct pim_upstream *pim_upstream_find(struct pim_instance *pim, struct pim_upstream *up = NULL; lookup.sg = *sg; - up = hash_lookup(pim->upstream_hash, &lookup); + up = rb_pim_upstream_find(&pim->upstream_head, &lookup); return up; } @@ -1168,15 +1160,12 @@ void pim_upstream_update_join_desired(struct pim_instance *pim, void pim_upstream_rpf_genid_changed(struct pim_instance *pim, struct in_addr neigh_addr) { - struct listnode *up_node; - struct listnode *up_nextnode; struct pim_upstream *up; /* * Scan all (S,G) upstreams searching for RPF'(S,G)=neigh_addr */ - for (ALL_LIST_ELEMENTS(pim->upstream_list, up_node, up_nextnode, up)) { - + frr_each (rb_pim_upstream, &pim->upstream_head, up) { if (PIM_DEBUG_PIM_TRACE) { char neigh_str[INET_ADDRSTRLEN]; char rpf_addr_str[PREFIX_STRLEN]; @@ -1788,8 +1777,6 @@ int pim_upstream_empty_inherited_olist(struct pim_upstream *up) */ void pim_upstream_find_new_rpf(struct pim_instance *pim) { - struct listnode *up_node; - struct listnode *up_nextnode; struct pim_upstream *up; struct pim_rpf old; enum pim_rpf_result rpf_result; @@ -1797,7 +1784,7 @@ void pim_upstream_find_new_rpf(struct pim_instance *pim) /* * Scan all (S,G) upstreams searching for RPF'(S,G)=neigh_addr */ - for (ALL_LIST_ELEMENTS(pim->upstream_list, up_node, up_nextnode, up)) { + frr_each (rb_pim_upstream, &pim->upstream_head, up) { if (up->upstream_addr.s_addr == INADDR_ANY) { if (PIM_DEBUG_PIM_TRACE) zlog_debug( @@ -1837,18 +1824,11 @@ void pim_upstream_terminate(struct pim_instance *pim) { struct pim_upstream *up; - if (pim->upstream_list) { - while (pim->upstream_list->count) { - up = listnode_head(pim->upstream_list); - pim_upstream_del(pim, up, __PRETTY_FUNCTION__); - } - - list_delete(&pim->upstream_list); + while ((up = rb_pim_upstream_first(&pim->upstream_head))) { + pim_upstream_del(pim, up, __PRETTY_FUNCTION__); } - if (pim->upstream_hash) - hash_free(pim->upstream_hash); - pim->upstream_hash = NULL; + rb_pim_upstream_fini(&pim->upstream_head); if (pim->upstream_sg_wheel) wheel_delete(pim->upstream_sg_wheel); @@ -1991,9 +1971,8 @@ static void pim_upstream_sg_running(void *arg) void pim_upstream_add_lhr_star_pimreg(struct pim_instance *pim) { struct pim_upstream *up; - struct listnode *node; - for (ALL_LIST_ELEMENTS_RO(pim->upstream_list, node, up)) { + frr_each (rb_pim_upstream, &pim->upstream_head, up) { if (up->sg.src.s_addr != INADDR_ANY) continue; @@ -2031,7 +2010,6 @@ void pim_upstream_remove_lhr_star_pimreg(struct pim_instance *pim, const char *nlist) { struct pim_upstream *up; - struct listnode *node; struct prefix_list *np; struct prefix g; enum prefix_list_type apply_new; @@ -2041,7 +2019,7 @@ void pim_upstream_remove_lhr_star_pimreg(struct pim_instance *pim, g.family = AF_INET; g.prefixlen = IPV4_MAX_PREFIXLEN; - for (ALL_LIST_ELEMENTS_RO(pim->upstream_list, node, up)) { + frr_each (rb_pim_upstream, &pim->upstream_head, up) { if (up->sg.src.s_addr != INADDR_ANY) continue; @@ -2075,11 +2053,5 @@ void pim_upstream_init(struct pim_instance *pim) wheel_init(router->master, 31000, 100, pim_upstream_hash_key, pim_upstream_sg_running, name); - snprintf(name, 64, "PIM %s Upstream Hash", - pim->vrf->name); - pim->upstream_hash = hash_create_size(8192, pim_upstream_hash_key, - pim_upstream_equal, name); - - pim->upstream_list = list_new(); - pim->upstream_list->cmp = pim_upstream_compare; + rb_pim_upstream_init(&pim->upstream_head); } diff --git a/pimd/pim_upstream.h b/pimd/pim_upstream.h index ab5082051..1eb2052bb 100644 --- a/pimd/pim_upstream.h +++ b/pimd/pim_upstream.h @@ -169,6 +169,7 @@ enum pim_upstream_sptbit { PIM_UPSTREAM_SPTBIT_TRUE }; +PREDECL_RBTREE_UNIQ(rb_pim_upstream); /* Upstream (S,G) channel in Joined state (S,G) in the "Not Joined" state is not represented @@ -198,6 +199,7 @@ enum pim_upstream_sptbit { */ struct pim_upstream { struct pim_instance *pim; + struct rb_pim_upstream_item upstream_rb; struct pim_upstream *parent; struct in_addr upstream_addr; /* Who we are talking to */ struct in_addr upstream_register; /*Who we received a register from*/ @@ -326,7 +328,11 @@ void pim_upstream_init(struct pim_instance *pim); void pim_upstream_terminate(struct pim_instance *pim); void join_timer_start(struct pim_upstream *up); -int pim_upstream_compare(void *arg1, void *arg2); +int pim_upstream_compare(const struct pim_upstream *up1, + const struct pim_upstream *up2); +DECLARE_RBTREE_UNIQ(rb_pim_upstream, struct pim_upstream, upstream_rb, + pim_upstream_compare) + void pim_upstream_register_reevaluate(struct pim_instance *pim); void pim_upstream_add_lhr_star_pimreg(struct pim_instance *pim); diff --git a/pimd/pim_zebra.c b/pimd/pim_zebra.c index 0417d0d06..06507b1f4 100644 --- a/pimd/pim_zebra.c +++ b/pimd/pim_zebra.c @@ -392,16 +392,13 @@ static void pim_zebra_vxlan_replay(void) void pim_scan_oil(struct pim_instance *pim) { - struct listnode *node; - struct listnode *nextnode; struct channel_oil *c_oil; pim->scan_oil_last = pim_time_monotonic_sec(); ++pim->scan_oil_events; - for (ALL_LIST_ELEMENTS(pim->channel_oil_list, node, nextnode, c_oil)) { + frr_each (rb_pim_oil, &pim->channel_oil_head, c_oil) pim_upstream_mroute_iif_update(c_oil, __func__); - } } static int on_rpf_cache_refresh(struct thread *t) diff --git a/redhat/frr.spec.in b/redhat/frr.spec.in index be3b83bf8..670bc6f4c 100644 --- a/redhat/frr.spec.in +++ b/redhat/frr.spec.in @@ -444,7 +444,7 @@ zebra_spec_add_service () { # Add port /etc/services entry if it isn't already there if [ -f %{_sysconfdir}/services ] && \ - ! %__sed -e 's/#.*$//' %{_sysconfdir}/services | %__grep -wq $1 ; then + ! %__sed -e 's/#.*$//' %{_sysconfdir}/services 2>/dev/null | %__grep -wq $1 ; then echo "$1 $2 # $3" >> %{_sysconfdir}/services fi } diff --git a/zebra/if_netlink.c b/zebra/if_netlink.c index c09007bcb..eae5d2b85 100644 --- a/zebra/if_netlink.c +++ b/zebra/if_netlink.c @@ -366,7 +366,7 @@ static void netlink_vrf_change(struct nlmsghdr *h, struct rtattr *tb, } } -static int get_iflink_speed(struct interface *interface, int *error) +static uint32_t get_iflink_speed(struct interface *interface, int *error) { struct ifreq ifdata; struct ethtool_cmd ecmd; @@ -419,7 +419,7 @@ static int get_iflink_speed(struct interface *interface, int *error) close(sd); - return (ecmd.speed_hi << 16) | ecmd.speed; + return ((uint32_t)ecmd.speed_hi << 16) | ecmd.speed; } uint32_t kernel_get_speed(struct interface *ifp, int *error) diff --git a/zebra/kernel_netlink.c b/zebra/kernel_netlink.c index 23f1a3bf8..3bceb5635 100644 --- a/zebra/kernel_netlink.c +++ b/zebra/kernel_netlink.c @@ -1086,7 +1086,7 @@ int netlink_request(struct nlsock *nl, struct nlmsghdr *n) netlink_socket (). */ void kernel_init(struct zebra_ns *zns) { - unsigned long groups; + uint32_t groups; #if defined SOL_NETLINK int one, ret; #endif @@ -1107,9 +1107,9 @@ void kernel_init(struct zebra_ns *zns) RTMGRP_IPV6_IFADDR | RTMGRP_IPV4_MROUTE | RTMGRP_NEIGH | - (1 << (RTNLGRP_IPV4_RULE - 1)) | - (1 << (RTNLGRP_IPV6_RULE - 1)) | - (1 << (RTNLGRP_NEXTHOP - 1)); + ((uint32_t) 1 << (RTNLGRP_IPV4_RULE - 1)) | + ((uint32_t) 1 << (RTNLGRP_IPV6_RULE - 1)) | + ((uint32_t) 1 << (RTNLGRP_NEXTHOP - 1)); snprintf(zns->netlink.name, sizeof(zns->netlink.name), "netlink-listen (NS %u)", zns->ns_id); diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c index fff569c09..29a341abb 100644 --- a/zebra/rt_netlink.c +++ b/zebra/rt_netlink.c @@ -787,34 +787,10 @@ static int netlink_route_change_read_unicast(struct nlmsghdr *h, ns_id_t ns_id, } else { if (!tb[RTA_MULTIPATH]) { struct nexthop nh; - size_t sz = (afi == AFI_IP) ? 4 : 16; - - memset(&nh, 0, sizeof(nh)); - if (bh_type == BLACKHOLE_UNSPEC) { - if (index && !gate) - nh.type = NEXTHOP_TYPE_IFINDEX; - else if (index && gate) - nh.type = - (afi == AFI_IP) - ? NEXTHOP_TYPE_IPV4_IFINDEX - : NEXTHOP_TYPE_IPV6_IFINDEX; - else if (!index && gate) - nh.type = - (afi == AFI_IP) - ? NEXTHOP_TYPE_IPV4 - : NEXTHOP_TYPE_IPV6; - else { - nh.type = - NEXTHOP_TYPE_BLACKHOLE; - nh.bh_type = BLACKHOLE_UNSPEC; - } - } else { - nh.type = NEXTHOP_TYPE_BLACKHOLE; - nh.bh_type = bh_type; - } - nh.ifindex = index; - if (gate) - memcpy(&nh.gate, gate, sz); + + nh = parse_nexthop_unicast( + ns_id, rtm, tb, bh_type, index, prefsrc, + gate, afi, vrf_id); rib_delete(afi, SAFI_UNICAST, vrf_id, proto, 0, flags, &p, &src_p, &nh, 0, table, metric, distance, true); diff --git a/zebra/zapi_msg.c b/zebra/zapi_msg.c index 1dbe41f46..bb2e55c87 100644 --- a/zebra/zapi_msg.c +++ b/zebra/zapi_msg.c @@ -2136,6 +2136,7 @@ static void zread_pseudowire(ZAPI_HANDLER_ARGS) /* Get data. */ STREAM_GET(ifname, s, IF_NAMESIZE); + ifname[IF_NAMESIZE - 1] = '\0'; STREAM_GETL(s, ifindex); STREAM_GETL(s, type); STREAM_GETL(s, af); @@ -2459,37 +2460,39 @@ stream_failure: static inline void zread_iptable(ZAPI_HANDLER_ARGS) { - struct zebra_pbr_iptable zpi; + struct zebra_pbr_iptable *zpi = + XCALLOC(MTYPE_TMP, sizeof(struct zebra_pbr_iptable)); struct stream *s; s = msg; - memset(&zpi, 0, sizeof(zpi)); - - zpi.interface_name_list = list_new(); - zpi.sock = client->sock; - zpi.vrf_id = zvrf->vrf->vrf_id; - STREAM_GETL(s, zpi.unique); - STREAM_GETL(s, zpi.type); - STREAM_GETL(s, zpi.filter_bm); - STREAM_GETL(s, zpi.action); - STREAM_GETL(s, zpi.fwmark); - STREAM_GET(&zpi.ipset_name, s, ZEBRA_IPSET_NAME_SIZE); - STREAM_GETW(s, zpi.pkt_len_min); - STREAM_GETW(s, zpi.pkt_len_max); - STREAM_GETW(s, zpi.tcp_flags); - STREAM_GETW(s, zpi.tcp_mask_flags); - STREAM_GETC(s, zpi.dscp_value); - STREAM_GETC(s, zpi.fragment); - STREAM_GETC(s, zpi.protocol); - STREAM_GETL(s, zpi.nb_interface); - zebra_pbr_iptable_update_interfacelist(s, &zpi); + zpi->interface_name_list = list_new(); + zpi->sock = client->sock; + zpi->vrf_id = zvrf->vrf->vrf_id; + STREAM_GETL(s, zpi->unique); + STREAM_GETL(s, zpi->type); + STREAM_GETL(s, zpi->filter_bm); + STREAM_GETL(s, zpi->action); + STREAM_GETL(s, zpi->fwmark); + STREAM_GET(&zpi->ipset_name, s, ZEBRA_IPSET_NAME_SIZE); + STREAM_GETW(s, zpi->pkt_len_min); + STREAM_GETW(s, zpi->pkt_len_max); + STREAM_GETW(s, zpi->tcp_flags); + STREAM_GETW(s, zpi->tcp_mask_flags); + STREAM_GETC(s, zpi->dscp_value); + STREAM_GETC(s, zpi->fragment); + STREAM_GETC(s, zpi->protocol); + STREAM_GETL(s, zpi->nb_interface); + zebra_pbr_iptable_update_interfacelist(s, zpi); if (hdr->command == ZEBRA_IPTABLE_ADD) - zebra_pbr_add_iptable(&zpi); + zebra_pbr_add_iptable(zpi); else - zebra_pbr_del_iptable(&zpi); + zebra_pbr_del_iptable(zpi); + stream_failure: + zebra_pbr_iptable_free(zpi); + zpi = NULL; return; } diff --git a/zebra/zebra_pbr.c b/zebra/zebra_pbr.c index e24d2e2b4..0c3adcdfa 100644 --- a/zebra/zebra_pbr.c +++ b/zebra/zebra_pbr.c @@ -345,11 +345,13 @@ void zebra_pbr_iptable_free(void *arg) iptable = (struct zebra_pbr_iptable *)arg; hook_call(zebra_pbr_iptable_update, 0, iptable); - for (ALL_LIST_ELEMENTS(iptable->interface_name_list, - node, nnode, name)) { - XFREE(MTYPE_PBR_IPTABLE_IFNAME, name); - list_delete_node(iptable->interface_name_list, - node); + if (iptable->interface_name_list) { + for (ALL_LIST_ELEMENTS(iptable->interface_name_list, node, + nnode, name)) { + XFREE(MTYPE_PBR_IPTABLE_IFNAME, name); + list_delete_node(iptable->interface_name_list, node); + } + list_delete(&iptable->interface_name_list); } XFREE(MTYPE_TMP, iptable); } @@ -688,6 +690,7 @@ void zebra_pbr_del_iptable(struct zebra_pbr_iptable *iptable) list_delete_node(iptable->interface_name_list, node); } + list_delete(&iptable->interface_name_list); XFREE(MTYPE_TMP, lookup); } else zlog_debug("%s: IPTable being deleted we know nothing about", |