From fdf19f06f2fd96513d5da7b835155bd607cf999a Mon Sep 17 00:00:00 2001 From: Mitesh Kanjariya Date: Tue, 20 Feb 2018 00:23:06 -0800 Subject: [PATCH 01/25] bgpd: allow advertise-subnet cmd without enabling advertise ipv4 unicast Type-5 routes can be useful in multiple scenarios such as advertise-subnet, default-originate etc. Currently, the code has a restriction that to allow advertising type-5 routes, user has to first enable advertise ipvX command. This restriction is not necessary and should be removed. Signed-off-by: Mitesh Kanjariya --- bgpd/bgp_evpn.c | 28 ++++++++-------------------- bgpd/bgp_evpn.h | 17 +++++++++++++++++ bgpd/bgp_evpn_private.h | 17 ----------------- bgpd/bgp_evpn_vty.c | 12 ++---------- bgpd/bgp_route.c | 4 ++-- 5 files changed, 29 insertions(+), 49 deletions(-) diff --git a/bgpd/bgp_evpn.c b/bgpd/bgp_evpn.c index ec8e2907a6..6a3496a4d0 100644 --- a/bgpd/bgp_evpn.c +++ b/bgpd/bgp_evpn.c @@ -2553,10 +2553,12 @@ static int install_uninstall_evpn_route(struct bgp *bgp, afi_t afi, safi_t safi, static void delete_withdraw_vrf_routes(struct bgp *bgp_vrf) { /* delete all ipv4 routes and withdraw from peers */ - bgp_evpn_withdraw_type5_routes(bgp_vrf, AFI_IP, SAFI_UNICAST); + if (advertise_type5_routes(bgp_vrf, AFI_IP)) + bgp_evpn_withdraw_type5_routes(bgp_vrf, AFI_IP, SAFI_UNICAST); /* delete all ipv6 routes and withdraw from peers */ - bgp_evpn_withdraw_type5_routes(bgp_vrf, AFI_IP6, SAFI_UNICAST); + if (advertise_type5_routes(bgp_vrf, AFI_IP6)) + bgp_evpn_withdraw_type5_routes(bgp_vrf, AFI_IP6, SAFI_UNICAST); } /* update and advertise all ipv4 and ipv6 routes in thr vrf table as type-5 @@ -2564,10 +2566,12 @@ static void delete_withdraw_vrf_routes(struct bgp *bgp_vrf) static void update_advertise_vrf_routes(struct bgp *bgp_vrf) { /* update all ipv4 routes */ - bgp_evpn_advertise_type5_routes(bgp_vrf, AFI_IP, SAFI_UNICAST); + if (advertise_type5_routes(bgp_vrf, AFI_IP)) + bgp_evpn_advertise_type5_routes(bgp_vrf, AFI_IP, SAFI_UNICAST); /* update all ipv6 routes */ - bgp_evpn_advertise_type5_routes(bgp_vrf, AFI_IP6, SAFI_UNICAST); + if (advertise_type5_routes(bgp_vrf, AFI_IP6)) + bgp_evpn_advertise_type5_routes(bgp_vrf, AFI_IP6, SAFI_UNICAST); } /* @@ -3189,10 +3193,6 @@ void bgp_evpn_withdraw_type5_route(struct bgp *bgp_vrf, struct prefix *p, struct prefix_evpn evp; char buf[PREFIX_STRLEN]; - /* NOTE: Check needed as this is called per-route also. */ - if (!advertise_type5_routes(bgp_vrf, afi)) - return; - build_type5_prefix_from_ip_prefix(&evp, p); ret = delete_evpn_type5_route(bgp_vrf, &evp); if (ret) { @@ -3211,10 +3211,6 @@ void bgp_evpn_withdraw_type5_routes(struct bgp *bgp_vrf, struct bgp_table *table = NULL; struct bgp_node *rn = NULL; - /* Bail out early if we don't have to advertise type-5 routes. */ - if (!advertise_type5_routes(bgp_vrf, afi)) - return; - table = bgp_vrf->rib[afi][safi]; for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) bgp_evpn_withdraw_type5_route(bgp_vrf, &rn->p, afi, safi); @@ -3235,10 +3231,6 @@ void bgp_evpn_advertise_type5_route(struct bgp *bgp_vrf, struct prefix *p, struct prefix_evpn evp; char buf[PREFIX_STRLEN]; - /* NOTE: Check needed as this is called per-route also. */ - if (!advertise_type5_routes(bgp_vrf, afi)) - return; - /* only advertise subnet routes as type-5 */ if (is_host_route(p)) return; @@ -3263,10 +3255,6 @@ void bgp_evpn_advertise_type5_routes(struct bgp *bgp_vrf, struct bgp_node *rn = NULL; struct bgp_info *ri; - /* Bail out early if we don't have to advertise type-5 routes. */ - if (!advertise_type5_routes(bgp_vrf, afi)) - return; - table = bgp_vrf->rib[afi][safi]; for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) { /* Need to identify the "selected" route entry to use its diff --git a/bgpd/bgp_evpn.h b/bgpd/bgp_evpn.h index a8dcbc112b..cd3b7e3af2 100644 --- a/bgpd/bgp_evpn.h +++ b/bgpd/bgp_evpn.h @@ -55,6 +55,23 @@ static inline vni_t label2vni(mpls_label_t *label) return vni; } +static inline int advertise_type5_routes(struct bgp *bgp_vrf, + afi_t afi) +{ + if (!bgp_vrf->l3vni) + return 0; + + if (afi == AFI_IP && + CHECK_FLAG(bgp_vrf->vrf_flags, BGP_VRF_ADVERTISE_IPV4_IN_EVPN)) + return 1; + + if (afi == AFI_IP6 && + CHECK_FLAG(bgp_vrf->vrf_flags, BGP_VRF_ADVERTISE_IPV6_IN_EVPN)) + return 1; + + return 0; +} + extern void bgp_evpn_advertise_type5_route(struct bgp *bgp_vrf, struct prefix *p, struct attr *src_attr, diff --git a/bgpd/bgp_evpn_private.h b/bgpd/bgp_evpn_private.h index cc0ec82344..5ff16c39e9 100644 --- a/bgpd/bgp_evpn_private.h +++ b/bgpd/bgp_evpn_private.h @@ -349,23 +349,6 @@ static inline void build_evpn_type3_prefix(struct prefix_evpn *p, p->prefix.ip.ipaddr_v4 = originator_ip; } -static inline int advertise_type5_routes(struct bgp *bgp_vrf, - afi_t afi) -{ - if (!bgp_vrf->l3vni) - return 0; - - if (afi == AFI_IP && - CHECK_FLAG(bgp_vrf->vrf_flags, BGP_VRF_ADVERTISE_IPV4_IN_EVPN)) - return 1; - - if (afi == AFI_IP6 && - CHECK_FLAG(bgp_vrf->vrf_flags, BGP_VRF_ADVERTISE_IPV6_IN_EVPN)) - return 1; - - return 0; -} - extern void evpn_rt_delete_auto(struct bgp*, vni_t, struct list*); extern void bgp_evpn_configure_export_rt_for_vrf(struct bgp *bgp_vrf, struct ecommunity *ecomadd); diff --git a/bgpd/bgp_evpn_vty.c b/bgpd/bgp_evpn_vty.c index 1373afec4e..c3cab18d2e 100644 --- a/bgpd/bgp_evpn_vty.c +++ b/bgpd/bgp_evpn_vty.c @@ -2690,14 +2690,6 @@ DEFUN (bgp_evpn_advertise_vni_subnet, if (!bgp_vrf) return CMD_WARNING; - if (!(advertise_type5_routes(bgp_vrf, AFI_IP) || - advertise_type5_routes(bgp_vrf, AFI_IP6))) { - vty_out(vty, - "%%Please enable ip prefix advertisement under l2vpn evpn in %s", - vrf_id_to_name(bgp_vrf->vrf_id)); - return CMD_WARNING; - } - evpn_set_advertise_subnet(bgp, vpn); return CMD_SUCCESS; } @@ -2841,7 +2833,7 @@ DEFUN (no_bgp_evpn_advertise_type5, if (afi == AFI_IP) { - /* if we are already advertising ipv4 prefix as type-5 + /* if we are not advertising ipv4 prefix as type-5 * nothing to do */ if (CHECK_FLAG(bgp_vrf->vrf_flags, @@ -2852,7 +2844,7 @@ DEFUN (no_bgp_evpn_advertise_type5, } } else { - /* if we are already advertising ipv6 prefix as type-5 + /* if we are not advertising ipv6 prefix as type-5 * nothing to do */ if (CHECK_FLAG(bgp_vrf->vrf_flags, diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index 20bf9635a3..0d226f9e72 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -2228,10 +2228,10 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_node *rn, /* advertise/withdraw type-5 routes */ if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) { - if (new_select) + if (advertise_type5_routes(bgp, afi) && new_select) bgp_evpn_advertise_type5_route( bgp, &rn->p, new_select->attr, afi, safi); - else if (old_select) + else if (advertise_type5_routes(bgp, afi) && old_select) bgp_evpn_withdraw_type5_route(bgp, &rn->p, afi, safi); } From 154faa5007767a23eeb1daed8a33421320a9276d Mon Sep 17 00:00:00 2001 From: Mitesh Kanjariya Date: Tue, 20 Feb 2018 00:46:22 -0800 Subject: [PATCH 02/25] bgpd: move l2vpn evpn related flags in struct bgp to af_flags We have af_flags in struct bgp to hold address family related flags, l2vpn evpn flags to indicate advertise ipvX unicast should be moved there. Signed-off-by: Mitesh Kanjariya --- bgpd/bgp_evpn.h | 6 ++++-- bgpd/bgp_evpn_vty.c | 38 +++++++++++++++++++++----------------- bgpd/bgpd.h | 13 ++++++++----- 3 files changed, 33 insertions(+), 24 deletions(-) diff --git a/bgpd/bgp_evpn.h b/bgpd/bgp_evpn.h index cd3b7e3af2..064cc71349 100644 --- a/bgpd/bgp_evpn.h +++ b/bgpd/bgp_evpn.h @@ -62,11 +62,13 @@ static inline int advertise_type5_routes(struct bgp *bgp_vrf, return 0; if (afi == AFI_IP && - CHECK_FLAG(bgp_vrf->vrf_flags, BGP_VRF_ADVERTISE_IPV4_IN_EVPN)) + CHECK_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN], + BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST)) return 1; if (afi == AFI_IP6 && - CHECK_FLAG(bgp_vrf->vrf_flags, BGP_VRF_ADVERTISE_IPV6_IN_EVPN)) + CHECK_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN], + BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST)) return 1; return 0; diff --git a/bgpd/bgp_evpn_vty.c b/bgpd/bgp_evpn_vty.c index c3cab18d2e..1720744439 100644 --- a/bgpd/bgp_evpn_vty.c +++ b/bgpd/bgp_evpn_vty.c @@ -2761,21 +2761,23 @@ DEFUN (bgp_evpn_advertise_type5, /* if we are already advertising ipv4 prefix as type-5 * nothing to do */ - if (!rmap_changed && CHECK_FLAG(bgp_vrf->vrf_flags, - BGP_VRF_ADVERTISE_IPV4_IN_EVPN)) + if (!rmap_changed && + CHECK_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN], + BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST)) return CMD_WARNING; - SET_FLAG(bgp_vrf->vrf_flags, - BGP_VRF_ADVERTISE_IPV4_IN_EVPN); + SET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN], + BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST); } else { /* if we are already advertising ipv6 prefix as type-5 * nothing to do */ - if (!rmap_changed && CHECK_FLAG(bgp_vrf->vrf_flags, - BGP_VRF_ADVERTISE_IPV6_IN_EVPN)) + if (!rmap_changed && + CHECK_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN], + BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST)) return CMD_WARNING; - SET_FLAG(bgp_vrf->vrf_flags, - BGP_VRF_ADVERTISE_IPV6_IN_EVPN); + SET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN], + BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST); } if (rmap_changed) { @@ -2836,22 +2838,22 @@ DEFUN (no_bgp_evpn_advertise_type5, /* if we are not advertising ipv4 prefix as type-5 * nothing to do */ - if (CHECK_FLAG(bgp_vrf->vrf_flags, - BGP_VRF_ADVERTISE_IPV4_IN_EVPN)) { + if (CHECK_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN], + BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST)) { bgp_evpn_withdraw_type5_routes(bgp_vrf, afi, safi); - UNSET_FLAG(bgp_vrf->vrf_flags, - BGP_VRF_ADVERTISE_IPV4_IN_EVPN); + UNSET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN], + BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST); } } else { /* if we are not advertising ipv6 prefix as type-5 * nothing to do */ - if (CHECK_FLAG(bgp_vrf->vrf_flags, - BGP_VRF_ADVERTISE_IPV6_IN_EVPN)) { + if (CHECK_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN], + BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST)) { bgp_evpn_withdraw_type5_routes(bgp_vrf, afi, safi); UNSET_FLAG(bgp_vrf->vrf_flags, - BGP_VRF_ADVERTISE_IPV6_IN_EVPN); + BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST); } } @@ -4373,10 +4375,12 @@ void bgp_config_write_evpn_info(struct vty *vty, struct bgp *bgp, afi_t afi, if (bgp->advertise_gw_macip) vty_out(vty, " advertise-default-gw\n"); - if (CHECK_FLAG(bgp->vrf_flags, BGP_VRF_ADVERTISE_IPV4_IN_EVPN)) + if (CHECK_FLAG(bgp->af_flags[AFI_L2VPN][SAFI_EVPN], + BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST)) vty_out(vty, " advertise ipv4 unicast\n"); - if (CHECK_FLAG(bgp->vrf_flags, BGP_VRF_ADVERTISE_IPV6_IN_EVPN)) + if (CHECK_FLAG(bgp->af_flags[AFI_L2VPN][SAFI_EVPN], + BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST)) vty_out(vty, " advertise ipv6 unicast\n"); } diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h index 220b6d989e..5b77be2be9 100644 --- a/bgpd/bgpd.h +++ b/bgpd/bgpd.h @@ -320,6 +320,11 @@ struct bgp { u_int16_t af_flags[AFI_MAX][SAFI_MAX]; #define BGP_CONFIG_DAMPENING (1 << 0) +/* l2vpn evpn flags */ +#define BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST (1 << 0) +#define BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST (1 << 1) + + /* Route table for next-hop lookup cache. */ struct bgp_table *nexthop_cache_table[AFI_MAX]; @@ -431,11 +436,9 @@ struct bgp { /* vrf flags */ uint32_t vrf_flags; #define BGP_VRF_AUTO (1 << 0) -#define BGP_VRF_ADVERTISE_IPV4_IN_EVPN (1 << 1) -#define BGP_VRF_ADVERTISE_IPV6_IN_EVPN (1 << 2) -#define BGP_VRF_IMPORT_RT_CFGD (1 << 3) -#define BGP_VRF_EXPORT_RT_CFGD (1 << 4) -#define BGP_VRF_RD_CFGD (1 << 5) +#define BGP_VRF_IMPORT_RT_CFGD (1 << 1) +#define BGP_VRF_EXPORT_RT_CFGD (1 << 2) +#define BGP_VRF_RD_CFGD (1 << 3) /* unique ID for auto derivation of RD for this vrf */ uint16_t vrf_rd_id; From 486456ca92b9778e7cb8e0b3524dd7f98bdde8f0 Mon Sep 17 00:00:00 2001 From: Mitesh Kanjariya Date: Thu, 15 Feb 2018 17:20:27 -0800 Subject: [PATCH 03/25] bgpd: support for default-originate type-5 route Implement support for 'default-originate' for L2VPN/EVPN address family. This is needed for the case where external routing within a POD, will follow the default route to the border/exit leaf. The border leaf has more than one next hop to forward the packet on to, depending on the destination IP. Signed-off-by: Mitesh Kanjariya --- ...t-for-default-originate-type-5-route.patch | 180 ++++++++++++++++++ bgpd/bgp_evpn_private.h | 14 ++ bgpd/bgp_evpn_vty.c | 89 +++++++++ bgpd/bgpd.h | 2 + 4 files changed, 285 insertions(+) create mode 100644 0001-bgpd-support-for-default-originate-type-5-route.patch diff --git a/0001-bgpd-support-for-default-originate-type-5-route.patch b/0001-bgpd-support-for-default-originate-type-5-route.patch new file mode 100644 index 0000000000..92121082c0 --- /dev/null +++ b/0001-bgpd-support-for-default-originate-type-5-route.patch @@ -0,0 +1,180 @@ +From dbc3fbc612ce6523a596804c270600de1f6f2309 Mon Sep 17 00:00:00 2001 +From: Mitesh Kanjariya +Date: Thu, 15 Feb 2018 17:20:27 -0800 +Subject: [PATCH] bgpd: support for default-originate type-5 route + +Implement support for 'default-originate' for L2VPN/EVPN address family. +This is needed for the case where external routing within a POD, +will follow the default route to the border/exit leaf. +The border/exit leaf has more than one next hop to forward the packet on to, +depending on the destination IP. + +Signed-off-by: Mitesh Kanjariya +--- + bgpd/bgp_evpn_private.h | 14 ++++++++ + bgpd/bgp_evpn_vty.c | 89 +++++++++++++++++++++++++++++++++++++++++++++++++ + bgpd/bgpd.h | 2 ++ + 3 files changed, 105 insertions(+) + +diff --git a/bgpd/bgp_evpn_private.h b/bgpd/bgp_evpn_private.h +index 5ff16c3..bc68e25 100644 +--- a/bgpd/bgp_evpn_private.h ++++ b/bgpd/bgp_evpn_private.h +@@ -349,6 +349,20 @@ static inline void build_evpn_type3_prefix(struct prefix_evpn *p, + p->prefix.ip.ipaddr_v4 = originator_ip; + } + ++static inline int evpn_default_originate_set(struct bgp *bgp, afi_t afi, ++ safi_t safi) ++{ ++ if (afi == AFI_IP && ++ CHECK_FLAG(bgp->af_flags[AFI_L2VPN][SAFI_EVPN], ++ BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4)) ++ return 1; ++ else if (afi == AFI_IP6 && ++ CHECK_FLAG(bgp->af_flags[AFI_L2VPN][SAFI_EVPN], ++ BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6)) ++ return 1; ++ return 0; ++} ++ + extern void evpn_rt_delete_auto(struct bgp*, vni_t, struct list*); + extern void bgp_evpn_configure_export_rt_for_vrf(struct bgp *bgp_vrf, + struct ecommunity *ecomadd); +diff --git a/bgpd/bgp_evpn_vty.c b/bgpd/bgp_evpn_vty.c +index 1720744..5ce71db 100644 +--- a/bgpd/bgp_evpn_vty.c ++++ b/bgpd/bgp_evpn_vty.c +@@ -2476,6 +2476,48 @@ static void evpn_unset_advertise_default_gw(struct bgp *bgp, + /* + * evpn - enable advertisement of default g/w + */ ++static void evpn_process_default_originate_cmd(struct bgp *bgp_vrf, ++ afi_t afi, int add) ++{ ++ struct prefix ip_prefix; ++ safi_t safi = SAFI_UNICAST; /* ipv4/ipv6 unicast */ ++ ++ /* form the default prefix 0.0.0.0/0 */ ++ memset(&ip_prefix, 0, sizeof(struct prefix)); ++ ip_prefix.family = afi2family(afi); ++ ip_prefix.prefixlen = 0; ++ ++ if (add) { ++ /* bail if we are already advertising default route */ ++ if (evpn_default_originate_set(bgp_vrf, afi, safi)) ++ return; ++ ++ if (afi == AFI_IP) ++ SET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN], ++ BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4); ++ else if (afi == AFI_IP6) ++ SET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN], ++ BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6); ++ bgp_evpn_advertise_type5_route(bgp_vrf, &ip_prefix, ++ NULL, afi, safi); ++ } else { ++ /* bail out if we havent advertised the default route */ ++ if (!evpn_default_originate_set(bgp_vrf, afi, safi)) ++ return; ++ if (afi == AFI_IP) ++ UNSET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN], ++ BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4); ++ else if (afi == AFI_IP6) ++ UNSET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN], ++ BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6); ++ bgp_evpn_withdraw_type5_route(bgp_vrf, &ip_prefix, ++ afi, safi); ++ } ++} ++ ++/* ++ * evpn - enable advertisement of default g/w ++ */ + static void evpn_set_advertise_subnet(struct bgp *bgp, + struct bgpevpn *vpn) + { +@@ -2671,6 +2713,43 @@ DEFUN (no_bgp_evpn_advertise_all_vni, + return CMD_SUCCESS; + } + ++DEFUN (bgp_evpn_default_originate, ++ bgp_evpn_default_originate_cmd, ++ "default-originate ", ++ "originate a default route\n" ++ "ipv4 address family\n" ++ "ipv6 address family\n") ++{ ++ afi_t afi = 0; ++ int idx_afi = 0; ++ struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp); ++ ++ if (!bgp_vrf) ++ return CMD_WARNING; ++ argv_find_and_parse_afi(argv, argc, &idx_afi, &afi); ++ evpn_process_default_originate_cmd(bgp_vrf, afi, 1); ++ return CMD_SUCCESS; ++} ++ ++DEFUN (no_bgp_evpn_default_originate, ++ no_bgp_evpn_default_originate_cmd, ++ "no default-originate ", ++ NO_STR ++ "withdraw a default route\n" ++ "ipv4 address family\n" ++ "ipv6 address family\n") ++{ ++ afi_t afi = 0; ++ int idx_afi = 0; ++ struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp); ++ ++ if (!bgp_vrf) ++ return CMD_WARNING; ++ argv_find_and_parse_afi(argv, argc, &idx_afi, &afi); ++ evpn_process_default_originate_cmd(bgp_vrf, afi, 0); ++ return CMD_SUCCESS; ++} ++ + DEFUN (bgp_evpn_advertise_vni_subnet, + bgp_evpn_advertise_vni_subnet_cmd, + "advertise-subnet", +@@ -4382,6 +4461,14 @@ void bgp_config_write_evpn_info(struct vty *vty, struct bgp *bgp, afi_t afi, + if (CHECK_FLAG(bgp->af_flags[AFI_L2VPN][SAFI_EVPN], + BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST)) + vty_out(vty, " advertise ipv6 unicast\n"); ++ ++ if (CHECK_FLAG(bgp->af_flags[AFI_L2VPN][SAFI_EVPN], ++ BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4)) ++ vty_out(vty, " default-originate ipv4\n"); ++ ++ if (CHECK_FLAG(bgp->af_flags[AFI_L2VPN][SAFI_EVPN], ++ BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6)) ++ vty_out(vty, " default-originate ipv6\n"); + } + + void bgp_ethernetvpn_init(void) +@@ -4411,6 +4498,8 @@ void bgp_ethernetvpn_init(void) + install_element(BGP_EVPN_NODE, &no_bgp_evpn_advertise_default_gw_cmd); + install_element(BGP_EVPN_NODE, &bgp_evpn_advertise_type5_cmd); + install_element(BGP_EVPN_NODE, &no_bgp_evpn_advertise_type5_cmd); ++ install_element(BGP_EVPN_NODE, &bgp_evpn_default_originate_cmd); ++ install_element(BGP_EVPN_NODE, &no_bgp_evpn_default_originate_cmd); + + /* "show bgp l2vpn evpn" commands. */ + install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_vni_cmd); +diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h +index 5b77be2..274ca82 100644 +--- a/bgpd/bgpd.h ++++ b/bgpd/bgpd.h +@@ -323,6 +323,8 @@ struct bgp { + /* l2vpn evpn flags */ + #define BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST (1 << 0) + #define BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST (1 << 1) ++#define BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4 (1 << 2) ++#define BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6 (1 << 3) + + + /* Route table for next-hop lookup cache. */ +-- +2.7.4 + diff --git a/bgpd/bgp_evpn_private.h b/bgpd/bgp_evpn_private.h index 5ff16c39e9..bc68e259b6 100644 --- a/bgpd/bgp_evpn_private.h +++ b/bgpd/bgp_evpn_private.h @@ -349,6 +349,20 @@ static inline void build_evpn_type3_prefix(struct prefix_evpn *p, p->prefix.ip.ipaddr_v4 = originator_ip; } +static inline int evpn_default_originate_set(struct bgp *bgp, afi_t afi, + safi_t safi) +{ + if (afi == AFI_IP && + CHECK_FLAG(bgp->af_flags[AFI_L2VPN][SAFI_EVPN], + BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4)) + return 1; + else if (afi == AFI_IP6 && + CHECK_FLAG(bgp->af_flags[AFI_L2VPN][SAFI_EVPN], + BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6)) + return 1; + return 0; +} + extern void evpn_rt_delete_auto(struct bgp*, vni_t, struct list*); extern void bgp_evpn_configure_export_rt_for_vrf(struct bgp *bgp_vrf, struct ecommunity *ecomadd); diff --git a/bgpd/bgp_evpn_vty.c b/bgpd/bgp_evpn_vty.c index 1720744439..5ce71dbf62 100644 --- a/bgpd/bgp_evpn_vty.c +++ b/bgpd/bgp_evpn_vty.c @@ -2473,6 +2473,48 @@ static void evpn_unset_advertise_default_gw(struct bgp *bgp, return; } +/* + * evpn - enable advertisement of default g/w + */ +static void evpn_process_default_originate_cmd(struct bgp *bgp_vrf, + afi_t afi, int add) +{ + struct prefix ip_prefix; + safi_t safi = SAFI_UNICAST; /* ipv4/ipv6 unicast */ + + /* form the default prefix 0.0.0.0/0 */ + memset(&ip_prefix, 0, sizeof(struct prefix)); + ip_prefix.family = afi2family(afi); + ip_prefix.prefixlen = 0; + + if (add) { + /* bail if we are already advertising default route */ + if (evpn_default_originate_set(bgp_vrf, afi, safi)) + return; + + if (afi == AFI_IP) + SET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN], + BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4); + else if (afi == AFI_IP6) + SET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN], + BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6); + bgp_evpn_advertise_type5_route(bgp_vrf, &ip_prefix, + NULL, afi, safi); + } else { + /* bail out if we havent advertised the default route */ + if (!evpn_default_originate_set(bgp_vrf, afi, safi)) + return; + if (afi == AFI_IP) + UNSET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN], + BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4); + else if (afi == AFI_IP6) + UNSET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN], + BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6); + bgp_evpn_withdraw_type5_route(bgp_vrf, &ip_prefix, + afi, safi); + } +} + /* * evpn - enable advertisement of default g/w */ @@ -2671,6 +2713,43 @@ DEFUN (no_bgp_evpn_advertise_all_vni, return CMD_SUCCESS; } +DEFUN (bgp_evpn_default_originate, + bgp_evpn_default_originate_cmd, + "default-originate ", + "originate a default route\n" + "ipv4 address family\n" + "ipv6 address family\n") +{ + afi_t afi = 0; + int idx_afi = 0; + struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp); + + if (!bgp_vrf) + return CMD_WARNING; + argv_find_and_parse_afi(argv, argc, &idx_afi, &afi); + evpn_process_default_originate_cmd(bgp_vrf, afi, 1); + return CMD_SUCCESS; +} + +DEFUN (no_bgp_evpn_default_originate, + no_bgp_evpn_default_originate_cmd, + "no default-originate ", + NO_STR + "withdraw a default route\n" + "ipv4 address family\n" + "ipv6 address family\n") +{ + afi_t afi = 0; + int idx_afi = 0; + struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp); + + if (!bgp_vrf) + return CMD_WARNING; + argv_find_and_parse_afi(argv, argc, &idx_afi, &afi); + evpn_process_default_originate_cmd(bgp_vrf, afi, 0); + return CMD_SUCCESS; +} + DEFUN (bgp_evpn_advertise_vni_subnet, bgp_evpn_advertise_vni_subnet_cmd, "advertise-subnet", @@ -4382,6 +4461,14 @@ void bgp_config_write_evpn_info(struct vty *vty, struct bgp *bgp, afi_t afi, if (CHECK_FLAG(bgp->af_flags[AFI_L2VPN][SAFI_EVPN], BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST)) vty_out(vty, " advertise ipv6 unicast\n"); + + if (CHECK_FLAG(bgp->af_flags[AFI_L2VPN][SAFI_EVPN], + BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4)) + vty_out(vty, " default-originate ipv4\n"); + + if (CHECK_FLAG(bgp->af_flags[AFI_L2VPN][SAFI_EVPN], + BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6)) + vty_out(vty, " default-originate ipv6\n"); } void bgp_ethernetvpn_init(void) @@ -4411,6 +4498,8 @@ void bgp_ethernetvpn_init(void) install_element(BGP_EVPN_NODE, &no_bgp_evpn_advertise_default_gw_cmd); install_element(BGP_EVPN_NODE, &bgp_evpn_advertise_type5_cmd); install_element(BGP_EVPN_NODE, &no_bgp_evpn_advertise_type5_cmd); + install_element(BGP_EVPN_NODE, &bgp_evpn_default_originate_cmd); + install_element(BGP_EVPN_NODE, &no_bgp_evpn_default_originate_cmd); /* "show bgp l2vpn evpn" commands. */ install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_vni_cmd); diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h index 5b77be2be9..274ca82ffc 100644 --- a/bgpd/bgpd.h +++ b/bgpd/bgpd.h @@ -323,6 +323,8 @@ struct bgp { /* l2vpn evpn flags */ #define BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST (1 << 0) #define BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST (1 << 1) +#define BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4 (1 << 2) +#define BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6 (1 << 3) /* Route table for next-hop lookup cache. */ From 6fb219da876ace4732e31005466cae708e512d42 Mon Sep 17 00:00:00 2001 From: Mitesh Kanjariya Date: Wed, 21 Feb 2018 22:02:07 -0800 Subject: [PATCH 04/25] bgpd: provide a match clause to match EVPN default route A Border Leaf can originate a default route for all the leafs within the POD. However, we do not want to advertise this route outside the POD. Therefore, we provide an option to filter a EVPN type5 default route through a route-map. Signed-off-by: Mitesh Kanjariya --- ...t-for-default-originate-type-5-route.patch | 180 ------------------ bgpd/bgp_evpn_private.h | 8 + bgpd/bgp_routemap.c | 44 +++++ 3 files changed, 52 insertions(+), 180 deletions(-) delete mode 100644 0001-bgpd-support-for-default-originate-type-5-route.patch diff --git a/0001-bgpd-support-for-default-originate-type-5-route.patch b/0001-bgpd-support-for-default-originate-type-5-route.patch deleted file mode 100644 index 92121082c0..0000000000 --- a/0001-bgpd-support-for-default-originate-type-5-route.patch +++ /dev/null @@ -1,180 +0,0 @@ -From dbc3fbc612ce6523a596804c270600de1f6f2309 Mon Sep 17 00:00:00 2001 -From: Mitesh Kanjariya -Date: Thu, 15 Feb 2018 17:20:27 -0800 -Subject: [PATCH] bgpd: support for default-originate type-5 route - -Implement support for 'default-originate' for L2VPN/EVPN address family. -This is needed for the case where external routing within a POD, -will follow the default route to the border/exit leaf. -The border/exit leaf has more than one next hop to forward the packet on to, -depending on the destination IP. - -Signed-off-by: Mitesh Kanjariya ---- - bgpd/bgp_evpn_private.h | 14 ++++++++ - bgpd/bgp_evpn_vty.c | 89 +++++++++++++++++++++++++++++++++++++++++++++++++ - bgpd/bgpd.h | 2 ++ - 3 files changed, 105 insertions(+) - -diff --git a/bgpd/bgp_evpn_private.h b/bgpd/bgp_evpn_private.h -index 5ff16c3..bc68e25 100644 ---- a/bgpd/bgp_evpn_private.h -+++ b/bgpd/bgp_evpn_private.h -@@ -349,6 +349,20 @@ static inline void build_evpn_type3_prefix(struct prefix_evpn *p, - p->prefix.ip.ipaddr_v4 = originator_ip; - } - -+static inline int evpn_default_originate_set(struct bgp *bgp, afi_t afi, -+ safi_t safi) -+{ -+ if (afi == AFI_IP && -+ CHECK_FLAG(bgp->af_flags[AFI_L2VPN][SAFI_EVPN], -+ BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4)) -+ return 1; -+ else if (afi == AFI_IP6 && -+ CHECK_FLAG(bgp->af_flags[AFI_L2VPN][SAFI_EVPN], -+ BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6)) -+ return 1; -+ return 0; -+} -+ - extern void evpn_rt_delete_auto(struct bgp*, vni_t, struct list*); - extern void bgp_evpn_configure_export_rt_for_vrf(struct bgp *bgp_vrf, - struct ecommunity *ecomadd); -diff --git a/bgpd/bgp_evpn_vty.c b/bgpd/bgp_evpn_vty.c -index 1720744..5ce71db 100644 ---- a/bgpd/bgp_evpn_vty.c -+++ b/bgpd/bgp_evpn_vty.c -@@ -2476,6 +2476,48 @@ static void evpn_unset_advertise_default_gw(struct bgp *bgp, - /* - * evpn - enable advertisement of default g/w - */ -+static void evpn_process_default_originate_cmd(struct bgp *bgp_vrf, -+ afi_t afi, int add) -+{ -+ struct prefix ip_prefix; -+ safi_t safi = SAFI_UNICAST; /* ipv4/ipv6 unicast */ -+ -+ /* form the default prefix 0.0.0.0/0 */ -+ memset(&ip_prefix, 0, sizeof(struct prefix)); -+ ip_prefix.family = afi2family(afi); -+ ip_prefix.prefixlen = 0; -+ -+ if (add) { -+ /* bail if we are already advertising default route */ -+ if (evpn_default_originate_set(bgp_vrf, afi, safi)) -+ return; -+ -+ if (afi == AFI_IP) -+ SET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN], -+ BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4); -+ else if (afi == AFI_IP6) -+ SET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN], -+ BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6); -+ bgp_evpn_advertise_type5_route(bgp_vrf, &ip_prefix, -+ NULL, afi, safi); -+ } else { -+ /* bail out if we havent advertised the default route */ -+ if (!evpn_default_originate_set(bgp_vrf, afi, safi)) -+ return; -+ if (afi == AFI_IP) -+ UNSET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN], -+ BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4); -+ else if (afi == AFI_IP6) -+ UNSET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN], -+ BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6); -+ bgp_evpn_withdraw_type5_route(bgp_vrf, &ip_prefix, -+ afi, safi); -+ } -+} -+ -+/* -+ * evpn - enable advertisement of default g/w -+ */ - static void evpn_set_advertise_subnet(struct bgp *bgp, - struct bgpevpn *vpn) - { -@@ -2671,6 +2713,43 @@ DEFUN (no_bgp_evpn_advertise_all_vni, - return CMD_SUCCESS; - } - -+DEFUN (bgp_evpn_default_originate, -+ bgp_evpn_default_originate_cmd, -+ "default-originate ", -+ "originate a default route\n" -+ "ipv4 address family\n" -+ "ipv6 address family\n") -+{ -+ afi_t afi = 0; -+ int idx_afi = 0; -+ struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp); -+ -+ if (!bgp_vrf) -+ return CMD_WARNING; -+ argv_find_and_parse_afi(argv, argc, &idx_afi, &afi); -+ evpn_process_default_originate_cmd(bgp_vrf, afi, 1); -+ return CMD_SUCCESS; -+} -+ -+DEFUN (no_bgp_evpn_default_originate, -+ no_bgp_evpn_default_originate_cmd, -+ "no default-originate ", -+ NO_STR -+ "withdraw a default route\n" -+ "ipv4 address family\n" -+ "ipv6 address family\n") -+{ -+ afi_t afi = 0; -+ int idx_afi = 0; -+ struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp); -+ -+ if (!bgp_vrf) -+ return CMD_WARNING; -+ argv_find_and_parse_afi(argv, argc, &idx_afi, &afi); -+ evpn_process_default_originate_cmd(bgp_vrf, afi, 0); -+ return CMD_SUCCESS; -+} -+ - DEFUN (bgp_evpn_advertise_vni_subnet, - bgp_evpn_advertise_vni_subnet_cmd, - "advertise-subnet", -@@ -4382,6 +4461,14 @@ void bgp_config_write_evpn_info(struct vty *vty, struct bgp *bgp, afi_t afi, - if (CHECK_FLAG(bgp->af_flags[AFI_L2VPN][SAFI_EVPN], - BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST)) - vty_out(vty, " advertise ipv6 unicast\n"); -+ -+ if (CHECK_FLAG(bgp->af_flags[AFI_L2VPN][SAFI_EVPN], -+ BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4)) -+ vty_out(vty, " default-originate ipv4\n"); -+ -+ if (CHECK_FLAG(bgp->af_flags[AFI_L2VPN][SAFI_EVPN], -+ BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6)) -+ vty_out(vty, " default-originate ipv6\n"); - } - - void bgp_ethernetvpn_init(void) -@@ -4411,6 +4498,8 @@ void bgp_ethernetvpn_init(void) - install_element(BGP_EVPN_NODE, &no_bgp_evpn_advertise_default_gw_cmd); - install_element(BGP_EVPN_NODE, &bgp_evpn_advertise_type5_cmd); - install_element(BGP_EVPN_NODE, &no_bgp_evpn_advertise_type5_cmd); -+ install_element(BGP_EVPN_NODE, &bgp_evpn_default_originate_cmd); -+ install_element(BGP_EVPN_NODE, &no_bgp_evpn_default_originate_cmd); - - /* "show bgp l2vpn evpn" commands. */ - install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_vni_cmd); -diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h -index 5b77be2..274ca82 100644 ---- a/bgpd/bgpd.h -+++ b/bgpd/bgpd.h -@@ -323,6 +323,8 @@ struct bgp { - /* l2vpn evpn flags */ - #define BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST (1 << 0) - #define BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST (1 << 1) -+#define BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4 (1 << 2) -+#define BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6 (1 << 3) - - - /* Route table for next-hop lookup cache. */ --- -2.7.4 - diff --git a/bgpd/bgp_evpn_private.h b/bgpd/bgp_evpn_private.h index bc68e259b6..4b2742058b 100644 --- a/bgpd/bgp_evpn_private.h +++ b/bgpd/bgp_evpn_private.h @@ -280,6 +280,14 @@ static inline void ip_prefix_from_type5_prefix(struct prefix_evpn *evp, } } +static inline int is_evpn_prefix_default(struct prefix *evp) +{ + if (evp->family != AF_EVPN) + return 0; + + return ((evp->u.prefix_evpn.ip_prefix_length == 0) ? 1 : 0); +} + static inline void ip_prefix_from_type2_prefix(struct prefix_evpn *evp, struct prefix *ip) { diff --git a/bgpd/bgp_routemap.c b/bgpd/bgp_routemap.c index 4d5624d3b0..b3cd4b7af7 100644 --- a/bgpd/bgp_routemap.c +++ b/bgpd/bgp_routemap.c @@ -594,6 +594,24 @@ struct route_map_rule_cmd route_match_ip_route_source_prefix_list_cmd = { route_match_ip_route_source_prefix_list_compile, route_match_ip_route_source_prefix_list_free}; +/* `match evpn default-route' */ + +/* Match function should return 1 if match is success else 0 */ +static route_map_result_t route_match_evpn_default_route(void *rule, + struct prefix *p, + route_map_object_t + type, void *object) +{ + if (type == RMAP_BGP && is_evpn_prefix_default(p)) + return RMAP_MATCH; + + return RMAP_NOMATCH; +} + +/* Route map commands for default-route matching. */ +struct route_map_rule_cmd route_match_evpn_default_route_cmd = { + "evpn default-route", route_match_evpn_default_route, NULL, NULL}; + /* `match mac address MAC_ACCESS_LIST' */ /* Match function should return 1 if match is success else return @@ -3249,6 +3267,29 @@ DEFUN (no_match_evpn_vni, RMAP_EVENT_MATCH_DELETED); } +DEFUN (match_evpn_default_route, + match_evpn_default_route_cmd, + "match evpn default-route", + MATCH_STR + EVPN_HELP_STR + "default EVPN type-5 route\n") +{ + return bgp_route_match_add(vty, "evpn default-route", NULL, + RMAP_EVENT_MATCH_ADDED); +} + +DEFUN (no_match_evpn_default_route, + no_match_evpn_default_route_cmd, + "no match evpn default-route", + NO_STR + MATCH_STR + EVPN_HELP_STR + "default EVPN type-5 route\n") +{ + return bgp_route_match_delete(vty, "evpn default-route", NULL, + RMAP_EVENT_MATCH_DELETED); +} + DEFUN (match_peer, match_peer_cmd, "match peer ", @@ -4628,6 +4669,7 @@ void bgp_route_map_init(void) route_map_install_match(&route_match_mac_address_cmd); route_map_install_match(&route_match_evpn_vni_cmd); route_map_install_match(&route_match_evpn_route_type_cmd); + route_map_install_match(&route_match_evpn_default_route_cmd); route_map_install_set(&route_set_ip_nexthop_cmd); route_map_install_set(&route_set_local_pref_cmd); @@ -4664,6 +4706,8 @@ void bgp_route_map_init(void) install_element(RMAP_NODE, &no_match_evpn_vni_cmd); install_element(RMAP_NODE, &match_evpn_route_type_cmd); install_element(RMAP_NODE, &no_match_evpn_route_type_cmd); + install_element(RMAP_NODE, &match_evpn_default_route_cmd); + install_element(RMAP_NODE, &no_match_evpn_default_route_cmd); install_element(RMAP_NODE, &match_aspath_cmd); install_element(RMAP_NODE, &no_match_aspath_cmd); From 2c29b18a1b327beaddabc11fd8e062310625b574 Mon Sep 17 00:00:00 2001 From: mitesh Date: Tue, 27 Feb 2018 02:19:57 -0800 Subject: [PATCH 05/25] bgpd: reassign the flags in struct bgp af_flags to avoid conflict We have af_flags in struct bgp which holds address family related flags. Seems like we had a conflict between two flags. Signed-off-by: Mitesh Kanjariya --- bgpd/bgpd.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h index bc5350ce24..43d76e5273 100644 --- a/bgpd/bgpd.h +++ b/bgpd/bgpd.h @@ -320,11 +320,11 @@ struct bgp { u_int16_t af_flags[AFI_MAX][SAFI_MAX]; #define BGP_CONFIG_DAMPENING (1 << 0) -/* l2vpn evpn flags */ -#define BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST (1 << 0) -#define BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST (1 << 1) -#define BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4 (1 << 2) -#define BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6 (1 << 3) +/* l2vpn evpn flags - 1 << 0 is used for DAMPENNG */ +#define BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST (1 << 1) +#define BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST (1 << 2) +#define BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4 (1 << 3) +#define BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6 (1 << 4) /* Route table for next-hop lookup cache. */ From 1ec31309bb056e4492ebf50a12e8bb29a9c4b29a Mon Sep 17 00:00:00 2001 From: vivek Date: Wed, 28 Feb 2018 02:07:23 +0000 Subject: [PATCH 06/25] *: EVPN symmetric routing for IPv6 tenant routes Implement support for EVPN symmetric routing for IPv6 routes. The next hop for EVPN routes is the IP address of the remote VTEP which is only an IPv4 address. This means that for IPv6 symmetric routing, there will be IPv6 destinations with IPv4 next hops. To make this work, the IPv4 next hops are converted into IPv4-mapped IPv6 addresses. As part of support, ensure that "L3" route-targets are not announced with IPv6 link-local addresses so that they won't be installed in the routing table. Signed-off-by: Vivek Venkatraman vivek@cumulusnetworks.com Reviewed-by: Mitesh Kanjariya mitesh@cumulusnetworks.com Reviewed-by: Donald Sharp sharpd@cumulusnetworks.com --- bgpd/bgp_evpn.c | 162 +++++++++++++++++++++++--------------------- bgpd/bgp_evpn_vty.c | 2 +- lib/ipaddr.h | 10 +++ zebra/zebra_rib.c | 25 +++++-- zebra/zserv.c | 35 ++++++++-- 5 files changed, 144 insertions(+), 90 deletions(-) diff --git a/bgpd/bgp_evpn.c b/bgpd/bgp_evpn.c index a8ee14c72e..2271aa1005 100644 --- a/bgpd/bgp_evpn.c +++ b/bgpd/bgp_evpn.c @@ -478,6 +478,17 @@ static void derive_rd_rt_for_vni(struct bgp *bgp, struct bgpevpn *vpn) bgp_evpn_derive_auto_rt_export(bgp, vpn); } +/* + * Convert nexthop (remote VTEP IP) into an IPv6 address. + */ +static void evpn_convert_nexthop_to_ipv6(struct attr *attr) +{ + if (BGP_ATTR_NEXTHOP_AFI_IP6(attr)) + return; + ipv4_to_ipv4_mapped_ipv6(&attr->mp_nexthop_global, attr->nexthop); + attr->mp_nexthop_len = IPV6_MAX_BYTELEN; +} + /* * Add (update) or delete MACIP from zebra. */ @@ -626,17 +637,17 @@ static void build_evpn_type5_route_extcomm(struct bgp *bgp_vrf, } /* - * Build extended communities for EVPN route. RT and ENCAP are - * applicable to all routes. - * TODO: currently kernel doesnt support ipv6 routes with ipv4 nexthops. - * This means that we can't do symmetric routing for ipv6 hosts routes - * in the same way as ipv4 host routes. - * We wont attach l3-vni related RTs for ipv6 routes. - * For now, We will only adevrtise ipv4 host routes - * with L3-VNI related ext-comm. + * Build extended communities for EVPN route. + * This function is applicable for type-2 and type-3 routes. The layer-2 RT + * and ENCAP extended communities are applicable for all routes. + * The default gateway extended community and MAC mobility (sticky) extended + * community are added as needed based on passed settings - only for type-2 + * routes. Likewise, the layer-3 RT and Router MAC extended communities are + * added, if present, based on passed settings - only for non-link-local + * type-2 routes. */ static void build_evpn_route_extcomm(struct bgpevpn *vpn, struct attr *attr, - afi_t afi) + int add_l3_ecomm) { struct ecommunity ecom_encap; struct ecommunity ecom_sticky; @@ -666,11 +677,10 @@ static void build_evpn_route_extcomm(struct bgpevpn *vpn, struct attr *attr, for (ALL_LIST_ELEMENTS(vpn->export_rtl, node, nnode, ecom)) attr->ecommunity = ecommunity_merge(attr->ecommunity, ecom); - /* - * only attach l3-vni export rts for ipv4 address family and if we are - * advertising both the labels in type-2 routes + /* Add the export RTs for L3VNI if told to - caller determines + * when this should be done. */ - if (afi == AFI_IP && CHECK_FLAG(vpn->flags, VNI_FLAG_USE_TWO_LABELS)) { + if (add_l3_ecomm) { vrf_export_rtl = bgpevpn_get_vrf_export_rtl(vpn); if (vrf_export_rtl && !list_isempty(vrf_export_rtl)) { for (ALL_LIST_ELEMENTS(vrf_export_rtl, node, nnode, @@ -681,6 +691,7 @@ static void build_evpn_route_extcomm(struct bgpevpn *vpn, struct attr *attr, } } + /* Add MAC mobility (sticky) if needed. */ if (attr->sticky) { seqnum = 0; memset(&ecom_sticky, 0, sizeof(ecom_sticky)); @@ -691,12 +702,8 @@ static void build_evpn_route_extcomm(struct bgpevpn *vpn, struct attr *attr, ecommunity_merge(attr->ecommunity, &ecom_sticky); } - /* - * only attach l3-vni rmac for ipv4 address family and if we are - * advertising both the labels in type-2 routes - */ - if (afi == AFI_IP && !is_zero_mac(&attr->rmac) && - CHECK_FLAG(vpn->flags, VNI_FLAG_USE_TWO_LABELS)) { + /* Add RMAC, if told to. */ + if (add_l3_ecomm) { memset(&ecom_rmac, 0, sizeof(ecom_rmac)); encode_rmac_extcomm(&eval_rmac, &attr->rmac); ecom_rmac.size = 1; @@ -705,6 +712,7 @@ static void build_evpn_route_extcomm(struct bgpevpn *vpn, struct attr *attr, &ecom_rmac); } + /* Add default gateway, if needed. */ if (attr->default_gw) { memset(&ecom_default_gw, 0, sizeof(ecom_default_gw)); encode_default_gw_extcomm(&eval_default_gw); @@ -1269,6 +1277,7 @@ static int update_evpn_route(struct bgp *bgp, struct bgpevpn *vpn, struct bgp_node *rn; struct attr attr; struct attr *attr_new; + int add_l3_ecomm = 0; struct bgp_info *ri; afi_t afi = AFI_L2VPN; safi_t safi = SAFI_EVPN; @@ -1288,15 +1297,23 @@ static int update_evpn_route(struct bgp *bgp, struct bgpevpn *vpn, if (p->prefix.route_type == BGP_EVPN_IMET_ROUTE) attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL); - /* router mac is only needed for type-2 and type-5 routes */ + /* router mac is only needed for type-2 routes here. */ if (p->prefix.route_type == BGP_EVPN_MAC_IP_ROUTE) bgpevpn_get_rmac(vpn, &attr.rmac); vni2label(vpn->vni, &(attr.label)); - /* Set up RT and ENCAP extended community. */ - build_evpn_route_extcomm(vpn, &attr, - IS_EVPN_PREFIX_IPADDR_V4(p) ? - AFI_IP : AFI_IP6); + /* Include L3 VNI related RTs and RMAC for type-2 routes, if they're + * IPv4 or IPv6 global addresses and we're advertising L3VNI with + * these routes. + */ + if (p->prefix.route_type == BGP_EVPN_MAC_IP_ROUTE && + (IS_EVPN_PREFIX_IPADDR_V4(p) || + !IN6_IS_ADDR_LINKLOCAL(&p->prefix.ip.ipaddr_v6)) && + CHECK_FLAG(vpn->flags, VNI_FLAG_USE_TWO_LABELS)) + add_l3_ecomm = 1; + + /* Set up extended community. */ + build_evpn_route_extcomm(vpn, &attr, add_l3_ecomm); /* First, create (or fetch) route node within the VNI. */ /* NOTE: There is no RD here. */ @@ -1478,22 +1495,20 @@ static int update_all_type2_routes(struct bgp *bgp, struct bgpevpn *vpn) struct attr attr; struct attr attr_sticky; struct attr attr_def_gw; - struct attr attr_ip6; - struct attr attr_sticky_ip6; - struct attr attr_def_gw_ip6; + struct attr attr_ip6_ll; struct attr *attr_new; + int add_l3_ecomm = 0; afi = AFI_L2VPN; safi = SAFI_EVPN; memset(&attr, 0, sizeof(struct attr)); memset(&attr_sticky, 0, sizeof(struct attr)); memset(&attr_def_gw, 0, sizeof(struct attr)); - memset(&attr_ip6, 0, sizeof(struct attr)); - memset(&attr_sticky_ip6, 0, sizeof(struct attr)); - memset(&attr_def_gw_ip6, 0, sizeof(struct attr)); + memset(&attr_ip6_ll, 0, sizeof(struct attr)); - /* Build path-attribute - all type-2 routes for this VNI will share the - * same path attribute. + /* Build path-attribute - multiple type-2 routes for this VNI will share + * the same path attribute, but we need separate structures for sticky + * MACs, default gateway and IPv6 link-local addresses (no L3 RT/RMAC). */ bgp_attr_default_set(&attr, BGP_ORIGIN_IGP); bgp_attr_default_set(&attr_sticky, BGP_ORIGIN_IGP); @@ -1512,31 +1527,21 @@ static int update_all_type2_routes(struct bgp *bgp, struct bgpevpn *vpn) attr_def_gw.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4; attr_def_gw.default_gw = 1; bgpevpn_get_rmac(vpn, &attr_def_gw.rmac); - bgp_attr_default_set(&attr_ip6, BGP_ORIGIN_IGP); - bgp_attr_default_set(&attr_sticky_ip6, BGP_ORIGIN_IGP); - bgp_attr_default_set(&attr_def_gw_ip6, BGP_ORIGIN_IGP); - attr_ip6.nexthop = vpn->originator_ip; - attr_ip6.mp_nexthop_global_in = vpn->originator_ip; - attr_ip6.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4; - bgpevpn_get_rmac(vpn, &attr_ip6.rmac); - attr_sticky_ip6.nexthop = vpn->originator_ip; - attr_sticky_ip6.mp_nexthop_global_in = vpn->originator_ip; - attr_sticky_ip6.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4; - attr_sticky_ip6.sticky = 1; - bgpevpn_get_rmac(vpn, &attr_sticky_ip6.rmac); - attr_def_gw_ip6.nexthop = vpn->originator_ip; - attr_def_gw_ip6.mp_nexthop_global_in = vpn->originator_ip; - attr_def_gw_ip6.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4; - attr_def_gw_ip6.default_gw = 1; - bgpevpn_get_rmac(vpn, &attr_def_gw_ip6.rmac); + bgp_attr_default_set(&attr_ip6_ll, BGP_ORIGIN_IGP); + attr_ip6_ll.nexthop = vpn->originator_ip; + attr_ip6_ll.mp_nexthop_global_in = vpn->originator_ip; + attr_ip6_ll.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4; - /* Set up RT, ENCAP and sticky MAC extended community. */ - build_evpn_route_extcomm(vpn, &attr, AFI_IP); - build_evpn_route_extcomm(vpn, &attr_sticky, AFI_IP); - build_evpn_route_extcomm(vpn, &attr_def_gw, AFI_IP); - build_evpn_route_extcomm(vpn, &attr_ip6, AFI_IP6); - build_evpn_route_extcomm(vpn, &attr_sticky_ip6, AFI_IP6); - build_evpn_route_extcomm(vpn, &attr_def_gw_ip6, AFI_IP); + /* Add L3 VNI RTs and RMAC for non IPv6 link-local attributes if + * using L3 VNI for type-2 routes also. + */ + if (CHECK_FLAG(vpn->flags, VNI_FLAG_USE_TWO_LABELS)) + add_l3_ecomm = 1; + + build_evpn_route_extcomm(vpn, &attr, add_l3_ecomm); + build_evpn_route_extcomm(vpn, &attr_sticky, add_l3_ecomm); + build_evpn_route_extcomm(vpn, &attr_def_gw, add_l3_ecomm); + build_evpn_route_extcomm(vpn, &attr_ip6_ll, 0); /* Walk this VNI's route table and update local type-2 routes. For any * routes updated, update corresponding entry in the global table too. @@ -1550,7 +1555,11 @@ static int update_all_type2_routes(struct bgp *bgp, struct bgpevpn *vpn) if (evp->prefix.route_type != BGP_EVPN_MAC_IP_ROUTE) continue; - if (IS_EVPN_PREFIX_IPADDR_V4(evp)) { + if (IS_EVPN_PREFIX_IPADDR_V6(evp) && + IN6_IS_ADDR_LINKLOCAL(&evp->prefix.ip.ipaddr_v6)) + update_evpn_route_entry(bgp, vpn, afi, safi, rn, + &attr_ip6_ll, 0, 1, &ri, 0); + else { if (evpn_route_is_sticky(bgp, rn)) update_evpn_route_entry(bgp, vpn, afi, safi, rn, &attr_sticky, 0, 1, @@ -1562,19 +1571,6 @@ static int update_all_type2_routes(struct bgp *bgp, struct bgpevpn *vpn) else update_evpn_route_entry(bgp, vpn, afi, safi, rn, &attr, 0, 1, &ri, 0); - } else { - if (evpn_route_is_sticky(bgp, rn)) - update_evpn_route_entry(bgp, vpn, afi, safi, rn, - &attr_sticky_ip6, 0, 1, - &ri, 0); - else if (evpn_route_is_def_gw(bgp, rn)) - update_evpn_route_entry(bgp, vpn, afi, safi, rn, - &attr_def_gw_ip6, 0, 1, - &ri, 0); - else - update_evpn_route_entry(bgp, vpn, afi, safi, rn, - &attr_ip6, 0, 1, - &ri, 0); } /* If a local route exists for this prefix, we need to update @@ -1605,11 +1601,9 @@ static int update_all_type2_routes(struct bgp *bgp, struct bgpevpn *vpn) /* Unintern temporary. */ aspath_unintern(&attr.aspath); - aspath_unintern(&attr_ip6.aspath); aspath_unintern(&attr_sticky.aspath); - aspath_unintern(&attr_sticky_ip6.aspath); aspath_unintern(&attr_def_gw.aspath); - aspath_unintern(&attr_def_gw_ip6.aspath); + aspath_unintern(&attr_ip6_ll.aspath); return 0; } @@ -1801,6 +1795,7 @@ static int install_evpn_route_entry_in_vrf(struct bgp *bgp_vrf, { struct bgp_node *rn; struct bgp_info *ri; + struct attr attr; struct attr *attr_new; int ret = 0; struct prefix p; @@ -1836,6 +1831,15 @@ static int install_evpn_route_entry_in_vrf(struct bgp *bgp_vrf, } else return 0; + /* EVPN routes currently only support a IPv4 next hop which corresponds + * to the remote VTEP. When importing into a VRF, if it is IPv6 host + * route, we have to convert the next hop to an IPv4-mapped address + * for the rest of the code to flow through. + */ + bgp_attr_dup(&attr, parent_ri->attr); + if (afi == AFI_IP6) + evpn_convert_nexthop_to_ipv6(&attr); + /* Check if route entry is already present. */ for (ri = rn->info; ri; ri = ri->next) if (ri->extra @@ -1844,7 +1848,7 @@ static int install_evpn_route_entry_in_vrf(struct bgp *bgp_vrf, if (!ri) { /* Add (or update) attribute to hash. */ - attr_new = bgp_attr_intern(parent_ri->attr); + attr_new = bgp_attr_intern(&attr); /* Create new route with its attribute. */ ri = info_make(parent_ri->type, parent_ri->sub_type, 0, @@ -1859,21 +1863,25 @@ static int install_evpn_route_entry_in_vrf(struct bgp *bgp_vrf, } bgp_info_add(rn, ri); } else { - if (attrhash_cmp(ri->attr, parent_ri->attr) + if (attrhash_cmp(ri->attr, &attr) && !CHECK_FLAG(ri->flags, BGP_INFO_REMOVED)) { bgp_unlock_node(rn); return 0; } /* The attribute has changed. */ /* Add (or update) attribute to hash. */ - attr_new = bgp_attr_intern(parent_ri->attr); + attr_new = bgp_attr_intern(&attr); /* Restore route, if needed. */ if (CHECK_FLAG(ri->flags, BGP_INFO_REMOVED)) bgp_info_restore(rn, ri); /* Mark if nexthop has changed. */ - if (!IPV4_ADDR_SAME(&ri->attr->nexthop, &attr_new->nexthop)) + if ((afi == AFI_IP && + !IPV4_ADDR_SAME(&ri->attr->nexthop, &attr_new->nexthop)) || + (afi == AFI_IP6 && + !IPV6_ADDR_SAME(&ri->attr->mp_nexthop_global, + &attr_new->mp_nexthop_global))) SET_FLAG(ri->flags, BGP_INFO_IGP_CHANGED); /* Unintern existing, set to new. */ diff --git a/bgpd/bgp_evpn_vty.c b/bgpd/bgp_evpn_vty.c index f519bb463b..f977760a96 100644 --- a/bgpd/bgp_evpn_vty.c +++ b/bgpd/bgp_evpn_vty.c @@ -2780,7 +2780,7 @@ DEFUN (no_bgp_evpn_advertise_type5, argv_find_and_parse_afi(argv, argc, &idx_afi, &afi); argv_find_and_parse_safi(argv, argc, &idx_safi, &safi); - if (!(afi == AFI_IP) || (afi == AFI_IP6)) { + if (!(afi == AFI_IP || afi == AFI_IP6)) { vty_out(vty, "%%only ipv4 or ipv6 address families are supported"); return CMD_WARNING; diff --git a/lib/ipaddr.h b/lib/ipaddr.h index 98c28008dc..3857b83027 100644 --- a/lib/ipaddr.h +++ b/lib/ipaddr.h @@ -85,4 +85,14 @@ static inline char *ipaddr2str(struct ipaddr *ip, char *buf, int size) } return buf; } + +static inline void ipv4_to_ipv4_mapped_ipv6(struct in6_addr *in6, + struct in_addr in) +{ + u_int32_t addr_type = htonl(0xFFFF); + memset(in6, 0, sizeof(struct in6_addr)); + memcpy((char *)in6 + 8, &addr_type, sizeof(addr_type)); + memcpy((char *)in6 + 12, &in, sizeof(struct in_addr)); +} + #endif /* __IPADDR_H__ */ diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c index 5c316e077f..cc4888f3e7 100644 --- a/zebra/zebra_rib.c +++ b/zebra/zebra_rib.c @@ -305,6 +305,8 @@ struct nexthop *route_entry_nexthop_ipv6_ifindex_add(struct route_entry *re, nexthop->type = NEXTHOP_TYPE_IPV6_IFINDEX; nexthop->gate.ipv6 = *ipv6; nexthop->ifindex = ifindex; + if (CHECK_FLAG(re->flags, ZEBRA_FLAG_EVPN_ROUTE)) + SET_FLAG(nexthop->flags, NEXTHOP_FLAG_ONLINK); route_entry_nexthop_add(re, nexthop); @@ -421,6 +423,10 @@ static int nexthop_active(afi_t afi, struct route_entry *re, re->nexthop_mtu = 0; } + /* Next hops (remote VTEPs) for EVPN routes are fully resolved. */ + if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_EVPN_RVTEP)) + return 1; + /* Skip nexthops that have been filtered out due to route-map */ /* The nexthops are specific to this route and so the same */ /* nexthop for a different route may not have this flag set */ @@ -858,9 +864,7 @@ static unsigned nexthop_active_check(struct route_node *rn, case NEXTHOP_TYPE_IPV4: case NEXTHOP_TYPE_IPV4_IFINDEX: family = AFI_IP; - if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_EVPN_RVTEP)) - SET_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE); - else if (nexthop_active(AFI_IP, re, nexthop, set, rn)) + if (nexthop_active(AFI_IP, re, nexthop, set, rn)) SET_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE); else UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE); @@ -2548,10 +2552,17 @@ void rib_delete(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type, struct ipaddr vtep_ip; memset(&vtep_ip, 0, sizeof(struct ipaddr)); - vtep_ip.ipa_type = IPADDR_V4; - memcpy(&(vtep_ip.ipaddr_v4), - &(tmp_nh->gate.ipv4), - sizeof(struct in_addr)); + if (afi == AFI_IP) { + vtep_ip.ipa_type = IPADDR_V4; + memcpy(&(vtep_ip.ipaddr_v4), + &(tmp_nh->gate.ipv4), + sizeof(struct in_addr)); + } else { + vtep_ip.ipa_type = IPADDR_V6; + memcpy(&(vtep_ip.ipaddr_v6), + &(tmp_nh->gate.ipv6), + sizeof(struct in6_addr)); + } zebra_vxlan_evpn_vrf_route_del(re->vrf_id, rmac, &vtep_ip, p); } diff --git a/zebra/zserv.c b/zebra/zserv.c index 98cb54f7b8..983b04ed91 100644 --- a/zebra/zserv.c +++ b/zebra/zserv.c @@ -1143,6 +1143,7 @@ static int zread_route_add(struct zserv *client, u_short length, struct nexthop *nexthop = NULL; int i, ret; vrf_id_t vrf_id = 0; + struct ipaddr vtep_ip; s = client->ibuf; if (zapi_route_decode(s, &api) < 0) @@ -1173,9 +1174,7 @@ static int zread_route_add(struct zserv *client, u_short length, re, &api_nh->gate.ipv4, NULL, re->vrf_id); break; - case NEXTHOP_TYPE_IPV4_IFINDEX: { - - struct ipaddr vtep_ip; + case NEXTHOP_TYPE_IPV4_IFINDEX: memset(&vtep_ip, 0, sizeof(struct ipaddr)); if (CHECK_FLAG(api.flags, @@ -1208,15 +1207,41 @@ static int zread_route_add(struct zserv *client, u_short length, &api.prefix); } break; - } case NEXTHOP_TYPE_IPV6: nexthop = route_entry_nexthop_ipv6_add( re, &api_nh->gate.ipv6, re->vrf_id); break; case NEXTHOP_TYPE_IPV6_IFINDEX: + memset(&vtep_ip, 0, sizeof(struct ipaddr)); + if (CHECK_FLAG(api.flags, + ZEBRA_FLAG_EVPN_ROUTE)) { + ifindex = + get_l3vni_svi_ifindex(vrf_id); + } else { + ifindex = api_nh->ifindex; + } + nexthop = route_entry_nexthop_ipv6_ifindex_add( - re, &api_nh->gate.ipv6, api_nh->ifindex, + re, &api_nh->gate.ipv6, ifindex, re->vrf_id); + + /* if this an EVPN route entry, + program the nh as neigh + */ + if (CHECK_FLAG(api.flags, + ZEBRA_FLAG_EVPN_ROUTE)) { + SET_FLAG(nexthop->flags, + NEXTHOP_FLAG_EVPN_RVTEP); + vtep_ip.ipa_type = IPADDR_V6; + memcpy(&vtep_ip.ipaddr_v6, + &(api_nh->gate.ipv6), + sizeof(struct in6_addr)); + zebra_vxlan_evpn_vrf_route_add( + vrf_id, + &api.rmac, + &vtep_ip, + &api.prefix); + } break; case NEXTHOP_TYPE_BLACKHOLE: nexthop = route_entry_nexthop_blackhole_add( From 558283638bb50ff24ea28bab89c1bb4c89ccc3dd Mon Sep 17 00:00:00 2001 From: vivek Date: Thu, 1 Mar 2018 19:50:46 +0000 Subject: [PATCH 07/25] lib, zebra: Fix warnings Signed-off-by: Vivek Venkatraman --- lib/ipaddr.h | 1 + zebra/zserv.c | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/ipaddr.h b/lib/ipaddr.h index 3857b83027..e8dbe9cf09 100644 --- a/lib/ipaddr.h +++ b/lib/ipaddr.h @@ -90,6 +90,7 @@ static inline void ipv4_to_ipv4_mapped_ipv6(struct in6_addr *in6, struct in_addr in) { u_int32_t addr_type = htonl(0xFFFF); + memset(in6, 0, sizeof(struct in6_addr)); memcpy((char *)in6 + 8, &addr_type, sizeof(addr_type)); memcpy((char *)in6 + 12, &in, sizeof(struct in_addr)); diff --git a/zebra/zserv.c b/zebra/zserv.c index 983b04ed91..1fc2bfd309 100644 --- a/zebra/zserv.c +++ b/zebra/zserv.c @@ -1190,7 +1190,7 @@ static int zread_route_add(struct zserv *client, u_short length, re->vrf_id); /* if this an EVPN route entry, - program the nh as neigh + * program the nh as neigh */ if (CHECK_FLAG(api.flags, ZEBRA_FLAG_EVPN_ROUTE)) { @@ -1226,7 +1226,7 @@ static int zread_route_add(struct zserv *client, u_short length, re->vrf_id); /* if this an EVPN route entry, - program the nh as neigh + * program the nh as neigh */ if (CHECK_FLAG(api.flags, ZEBRA_FLAG_EVPN_ROUTE)) { From f83f396624b34c5e50241910f6bdbfacb4249559 Mon Sep 17 00:00:00 2001 From: Mladen Sablic Date: Tue, 27 Feb 2018 23:16:45 +0100 Subject: [PATCH 08/25] pimd: mtrace only IGMP sockets Feature of mtrace only IGMP sockets on pim sm and pim ssm interfaces. Modifed IGMP socket creation and show igmp interface command output. Signed-off-by: Mladen Sablic --- pimd/pim_cmd.c | 18 ++++++++++++++++-- pimd/pim_iface.c | 20 +++++++++++++++++++- pimd/pim_igmp.c | 21 +++++++++++++++++---- pimd/pim_igmp.h | 5 ++++- pimd/pim_igmpv2.c | 6 ++++++ pimd/pim_igmpv3.c | 3 +++ 6 files changed, 65 insertions(+), 8 deletions(-) diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index 6002794658..803e7bb013 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -604,11 +604,18 @@ static void igmp_show_interfaces(struct pim_instance *pim, struct vty *vty, json_object_object_add(json, ifp->name, json_row); + if (igmp->mtrace_only) { + json_object_boolean_true_add( + json_row, "mtraceOnly"); + } } else { vty_out(vty, "%-9s %5s %15s %d %7s %11s %8s\n", ifp->name, - if_is_up(ifp) ? "up" : "down", + if_is_up(ifp) + ? (igmp->mtrace_only ? "mtrc" + : "up") + : "down", inet_ntoa(igmp->ifaddr), pim_ifp->igmp_version, igmp->t_igmp_query_timer ? "local" @@ -758,10 +765,17 @@ static void igmp_show_interfaces_single(struct pim_instance *pim, json_object_object_add(json, ifp->name, json_row); + if (igmp->mtrace_only) { + json_object_boolean_true_add( + json_row, "mtraceOnly"); + } } else { vty_out(vty, "Interface : %s\n", ifp->name); vty_out(vty, "State : %s\n", - if_is_up(ifp) ? "up" : "down"); + if_is_up(ifp) + ? (igmp->mtrace_only ? "mtrace" + : "up") + : "down"); vty_out(vty, "Address : %s\n", inet_ntoa(pim_ifp->primary_address)); vty_out(vty, "Uptime : %s\n", uptime); diff --git a/pimd/pim_iface.c b/pimd/pim_iface.c index 998f8fc2ca..ff7238ae97 100644 --- a/pimd/pim_iface.c +++ b/pimd/pim_iface.c @@ -574,7 +574,11 @@ void pim_if_addr_add(struct connected *ifc) /* if addr new, add IGMP socket */ if (ifc->address->family == AF_INET) pim_igmp_sock_add(pim_ifp->igmp_socket_list, - ifaddr, ifp); + ifaddr, ifp, false); + } else if (igmp->mtrace_only) { + igmp_sock_delete(igmp); + pim_igmp_sock_add(pim_ifp->igmp_socket_list, ifaddr, + ifp, false); } /* Replay Static IGMP groups */ @@ -611,6 +615,20 @@ void pim_if_addr_add(struct connected *ifc) } } } /* igmp */ + else { + struct igmp_sock *igmp; + + /* lookup IGMP socket */ + igmp = pim_igmp_sock_lookup_ifaddr(pim_ifp->igmp_socket_list, + ifaddr); + if (ifc->address->family == AF_INET) { + if (igmp) + igmp_sock_delete(igmp); + /* if addr new, add IGMP socket */ + pim_igmp_sock_add(pim_ifp->igmp_socket_list, ifaddr, + ifp, true); + } + } /* igmp mtrace only */ if (PIM_IF_TEST_PIM(pim_ifp->options)) { diff --git a/pimd/pim_igmp.c b/pimd/pim_igmp.c index c0a58516d9..5e1aecc3a3 100644 --- a/pimd/pim_igmp.c +++ b/pimd/pim_igmp.c @@ -281,6 +281,9 @@ static int igmp_recv_query(struct igmp_sock *igmp, int query_version, uint16_t recv_checksum; uint16_t checksum; + if (igmp->mtrace_only) + return 0; + memcpy(&group_addr, igmp_msg + 4, sizeof(struct in_addr)); ifp = igmp->interface; @@ -387,6 +390,9 @@ static int igmp_v1_recv_report(struct igmp_sock *igmp, struct in_addr from, on_trace(__PRETTY_FUNCTION__, igmp->interface, from); + if (igmp->mtrace_only) + return 0; + if (igmp_msg_len != IGMP_V12_MSG_SIZE) { zlog_warn( "Recv IGMP report v1 from %s on %s: size=%d other than correct=%d", @@ -510,7 +516,6 @@ int pim_igmp_packet(struct igmp_sock *igmp, char *buf, size_t len) return igmp_mtrace_recv_response(igmp, ip_hdr, ip_hdr->ip_src, from_str, igmp_msg, igmp_msg_len); - break; case PIM_IGMP_MTRACE_QUERY_REQUEST: return igmp_mtrace_recv_qry_req(igmp, ip_hdr, ip_hdr->ip_src, from_str, igmp_msg, @@ -819,7 +824,7 @@ static int igmp_group_hash_equal(const void *arg1, const void *arg2) } static struct igmp_sock *igmp_sock_new(int fd, struct in_addr ifaddr, - struct interface *ifp) + struct interface *ifp, int mtrace_only) { struct pim_interface *pim_ifp; struct igmp_sock *igmp; @@ -862,6 +867,13 @@ static struct igmp_sock *igmp_sock_new(int fd, struct in_addr ifaddr, pim_ifp->igmp_default_robustness_variable; igmp->sock_creation = pim_time_monotonic_sec(); + if (mtrace_only) { + igmp->mtrace_only = mtrace_only; + return igmp; + } + + igmp->mtrace_only = false; + /* igmp_startup_mode_on() will reset QQI: @@ -919,7 +931,8 @@ static void igmp_read_on(struct igmp_sock *igmp) struct igmp_sock *pim_igmp_sock_add(struct list *igmp_sock_list, struct in_addr ifaddr, - struct interface *ifp) + struct interface *ifp, + bool mtrace_only) { struct pim_interface *pim_ifp; struct igmp_sock *igmp; @@ -934,7 +947,7 @@ struct igmp_sock *pim_igmp_sock_add(struct list *igmp_sock_list, return 0; } - igmp = igmp_sock_new(fd, ifaddr, ifp); + igmp = igmp_sock_new(fd, ifaddr, ifp, mtrace_only); if (!igmp) { zlog_err("%s %s: igmp_sock_new() failure", __FILE__, __PRETTY_FUNCTION__); diff --git a/pimd/pim_igmp.h b/pimd/pim_igmp.h index 962c50e76a..561a127d0f 100644 --- a/pimd/pim_igmp.h +++ b/pimd/pim_igmp.h @@ -90,6 +90,8 @@ struct igmp_sock { int querier_robustness_variable; /* QRV */ int startup_query_count; + bool mtrace_only; + struct list *igmp_group_list; /* list of struct igmp_group */ struct hash *igmp_group_hash; }; @@ -99,7 +101,8 @@ struct igmp_sock *pim_igmp_sock_lookup_ifaddr(struct list *igmp_sock_list, struct igmp_sock *igmp_sock_lookup_by_fd(struct list *igmp_sock_list, int fd); struct igmp_sock *pim_igmp_sock_add(struct list *igmp_sock_list, struct in_addr ifaddr, - struct interface *ifp); + struct interface *ifp, + bool mtrace_only); void igmp_sock_delete(struct igmp_sock *igmp); void igmp_sock_free(struct igmp_sock *igmp); void igmp_sock_delete_all(struct interface *ifp); diff --git a/pimd/pim_igmpv2.c b/pimd/pim_igmpv2.c index efa36e618f..dbbe83a965 100644 --- a/pimd/pim_igmpv2.c +++ b/pimd/pim_igmpv2.c @@ -111,6 +111,9 @@ int igmp_v2_recv_report(struct igmp_sock *igmp, struct in_addr from, on_trace(__PRETTY_FUNCTION__, igmp->interface, from); + if (igmp->mtrace_only) + return 0; + if (igmp_msg_len != IGMP_V12_MSG_SIZE) { zlog_warn( "Recv IGMPv2 REPORT from %s on %s: size=%d other than correct=%d", @@ -154,6 +157,9 @@ int igmp_v2_recv_leave(struct igmp_sock *igmp, struct in_addr from, on_trace(__PRETTY_FUNCTION__, igmp->interface, from); + if (igmp->mtrace_only) + return 0; + if (igmp_msg_len != IGMP_V12_MSG_SIZE) { zlog_warn( "Recv IGMPv2 LEAVE from %s on %s: size=%d other than correct=%d", diff --git a/pimd/pim_igmpv3.c b/pimd/pim_igmpv3.c index ecde546c06..3360e36b4a 100644 --- a/pimd/pim_igmpv3.c +++ b/pimd/pim_igmpv3.c @@ -1874,6 +1874,9 @@ int igmp_v3_recv_report(struct igmp_sock *igmp, struct in_addr from, int local_ncb = 0; struct pim_interface *pim_ifp; + if (igmp->mtrace_only) + return 0; + pim_ifp = igmp->interface->info; if (igmp_msg_len < IGMP_V3_MSG_MIN_SIZE) { From 2b1236a27e7502d0adfc1a137a378983b3a8ebe1 Mon Sep 17 00:00:00 2001 From: Quentin Young Date: Fri, 9 Mar 2018 17:51:42 -0500 Subject: [PATCH 09/25] *: globally ignore clippy-generated source Tired of dealing with this Signed-off-by: Quentin Young --- .gitignore | 3 +++ bgpd/.gitignore | 1 - ldpd/.gitignore | 1 - lib/.gitignore | 1 - ospfd/.gitignore | 1 - sharpd/.gitignore | 1 - zebra/.gitignore | 1 - 7 files changed, 3 insertions(+), 6 deletions(-) diff --git a/.gitignore b/.gitignore index f7c731b4bc..c5fd0ced9b 100644 --- a/.gitignore +++ b/.gitignore @@ -82,3 +82,6 @@ GPATH *.lo compile_commands.json .dirstamp + +# clippy generated source +*_clippy.c diff --git a/bgpd/.gitignore b/bgpd/.gitignore index a97bdb83d3..105be22995 100644 --- a/bgpd/.gitignore +++ b/bgpd/.gitignore @@ -16,4 +16,3 @@ TAGS .arch-ids *~ *.loT -*clippy.c diff --git a/ldpd/.gitignore b/ldpd/.gitignore index eee96c636f..a2f4b51698 100644 --- a/ldpd/.gitignore +++ b/ldpd/.gitignore @@ -15,4 +15,3 @@ TAGS .arch-ids *~ *.loT -ldp_vty_cmds_clippy.c diff --git a/lib/.gitignore b/lib/.gitignore index 94f401ebe6..072146dbd5 100644 --- a/lib/.gitignore +++ b/lib/.gitignore @@ -24,4 +24,3 @@ refix grammar_sandbox clippy defun_lex.c -plist_clippy.c diff --git a/ospfd/.gitignore b/ospfd/.gitignore index f0d800efb4..752c875a62 100644 --- a/ospfd/.gitignore +++ b/ospfd/.gitignore @@ -15,4 +15,3 @@ TAGS *~ *.loT *.a -*clippy.c diff --git a/sharpd/.gitignore b/sharpd/.gitignore index c396f3ef94..cc33cfc188 100644 --- a/sharpd/.gitignore +++ b/sharpd/.gitignore @@ -13,6 +13,5 @@ TAGS .arch-ids *~ *.loT -*clippy.c sharpd sharpd.conf diff --git a/zebra/.gitignore b/zebra/.gitignore index 7a1321e546..4a06756a2d 100644 --- a/zebra/.gitignore +++ b/zebra/.gitignore @@ -13,4 +13,3 @@ TAGS .arch-ids *~ *.loT -zebra_vty_clippy.c From ba85366ad34ae0497df8f4773aae81a567e10256 Mon Sep 17 00:00:00 2001 From: Arthur Jones Date: Fri, 9 Mar 2018 15:08:24 -0800 Subject: [PATCH 10/25] zebra/if_netlink: compile under musl-libc musl-libc is a lightweight libc used by alpine linux: https://www.musl-libc.org/ AFAICT, this is the only change to the source needed to get basic frr support compiling on musl. Two changes in one patch, get ethhdr from netinet/if_ether.h and replace the only __caddr_t I could find in the source base with caddr_t. Testing done: Compiled apk packages using a docker environment (patches coming soon) also compiled redhat and debian using a similar docker environment (RFC patches for those changes are queued up too)... Issue: https://github.com/FRRouting/frr/issues/1859 Signed-off-by: Arthur Jones --- zebra/if_netlink.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/zebra/if_netlink.c b/zebra/if_netlink.c index bb0a0e052e..a37d74416b 100644 --- a/zebra/if_netlink.c +++ b/zebra/if_netlink.c @@ -30,6 +30,7 @@ */ #define _LINUX_IN6_H +#include #include #include #include @@ -362,7 +363,7 @@ static int get_iflink_speed(struct interface *interface) /* initialize ethtool interface */ memset(&ecmd, 0, sizeof(ecmd)); ecmd.cmd = ETHTOOL_GSET; /* ETHTOOL_GLINK */ - ifdata.ifr_data = (__caddr_t)&ecmd; + ifdata.ifr_data = (caddr_t)&ecmd; /* use ioctl to get IP address of an interface */ if (zserv_privs.change(ZPRIVS_RAISE)) From c737c7bab3a598c231ceee1d9fed7afec88f5bbf Mon Sep 17 00:00:00 2001 From: Arthur Jones Date: Sun, 11 Mar 2018 10:32:24 -0700 Subject: [PATCH 11/25] alpine: minimal alpine packaging For building dev packages for alpine, we provide a minimal APKBUILD file and add a configure option for only numeric versions in the VERSION variable as alpine does not allow non-numeric characters in the version string. These changes allow alpine to be built, but don't yet provide a mechanism to build. Changes to do the build in docker are coming soon... Testing done: Built alpine packages in local docker environment, packages showed no "dev" in the package name. Also built CentOS packages with numeric version disabled and the "dev" is still in the package name. Issue: https://github.com/FRRouting/frr/issues/1859 Signed-off-by: Arthur Jones --- alpine/APKBUILD.in | 36 ++++++++++++++++++++++++++++++++++++ configure.ac | 11 +++++++++++ 2 files changed, 47 insertions(+) create mode 100644 alpine/APKBUILD.in diff --git a/alpine/APKBUILD.in b/alpine/APKBUILD.in new file mode 100644 index 0000000000..33c2859245 --- /dev/null +++ b/alpine/APKBUILD.in @@ -0,0 +1,36 @@ +# Maintainer: Arthur Jones +pkgname=frr +pkgver=@VERSION@ +pkgrel=0 +pkgdesc="Free Range Routing is a fork of quagga" +url="https://frrouting.org/" +arch="all" +license="GPL-2.0" +depends="iproute2 json-c c-ares ipsec-tools iproute2" +makedepends="ncurses-dev net-snmp-dev gawk texinfo perl + acct autoconf automake bash + binutils binutils-libs bison bsd-compat-headers build-base + c-ares c-ares-dev ca-certificates cryptsetup-libs curl + device-mapper-libs expat fakeroot flex fortify-headers gdbm + git gmp isl json-c-dev kmod lddtree libacl libatomic libattr + libblkid libburn libbz2 libc-dev libcap libcurl libedit libffi libgcc + libgomp libisoburn libisofs libltdl libressl libssh2 + libstdc++ libtool libuuid linux-headers lzip lzo m4 make mkinitfs mpc1 + mpfr3 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" +subpackages="$pkgname-dev $pkgname-doc $pkgname-dbg" +source="$pkgname-$pkgver.tar.gz" + +builddir="$srcdir"/$pkgname-$pkgver + +build() { + cd "$builddir" + ./configure --prefix=/usr || return 1 + make || return 1 +} + +package() { + cd "$builddir" + make DESTDIR="$pkgdir" install || return 1 +} diff --git a/configure.ac b/configure.ac index 0d6c99acfa..e85d19f687 100755 --- a/configure.ac +++ b/configure.ac @@ -396,6 +396,8 @@ AC_ARG_ENABLE(rpki, AS_HELP_STRING([--enable-rpki], [enable RPKI prefix validation support])) AC_ARG_ENABLE([clippy-only], AS_HELP_STRING([--enable-clippy-only], [Only build clippy])) +AC_ARG_ENABLE([numeric_version], + AS_HELP_STRING([--enable-numeric-version], [Only numeric digits allowed in version (for Alpine)])) AS_IF([test "${enable_clippy_only}" != "yes"], [ AC_CHECK_HEADERS(json-c/json.h) @@ -647,6 +649,14 @@ AC_DEFINE_UNQUOTED(MULTIPATH_NUM, $MPATH_NUM, Maximum number of paths for a rout AC_DEFINE_UNQUOTED(VTYSH_PAGER, "$VTYSH_PAGER", [What pager to use]) +dnl ------------------------------------ +dnl Alpine only accepts numeric versions +dnl ------------------------------------ +if test "x${enable_numeric_version}" != "x" ; then + VERSION="`echo ${VERSION} | tr -c -d '[[.0-9]]'`" + PACKAGE_VERSION="`echo ${PACKAGE_VERSION} | tr -c -d '[[.0-9]]'`" +fi + dnl ----------------------------------- dnl Add extra version string to package dnl name, string and version fields. @@ -1872,6 +1882,7 @@ AC_CONFIG_FILES([Makefile redhat/frr.spec debianpkg/Makefile debianpkg/changelog + alpine/APKBUILD snapcraft/snapcraft.yaml lib/version.h tests/lib/cli/test_cli.refout From 688818844fe662dea093082c2717481779319f43 Mon Sep 17 00:00:00 2001 From: Quentin Young Date: Fri, 9 Mar 2018 12:07:25 -0500 Subject: [PATCH 12/25] lib: add convenience debugging macros * Add DEBUG*() macros This set of macros allows you to write printf-like debugging lines that automatically check whether a debug is on before printing. This should eliminate the need for explicit checks in simple cases. For example: if (SUCH_AND_SUCH_DEBUG_IS_ON) { zlog_warn(...); } Becomes: DEBUG(warn, such_and_such, ...); Or, equivalently, DEBUGE(such_and_such, ...); The levels passed to DEBUG are expanded into the names of zlog_* functions, so the same zlog levels are available. There's also a set of macros that have the level built into them; DEBUGE for errors, DEBUGW for warnings, etc. Good for brevity. * Add singular setting macros Change the 'SET' macros to accept a boolean indicating whether the provided bits should be set or unset, and map on/off macros to them. Helps condense code where you already have a boolean condition that tells you what you want to do as you can avoid writing the branch. Signed-off-by: Quentin Young --- lib/debug.h | 92 ++++++++++++++++++++++++++++++++--------------------- 1 file changed, 55 insertions(+), 37 deletions(-) diff --git a/lib/debug.h b/lib/debug.h index 3e6772aacf..d0fa27d3fe 100644 --- a/lib/debug.h +++ b/lib/debug.h @@ -104,76 +104,77 @@ struct debug_callbacks { * * MT-Safe */ -#define DEBUG_MODE_CHECK(name, type) \ - CHECK_FLAG_ATOMIC(&(name)->flags, (type)&DEBUG_MODE_ALL) +#define DEBUG_MODE_CHECK(name, mode) \ + CHECK_FLAG_ATOMIC(&(name)->flags, (mode)&DEBUG_MODE_ALL) /* * Check if an option bit is set for a debug. * * MT-Safe */ -#define DEBUG_OPT_CHECK(name, type) \ - CHECK_FLAG_ATOMIC(&(name)->flags, (type)&DEBUG_OPT_ALL) +#define DEBUG_OPT_CHECK(name, opt) \ + CHECK_FLAG_ATOMIC(&(name)->flags, (opt)&DEBUG_OPT_ALL) /* * Check if bits are set for a debug. * * MT-Safe */ -#define DEBUG_FLAGS_CHECK(name, type) CHECK_FLAG_ATOMIC(&(name)->flags, (type)) - -/* - * Check if any mode is on for a debug. - * - * MT-Safe - */ -#define DEBUG(name) DEBUG_MODE_CHECK((name), DEBUG_MODE_ALL) +#define DEBUG_FLAGS_CHECK(name, fl) CHECK_FLAG_ATOMIC(&(name)->flags, (fl)) /* * Set modes on a debug. * * MT-Safe */ -#define DEBUG_MODE_SET(name, type) \ - SET_FLAG_ATOMIC(&(name)->flags, (type)&DEBUG_MODE_ALL) +#define DEBUG_MODE_SET(name, mode, onoff) \ + do { \ + if (onoff) \ + SET_FLAG_ATOMIC(&(name)->flags, \ + (mode)&DEBUG_MODE_ALL); \ + else \ + UNSET_FLAG_ATOMIC(&(name)->flags, \ + (mode)&DEBUG_MODE_ALL); \ + } while (0) -/* - * Unset modes on a debug. - * - * MT-Safe - */ -#define DEBUG_MODE_UNSET(name, type) \ - UNSET_FLAG_ATOMIC(&(name)->flags, (type)&DEBUG_MODE_ALL) +/* Convenience macros for specific set operations. */ +#define DEBUG_MODE_ON(name, mode) DEBUG_MODE_SET(name, mode, true) +#define DEBUG_MODE_OFF(name, mode) DEBUG_MODE_SET(name, mode, false) /* * Set options on a debug. * * MT-Safe */ -#define DEBUG_OPT_SET(name, type) \ - SET_FLAG_ATOMIC(&(name)->flags, (type)&DEBUG_OPT_ALL) +#define DEBUG_OPT_SET(name, opt, onoff) \ + do { \ + if (onoff) \ + SET_FLAG_ATOMIC(&(name)->flags, (opt)&DEBUG_OPT_ALL); \ + else \ + UNSET_FLAG_ATOMIC(&(name)->flags, \ + (opt)&DEBUG_OPT_ALL); \ + } while (0) -/* - * Unset options on a debug. - * - * MT-Safe - */ -#define DEBUG_OPT_UNSET(name, type) \ - UNSET_FLAG_ATOMIC(&(name)->flags, (type)&DEBUG_OPT_ALL) +/* Convenience macros for specific set operations. */ +#define DEBUG_OPT_ON(name, opt) DEBUG_OPT_SET(name, opt, true) +#define DEBUG_OPT_OFF(name, opt) DEBUG_OPT_SET(name, opt, true) /* * Set bits on a debug. * * MT-Safe */ -#define DEBUG_FLAGS_SET(name, type) SET_FLAG_ATOMIC(&(name)->flags, (type)) +#define DEBUG_FLAGS_SET(name, fl, onoff) \ + do { \ + if (onoff) \ + SET_FLAG_ATOMIC(&(name)->flags, (fl)); \ + else \ + UNSET_FLAG_ATOMIC(&(name)->flags, (fl)); \ + } while (0) -/* - * Unset bits on a debug. - * - * MT-Safe - */ -#define DEBUG_FLAGS_UNSET(name, type) UNSET_FLAG_ATOMIC(&(name)->flags, (type)) +/* Convenience macros for specific set operations. */ +#define DEBUG_FLAGS_ON(name, fl) DEBUG_FLAGS_SET(&(name)->flags, (type), true) +#define DEBUG_FLAGS_OFF(name, fl) DEBUG_FLAGS_SET(&(name)->flags, (type), false) /* * Unset all modes and options on a debug. @@ -201,6 +202,23 @@ struct debug_callbacks { #define DEBUG_NODE2MODE(vtynode) \ (((vtynode) == CONFIG_NODE) ? DEBUG_MODE_ALL : DEBUG_MODE_TERM) +/* + * Debug at the given level to the default logging destination. + * + * MT-Safe + */ +#define DEBUG(level, name, fmt, ...) \ + do { \ + if (DEBUG_MODE_CHECK(name, DEBUG_MODE_ALL)) \ + zlog_##level(fmt, ##__VA_ARGS__); \ + } while (0) + +/* Convenience macros for the various levels. */ +#define DEBUGE(name, fmt, ...) DEBUG(err, name, fmt, ##__VA_ARGS__) +#define DEBUGW(name, fmt, ...) DEBUG(warn, name, fmt, ##__VA_ARGS__) +#define DEBUGI(name, fmt, ...) DEBUG(info, name, fmt, ##__VA_ARGS__) +#define DEBUGN(name, fmt, ...) DEBUG(notice, name, fmt, ##__VA_ARGS__) +#define DEBUGD(name, fmt, ...) DEBUG(debug, name, fmt, ##__VA_ARGS__) /* * Optional initializer for debugging. Highly recommended. From 12cd053cd64904425cb19f4b3e5fb154a9a713e8 Mon Sep 17 00:00:00 2001 From: Arthur Jones Date: Mon, 12 Mar 2018 16:32:23 +0000 Subject: [PATCH 13/25] docs/install.texi: document --enable-numeric-version Document the configure option to strip non-numeric characters from the version string. Testing done: Build alpine packages in docker, run texinfo on the doc apk package. Issue: https://github.com/FRRouting/frr/issues/1859 Signed-off-by: Arthur Jones --- doc/install.texi | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/doc/install.texi b/doc/install.texi index d0d56804b0..e6d4be61dd 100644 --- a/doc/install.texi +++ b/doc/install.texi @@ -109,6 +109,10 @@ of grammar sandbox. Turn on some compile options to allow you to run fuzzing tools against the system. This tools is intended as a developer only tool and should not be used for normal operations +@item --enable-numeric-version +Alpine Linux does not allow non-numeric characters in the version +string. With this option, we provide a way to strip out these +characters for apk dev package builds. @end table You may specify any combination of the above options to the configure From 2cf63c35614034ef83fe2a561cf79a638366cc5b Mon Sep 17 00:00:00 2001 From: Quentin Young Date: Mon, 12 Mar 2018 14:01:47 -0400 Subject: [PATCH 14/25] lib: fixup zlog_hexdump * Allocate correct amount of memory * Use snprintf() instead of sprintf() Signed-off-by: Quentin Young --- lib/log.c | 39 +++++++++++++++++++++++---------------- 1 file changed, 23 insertions(+), 16 deletions(-) diff --git a/lib/log.c b/lib/log.c index 9e33ef9102..5537d8d721 100644 --- a/lib/log.c +++ b/lib/log.c @@ -1092,41 +1092,48 @@ void zlog_hexdump(const void *mem, unsigned int len) unsigned long i = 0; unsigned int j = 0; unsigned int columns = 8; - char buf[(len * 4) + ((len / 4) * 20) + 30]; + /* 19 bytes for 0xADDRESS: */ + /* 24 bytes for data; 2 chars plus a space per data byte */ + /* 1 byte for space */ + /* 8 bytes for ASCII representation */ + /* 1 byte for a newline */ + /* ===================== */ + /* 53 bytes per 8 bytes of data */ + /* 1 byte for null term */ + size_t bs = ((len / 8) + 1) * 53 + 1; + char buf[bs]; char *s = buf; for (i = 0; i < len + ((len % columns) ? (columns - len % columns) : 0); i++) { /* print offset */ if (i % columns == 0) - s += sprintf(s, "0x%016lx: ", (unsigned long)mem + i); + s += snprintf(s, bs - (s - buf), + "0x%016lx: ", (unsigned long)mem + i); /* print hex data */ if (i < len) - s += sprintf(s, "%02x ", 0xFF & ((const char *)mem)[i]); + s += snprintf(s, bs - (s - buf), "%02x ", + 0xFF & ((const char *)mem)[i]); /* end of block, just aligning for ASCII dump */ else - s += sprintf(s, " "); + s += snprintf(s, bs - (s - buf), " "); /* print ASCII dump */ if (i % columns == (columns - 1)) { for (j = i - (columns - 1); j <= i; j++) { - if (j >= len) /* end of block, not really - printing */ - s += sprintf(s, " "); - - else if (isprint((int)((const char *)mem) - [j])) /* printable char - */ - s += sprintf( - s, "%c", + /* end of block not really printing */ + if (j >= len) + s += snprintf(s, bs - (s - buf), " "); + else if (isprint((int)((const char *)mem)[j])) + s += snprintf( + s, bs - (s - buf), "%c", 0xFF & ((const char *)mem)[j]); - else /* other char */ - s += sprintf(s, "."); + s += snprintf(s, bs - (s - buf), "."); } - s += sprintf(s, "\n"); + s += snprintf(s, bs - (s - buf), "\n"); } } zlog_debug("\n%s", buf); From 3fc174e18c080416932fff5e8cb3a08f0d9f8660 Mon Sep 17 00:00:00 2001 From: Quentin Young Date: Mon, 12 Mar 2018 14:04:56 -0400 Subject: [PATCH 15/25] tests: add unit test for zlog Just tests zlog_hexdump right now Signed-off-by: Quentin Young --- lib/log.c | 18 +++++++------ tests/Makefile.am | 6 ++++- tests/lib/test_zlog.c | 61 ++++++++++++++++++++++++++++++++++++++++++ tests/lib/test_zlog.py | 4 +++ 4 files changed, 80 insertions(+), 9 deletions(-) create mode 100644 tests/lib/test_zlog.c create mode 100644 tests/lib/test_zlog.py diff --git a/lib/log.c b/lib/log.c index 5537d8d721..f6dfa10923 100644 --- a/lib/log.c +++ b/lib/log.c @@ -1092,14 +1092,16 @@ void zlog_hexdump(const void *mem, unsigned int len) unsigned long i = 0; unsigned int j = 0; unsigned int columns = 8; - /* 19 bytes for 0xADDRESS: */ - /* 24 bytes for data; 2 chars plus a space per data byte */ - /* 1 byte for space */ - /* 8 bytes for ASCII representation */ - /* 1 byte for a newline */ - /* ===================== */ - /* 53 bytes per 8 bytes of data */ - /* 1 byte for null term */ + /* + * 19 bytes for 0xADDRESS: + * 24 bytes for data; 2 chars plus a space per data byte + * 1 byte for space + * 8 bytes for ASCII representation + * 1 byte for a newline + * ===================== + * 53 bytes per 8 bytes of data + * 1 byte for null term + */ size_t bs = ((len / 8) + 1) * 53 + 1; char buf[bs]; char *s = buf; diff --git a/tests/Makefile.am b/tests/Makefile.am index f4ab2a126a..0c9a5684da 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -73,6 +73,7 @@ check_PROGRAMS = \ lib/test_timer_correctness \ lib/test_timer_performance \ lib/test_ttable \ + lib/test_zlog \ lib/cli/test_cli \ lib/cli/test_commands \ $(TESTS_BGPD) \ @@ -115,9 +116,9 @@ lib_test_heavy_SOURCES = lib/test_heavy.c helpers/c/main.c lib_test_memory_SOURCES = lib/test_memory.c lib_test_nexthop_iter_SOURCES = lib/test_nexthop_iter.c helpers/c/prng.c lib_test_privs_SOURCES = lib/test_privs.c +lib_test_ringbuf_SOURCES = lib/test_ringbuf.c lib_test_srcdest_table_SOURCES = lib/test_srcdest_table.c \ helpers/c/prng.c -lib_test_ringbuf_SOURCES = lib/test_ringbuf.c lib_test_segv_SOURCES = lib/test_segv.c lib_test_sig_SOURCES = lib/test_sig.c lib_test_stream_SOURCES = lib/test_stream.c @@ -127,6 +128,7 @@ lib_test_timer_correctness_SOURCES = lib/test_timer_correctness.c \ lib_test_timer_performance_SOURCES = lib/test_timer_performance.c \ helpers/c/prng.c lib_test_ttable_SOURCES = lib/test_ttable.c +lib_test_zlog_SOURCES = lib/test_zlog.c lib_test_zmq_SOURCES = lib/test_zmq.c lib_test_zmq_CFLAGS = $(AM_CFLAGS) $(ZEROMQ_CFLAGS) lib_cli_test_cli_SOURCES = lib/cli/test_cli.c lib/cli/common_cli.c @@ -167,6 +169,7 @@ lib_test_table_LDADD = $(ALL_TESTS_LDADD) -lm lib_test_timer_correctness_LDADD = $(ALL_TESTS_LDADD) lib_test_timer_performance_LDADD = $(ALL_TESTS_LDADD) lib_test_ttable_LDADD = $(ALL_TESTS_LDADD) +lib_test_zlog_LDADD = $(ALL_TESTS_LDADD) lib_test_zmq_LDADD = ../lib/libfrrzmq.la $(ALL_TESTS_LDADD) $(ZEROMQ_LIBS) lib_cli_test_cli_LDADD = $(ALL_TESTS_LDADD) lib_cli_test_commands_LDADD = $(ALL_TESTS_LDADD) @@ -207,6 +210,7 @@ EXTRA_DIST = \ lib/test_timer_correctness.py \ lib/test_ttable.py \ lib/test_ttable.refout \ + lib/test_zlog.py \ ospf6d/test_lsdb.py \ ospf6d/test_lsdb.in \ ospf6d/test_lsdb.refout \ diff --git a/tests/lib/test_zlog.c b/tests/lib/test_zlog.c new file mode 100644 index 0000000000..790e65cfe9 --- /dev/null +++ b/tests/lib/test_zlog.c @@ -0,0 +1,61 @@ +/* + * Zlog tests. + * Copyright (C) 2018 Cumulus Networks, Inc. + * Quentin Young + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * 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 + */ +#include +#include +#include "log.h" + +/* maximum amount of data to hexdump */ +#define MAXDATA 16384 + +/* + * Test hexdump functionality. + * + * At the moment, not crashing is considered success. + */ +static bool test_zlog_hexdump(void) +{ + unsigned int nl = 1; + + do { + long d[nl]; + + for (unsigned int i = 0; i < nl; i++) + d[i] = random(); + zlog_hexdump(d, nl * sizeof(long)); + } while (++nl * sizeof(long) <= MAXDATA); + + return true; +} + +bool (*tests[])(void) = { + test_zlog_hexdump, +}; + +int main(int argc, char **argv) +{ + openzlog("testzlog", "NONE", 0, LOG_CONS | LOG_NDELAY | LOG_PID, + LOG_ERR); + zlog_set_file("test_zlog.log", LOG_DEBUG); + + for (unsigned int i = 0; i < array_size(tests); i++) + if (!tests[i]()) + return 1; + return 0; +} diff --git a/tests/lib/test_zlog.py b/tests/lib/test_zlog.py new file mode 100644 index 0000000000..2ca2585886 --- /dev/null +++ b/tests/lib/test_zlog.py @@ -0,0 +1,4 @@ +import frrtest + +class TestZlog(frrtest.TestMultiOut): + program = './test_zlog' From 8068a649a79409737dfa5235a84915b544d4fff7 Mon Sep 17 00:00:00 2001 From: Quentin Young Date: Tue, 6 Mar 2018 17:01:42 -0500 Subject: [PATCH 16/25] zebra: dont return a status code in zapi handlers All of the ZAPI message handlers return an integer that means different things to each of them, but nobody ever reads these integers, so this is technical debt that we can just eliminate outright. Signed-off-by: Quentin Young --- zebra/zebra_mroute.c | 5 +- zebra/zebra_mroute.h | 4 +- zebra/zebra_ptm.c | 28 +++--- zebra/zebra_ptm.h | 10 +- zebra/zebra_vxlan.c | 88 +++++++++--------- zebra/zebra_vxlan.h | 30 +++--- zebra/zebra_vxlan_null.c | 20 ++-- zebra/zserv.c | 194 +++++++++++++++++++-------------------- 8 files changed, 188 insertions(+), 191 deletions(-) diff --git a/zebra/zebra_mroute.c b/zebra/zebra_mroute.c index e9cd19ebe0..1143451d62 100644 --- a/zebra/zebra_mroute.c +++ b/zebra/zebra_mroute.c @@ -32,8 +32,8 @@ #include "zebra/rt.h" #include "zebra/debug.h" -int zebra_ipmr_route_stats(struct zserv *client, u_short length, - struct zebra_vrf *zvrf) +void zebra_ipmr_route_stats(struct zserv *client, u_short length, + struct zebra_vrf *zvrf) { struct mcast_route_data mroute; struct stream *s; @@ -69,5 +69,4 @@ stream_failure: stream_putw_at(s, 0, stream_get_endp(s)); zebra_server_send_message(client); - return 0; } diff --git a/zebra/zebra_mroute.h b/zebra/zebra_mroute.h index 616c3a83ab..5bee7b03d6 100644 --- a/zebra/zebra_mroute.h +++ b/zebra/zebra_mroute.h @@ -28,7 +28,7 @@ struct mcast_route_data { unsigned long long lastused; }; -int zebra_ipmr_route_stats(struct zserv *client, u_short length, - struct zebra_vrf *zvf); +void zebra_ipmr_route_stats(struct zserv *client, u_short length, + struct zebra_vrf *zvf); #endif diff --git a/zebra/zebra_ptm.c b/zebra/zebra_ptm.c index f6775fa0b1..b0295d127e 100644 --- a/zebra/zebra_ptm.c +++ b/zebra/zebra_ptm.c @@ -661,8 +661,8 @@ int zebra_ptm_sock_read(struct thread *thread) } /* BFD peer/dst register/update */ -int zebra_ptm_bfd_dst_register(struct zserv *client, u_short length, - int command, struct zebra_vrf *zvrf) +void zebra_ptm_bfd_dst_register(struct zserv *client, u_short length, + int command, struct zebra_vrf *zvrf) { struct stream *s; struct prefix src_p; @@ -693,7 +693,7 @@ int zebra_ptm_bfd_dst_register(struct zserv *client, u_short length, ptm_cb.t_timer = NULL; thread_add_timer(zebrad.master, zebra_ptm_connect, NULL, ptm_cb.reconnect_time, &ptm_cb.t_timer); - return -1; + return; } ptm_lib_init_msg(ptm_hdl, 0, PTMLIB_MSG_TYPE_CMD, NULL, &out_ctxt); @@ -816,16 +816,16 @@ int zebra_ptm_bfd_dst_register(struct zserv *client, u_short length, ptm_cb.out_data); zebra_ptm_send_message(ptm_cb.out_data, data_len); - return 0; + return; stream_failure: ptm_lib_cleanup_msg(ptm_hdl, out_ctxt); - return 0; + return; } /* BFD peer/dst deregister */ -int zebra_ptm_bfd_dst_deregister(struct zserv *client, u_short length, - struct zebra_vrf *zvrf) +void zebra_ptm_bfd_dst_deregister(struct zserv *client, u_short length, + struct zebra_vrf *zvrf) { struct stream *s; struct prefix src_p; @@ -849,7 +849,7 @@ int zebra_ptm_bfd_dst_deregister(struct zserv *client, u_short length, ptm_cb.t_timer = NULL; thread_add_timer(zebrad.master, zebra_ptm_connect, NULL, ptm_cb.reconnect_time, &ptm_cb.t_timer); - return -1; + return; } ptm_lib_init_msg(ptm_hdl, 0, PTMLIB_MSG_TYPE_CMD, NULL, &out_ctxt); @@ -948,15 +948,15 @@ int zebra_ptm_bfd_dst_deregister(struct zserv *client, u_short length, zebra_ptm_send_message(ptm_cb.out_data, data_len); - return 0; + return; stream_failure: ptm_lib_cleanup_msg(ptm_hdl, out_ctxt); - return 0; + return; } /* BFD client register */ -int zebra_ptm_bfd_client_register(struct zserv *client, u_short length) +void zebra_ptm_bfd_client_register(struct zserv *client, u_short length) { struct stream *s; unsigned int pid; @@ -977,7 +977,7 @@ int zebra_ptm_bfd_client_register(struct zserv *client, u_short length) ptm_cb.t_timer = NULL; thread_add_timer(zebrad.master, zebra_ptm_connect, NULL, ptm_cb.reconnect_time, &ptm_cb.t_timer); - return -1; + return; } ptm_lib_init_msg(ptm_hdl, 0, PTMLIB_MSG_TYPE_CMD, NULL, &out_ctxt); @@ -1003,7 +1003,7 @@ int zebra_ptm_bfd_client_register(struct zserv *client, u_short length) SET_FLAG(ptm_cb.client_flags[client->proto], ZEBRA_PTM_BFD_CLIENT_FLAG_REG); - return 0; + return; stream_failure: /* @@ -1013,7 +1013,7 @@ stream_failure: * if (out_ctxt) * ptm_lib_cleanup_msg(ptm_hdl, out_ctxt); */ - return 0; + return; } /* BFD client deregister */ diff --git a/zebra/zebra_ptm.h b/zebra/zebra_ptm.h index 392853b599..2397d53845 100644 --- a/zebra/zebra_ptm.h +++ b/zebra/zebra_ptm.h @@ -62,12 +62,12 @@ int zebra_ptm_connect(struct thread *t); void zebra_ptm_write(struct vty *vty); int zebra_ptm_get_enable_state(void); -int zebra_ptm_bfd_dst_register(struct zserv *client, u_short length, - int command, struct zebra_vrf *zvrf); -int zebra_ptm_bfd_dst_deregister(struct zserv *client, u_short length, - struct zebra_vrf *zvrf); +void zebra_ptm_bfd_dst_register(struct zserv *client, u_short length, + int command, struct zebra_vrf *zvrf); +void zebra_ptm_bfd_dst_deregister(struct zserv *client, u_short length, + struct zebra_vrf *zvrf); void zebra_ptm_show_status(struct vty *vty, struct interface *ifp); -int zebra_ptm_bfd_client_register(struct zserv *client, u_short length); +void zebra_ptm_bfd_client_register(struct zserv *client, u_short length); void zebra_ptm_if_init(struct zebra_if *zebra_ifp); void zebra_ptm_if_set_ptm_state(struct interface *ifp, struct zebra_if *zebra_ifp); diff --git a/zebra/zebra_vxlan.c b/zebra/zebra_vxlan.c index d3ede66fb0..bac589a841 100644 --- a/zebra/zebra_vxlan.c +++ b/zebra/zebra_vxlan.c @@ -4863,8 +4863,8 @@ int zebra_vxlan_local_neigh_add_update(struct interface *ifp, /* * Handle message from client to delete a remote MACIP for a VNI. */ -int zebra_vxlan_remote_macip_del(struct zserv *client, u_short length, - struct zebra_vrf *zvrf) +void zebra_vxlan_remote_macip_del(struct zserv *client, u_short length, + struct zebra_vrf *zvrf) { struct stream *s; vni_t vni; @@ -5008,7 +5008,7 @@ int zebra_vxlan_remote_macip_del(struct zserv *client, u_short length, } stream_failure: - return 0; + return; } /* @@ -5016,8 +5016,8 @@ stream_failure: * could be just the add of a MAC address or the add of a neighbor * (IP+MAC). */ -int zebra_vxlan_remote_macip_add(struct zserv *client, u_short length, - struct zebra_vrf *zvrf) +void zebra_vxlan_remote_macip_add(struct zserv *client, u_short length, + struct zebra_vrf *zvrf) { struct stream *s; vni_t vni; @@ -5045,7 +5045,7 @@ int zebra_vxlan_remote_macip_add(struct zserv *client, u_short length, zlog_warn( "%s: EVPN Not turned on yet we have received a remote_macip add zapi callback", __PRETTY_FUNCTION__); - return -1; + return; } s = client->ibuf; @@ -5159,7 +5159,7 @@ int zebra_vxlan_remote_macip_add(struct zserv *client, u_short length, prefix_mac2str(&macaddr, buf, sizeof(buf)), vni, inet_ntoa(vtep_ip)); - return -1; + return; } /* Is this MAC created for a MACIP? */ @@ -5212,7 +5212,7 @@ int zebra_vxlan_remote_macip_add(struct zserv *client, u_short length, prefix_mac2str(&macaddr, buf, sizeof(buf)), vni, inet_ntoa(vtep_ip)); - return -1; + return; } } else if (memcmp(&n->emac, &macaddr, sizeof(macaddr)) @@ -5240,7 +5240,7 @@ int zebra_vxlan_remote_macip_add(struct zserv *client, u_short length, } stream_failure: - return 0; + return; } /* @@ -5543,8 +5543,8 @@ int zebra_vxlan_local_mac_add_update(struct interface *ifp, /* * Handle message from client to delete a remote VTEP for a VNI. */ -int zebra_vxlan_remote_vtep_del(struct zserv *client, u_short length, - struct zebra_vrf *zvrf) +void zebra_vxlan_remote_vtep_del(struct zserv *client, u_short length, + struct zebra_vrf *zvrf) { struct stream *s; u_short l = 0; @@ -5559,13 +5559,13 @@ int zebra_vxlan_remote_vtep_del(struct zserv *client, u_short length, zlog_warn( "%s: EVPN is not enabled yet we have received a vtep del command", __PRETTY_FUNCTION__); - return -1; + return; } if (zvrf_id(zvrf) != VRF_DEFAULT) { zlog_err("Recv MACIP DEL for non-default VRF %u", zvrf_id(zvrf)); - return -1; + return; } s = client->ibuf; @@ -5623,14 +5623,14 @@ int zebra_vxlan_remote_vtep_del(struct zserv *client, u_short length, } stream_failure: - return 0; + return; } /* * Handle message from client to add a remote VTEP for a VNI. */ -int zebra_vxlan_remote_vtep_add(struct zserv *client, u_short length, - struct zebra_vrf *zvrf) +void zebra_vxlan_remote_vtep_add(struct zserv *client, u_short length, + struct zebra_vrf *zvrf) { struct stream *s; u_short l = 0; @@ -5644,13 +5644,13 @@ int zebra_vxlan_remote_vtep_add(struct zserv *client, u_short length, zlog_warn( "%s: EVPN not enabled yet we received a vtep_add zapi call", __PRETTY_FUNCTION__); - return -1; + return; } if (zvrf_id(zvrf) != VRF_DEFAULT) { zlog_err("Recv MACIP ADD for non-default VRF %u", zvrf_id(zvrf)); - return -1; + return; } s = client->ibuf; @@ -5705,7 +5705,7 @@ int zebra_vxlan_remote_vtep_add(struct zserv *client, u_short length, } stream_failure: - return 0; + return; } /* @@ -6512,8 +6512,8 @@ int zebra_vxlan_vrf_delete(struct zebra_vrf *zvrf) * Handle message from client to enable/disable advertisement of g/w macip * routes */ -int zebra_vxlan_advertise_subnet(struct zserv *client, u_short length, - struct zebra_vrf *zvrf) +void zebra_vxlan_advertise_subnet(struct zserv *client, u_short length, + struct zebra_vrf *zvrf) { struct stream *s; int advertise; @@ -6527,7 +6527,7 @@ int zebra_vxlan_advertise_subnet(struct zserv *client, u_short length, if (zvrf_id(zvrf) != VRF_DEFAULT) { zlog_err("EVPN GW-MACIP Adv for non-default VRF %u", zvrf_id(zvrf)); - return -1; + return; } s = client->ibuf; @@ -6536,10 +6536,10 @@ int zebra_vxlan_advertise_subnet(struct zserv *client, u_short length, zvni = zvni_lookup(vni); if (!zvni) - return 0; + return; if (zvni->advertise_subnet == advertise) - return 0; + return; if (IS_ZEBRA_DEBUG_VXLAN) zlog_debug("EVPN subnet Adv %s on VNI %d , currently %s", @@ -6551,35 +6551,35 @@ int zebra_vxlan_advertise_subnet(struct zserv *client, u_short length, ifp = zvni->vxlan_if; if (!ifp) - return 0; + return; zif = ifp->info; /* If down or not mapped to a bridge, we're done. */ if (!if_is_operative(ifp) || !zif->brslave_info.br_if) - return 0; + return; zl2_info = zif->l2info.vxl; vlan_if = zvni_map_to_svi(zl2_info.access_vlan, zif->brslave_info.br_if); if (!vlan_if) - return 0; + return; if (zvni->advertise_subnet) zvni_advertise_subnet(zvni, vlan_if, 1); else zvni_advertise_subnet(zvni, vlan_if, 0); - return 0; + return; } /* * Handle message from client to enable/disable advertisement of g/w macip * routes */ -int zebra_vxlan_advertise_gw_macip(struct zserv *client, u_short length, - struct zebra_vrf *zvrf) +void zebra_vxlan_advertise_gw_macip(struct zserv *client, u_short length, + struct zebra_vrf *zvrf) { struct stream *s; int advertise; @@ -6590,7 +6590,7 @@ int zebra_vxlan_advertise_gw_macip(struct zserv *client, u_short length, if (zvrf_id(zvrf) != VRF_DEFAULT) { zlog_err("EVPN GW-MACIP Adv for non-default VRF %u", zvrf_id(zvrf)); - return -1; + return; } s = client->ibuf; @@ -6606,7 +6606,7 @@ int zebra_vxlan_advertise_gw_macip(struct zserv *client, u_short length, : "disabled"); if (zvrf->advertise_gw_macip == advertise) - return 0; + return; zvrf->advertise_gw_macip = advertise; @@ -6625,7 +6625,7 @@ int zebra_vxlan_advertise_gw_macip(struct zserv *client, u_short length, zvni = zvni_lookup(vni); if (!zvni) - return 0; + return; if (IS_ZEBRA_DEBUG_VXLAN) zlog_debug( @@ -6635,26 +6635,26 @@ int zebra_vxlan_advertise_gw_macip(struct zserv *client, u_short length, : "disabled"); if (zvni->advertise_gw_macip == advertise) - return 0; + return; zvni->advertise_gw_macip = advertise; ifp = zvni->vxlan_if; if (!ifp) - return 0; + return; zif = ifp->info; /* If down or not mapped to a bridge, we're done. */ if (!if_is_operative(ifp) || !zif->brslave_info.br_if) - return 0; + return; zl2_info = zif->l2info.vxl; vlan_if = zvni_map_to_svi(zl2_info.access_vlan, zif->brslave_info.br_if); if (!vlan_if) - return 0; + return; if (advertise_gw_macip_enabled(zvni)) { /* Add primary SVI MAC-IP */ @@ -6676,7 +6676,7 @@ int zebra_vxlan_advertise_gw_macip(struct zserv *client, u_short length, } stream_failure: - return 0; + return; } @@ -6686,8 +6686,8 @@ stream_failure: * when disabled, the entries should be deleted and remote VTEPs and MACs * uninstalled from the kernel. */ -int zebra_vxlan_advertise_all_vni(struct zserv *client, u_short length, - struct zebra_vrf *zvrf) +void zebra_vxlan_advertise_all_vni(struct zserv *client, u_short length, + struct zebra_vrf *zvrf) { struct stream *s = NULL; int advertise = 0; @@ -6695,7 +6695,7 @@ int zebra_vxlan_advertise_all_vni(struct zserv *client, u_short length, if (zvrf_id(zvrf) != VRF_DEFAULT) { zlog_err("EVPN VNI Adv for non-default VRF %u", zvrf_id(zvrf)); - return -1; + return; } s = client->ibuf; @@ -6707,7 +6707,7 @@ int zebra_vxlan_advertise_all_vni(struct zserv *client, u_short length, is_evpn_enabled() ? "enabled" : "disabled"); if (zvrf->advertise_all_vni == advertise) - return 0; + return; zvrf->advertise_all_vni = advertise; if (is_evpn_enabled()) { @@ -6732,13 +6732,13 @@ int zebra_vxlan_advertise_all_vni(struct zserv *client, u_short length, /* cleanup all l3vnis */ zns = zebra_ns_lookup(NS_DEFAULT); if (!zns) - return -1; + return; hash_iterate(zns->l3vni_table, zl3vni_cleanup_all, NULL); } stream_failure: - return 0; + return; } /* diff --git a/zebra/zebra_vxlan.h b/zebra/zebra_vxlan.h index 7abf0050fc..af76a41d80 100644 --- a/zebra/zebra_vxlan.h +++ b/zebra/zebra_vxlan.h @@ -51,6 +51,22 @@ static inline int is_evpn_enabled() #define VNI_STR_LEN 32 +/* zserv handlers */ +extern void zebra_vxlan_remote_macip_add(struct zserv *client, u_short length, + struct zebra_vrf *zvrf); +extern void zebra_vxlan_remote_macip_del(struct zserv *client, u_short length, + struct zebra_vrf *zvrf); +extern void zebra_vxlan_remote_vtep_add(struct zserv *client, u_short length, + struct zebra_vrf *zvrf); +extern void zebra_vxlan_remote_vtep_del(struct zserv *client, u_short length, + struct zebra_vrf *zvrf); +extern void zebra_vxlan_advertise_subnet(struct zserv *client, u_short length, + struct zebra_vrf *zvrf); +extern void zebra_vxlan_advertise_gw_macip(struct zserv *client, u_short length, + struct zebra_vrf *zvrf); +extern void zebra_vxlan_advertise_all_vni(struct zserv *client, u_short length, + struct zebra_vrf *zvrf); + extern int is_l3vni_for_prefix_routes_only(vni_t vni); extern ifindex_t get_l3vni_svi_ifindex(vrf_id_t vrf_id); extern int zebra_vxlan_vrf_delete(struct zebra_vrf *zvrf); @@ -117,10 +133,6 @@ extern int zebra_vxlan_local_neigh_add_update( extern int zebra_vxlan_local_neigh_del(struct interface *ifp, struct interface *link_if, struct ipaddr *ip); -extern int zebra_vxlan_remote_macip_add(struct zserv *client, u_short length, - struct zebra_vrf *zvrf); -extern int zebra_vxlan_remote_macip_del(struct zserv *client, u_short length, - struct zebra_vrf *zvrf); extern int zebra_vxlan_local_mac_add_update(struct interface *ifp, struct interface *br_if, struct ethaddr *mac, vlanid_t vid, @@ -140,16 +152,6 @@ extern int zebra_vxlan_if_down(struct interface *ifp); extern int zebra_vxlan_if_add(struct interface *ifp); extern int zebra_vxlan_if_update(struct interface *ifp, u_int16_t chgflags); extern int zebra_vxlan_if_del(struct interface *ifp); -extern int zebra_vxlan_remote_vtep_add(struct zserv *client, u_short length, - struct zebra_vrf *zvrf); -extern int zebra_vxlan_remote_vtep_del(struct zserv *client, u_short length, - struct zebra_vrf *zvrf); -extern int zebra_vxlan_advertise_subnet(struct zserv *client, u_short length, - struct zebra_vrf *zvrf); -extern int zebra_vxlan_advertise_gw_macip(struct zserv *client, u_short length, - struct zebra_vrf *zvrf); -extern int zebra_vxlan_advertise_all_vni(struct zserv *client, u_short length, - struct zebra_vrf *zvrf); extern int zebra_vxlan_process_vrf_vni_cmd(struct zebra_vrf *zvrf, vni_t vni, char *err, int err_str_sz, int filter, int add); diff --git a/zebra/zebra_vxlan_null.c b/zebra/zebra_vxlan_null.c index 1bac2cafb6..e6a3dd674e 100644 --- a/zebra/zebra_vxlan_null.c +++ b/zebra/zebra_vxlan_null.c @@ -117,14 +117,14 @@ int zebra_vxlan_svi_down(struct interface *ifp, struct interface *link_if) return 0; } -int zebra_vxlan_remote_macip_add(struct zserv *client, int sock, u_short length, - struct zebra_vrf *zvrf) +void zebra_vxlan_remote_macip_add(struct zserv *client, int sock, + u_short length, struct zebra_vrf *zvrf) { return 0; } -int zebra_vxlan_remote_macip_del(struct zserv *client, int sock, u_short length, - struct zebra_vrf *zvrf) +void zebra_vxlan_remote_macip_del(struct zserv *client, int sock, + u_short length, struct zebra_vrf *zvrf) { return 0; } @@ -182,20 +182,20 @@ int zebra_vxlan_if_del(struct interface *ifp) return 0; } -int zebra_vxlan_remote_vtep_add(struct zserv *client, int sock, u_short length, - struct zebra_vrf *zvrf) +void zebra_vxlan_remote_vtep_add(struct zserv *client, int sock, u_short length, + struct zebra_vrf *zvrf) { return 0; } -int zebra_vxlan_remote_vtep_del(struct zserv *client, int sock, u_short length, - struct zebra_vrf *zvrf) +void zebra_vxlan_remote_vtep_del(struct zserv *client, int sock, u_short length, + struct zebra_vrf *zvrf) { return 0; } -int zebra_vxlan_advertise_all_vni(struct zserv *client, int sock, - u_short length, struct zebra_vrf *zvrf) +void zebra_vxlan_advertise_all_vni(struct zserv *client, int sock, + u_short length, struct zebra_vrf *zvrf) { return 0; } diff --git a/zebra/zserv.c b/zebra/zserv.c index 1a2ad7f8b4..f3ee38fef1 100644 --- a/zebra/zserv.c +++ b/zebra/zserv.c @@ -693,8 +693,8 @@ static int zsend_write_nexthop(struct stream *s, struct nexthop *nexthop) } /* Nexthop register */ -static int zserv_rnh_register(struct zserv *client, u_short length, - rnh_type_t type, struct zebra_vrf *zvrf) +static void zserv_rnh_register(struct zserv *client, u_short length, + rnh_type_t type, struct zebra_vrf *zvrf) { struct rnh *rnh; struct stream *s; @@ -722,7 +722,7 @@ static int zserv_rnh_register(struct zserv *client, u_short length, zlog_warn( "%s: Specified prefix length %d is too large for a v4 address", __PRETTY_FUNCTION__, p.prefixlen); - return -1; + return; } STREAM_GET(&p.u.prefix4.s_addr, s, IPV4_MAX_BYTELEN); l += IPV4_MAX_BYTELEN; @@ -731,7 +731,7 @@ static int zserv_rnh_register(struct zserv *client, u_short length, zlog_warn( "%s: Specified prefix length %d is to large for a v6 address", __PRETTY_FUNCTION__, p.prefixlen); - return -1; + return; } STREAM_GET(&p.u.prefix6, s, IPV6_MAX_BYTELEN); l += IPV6_MAX_BYTELEN; @@ -739,7 +739,7 @@ static int zserv_rnh_register(struct zserv *client, u_short length, zlog_err( "rnh_register: Received unknown family type %d\n", p.family); - return -1; + return; } rnh = zebra_add_rnh(&p, zvrf_id(zvrf), type); if (type == RNH_NEXTHOP_TYPE) { @@ -764,12 +764,12 @@ static int zserv_rnh_register(struct zserv *client, u_short length, } stream_failure: - return 0; + return; } /* Nexthop register */ -static int zserv_rnh_unregister(struct zserv *client, u_short length, - rnh_type_t type, struct zebra_vrf *zvrf) +static void zserv_rnh_unregister(struct zserv *client, u_short length, + rnh_type_t type, struct zebra_vrf *zvrf) { struct rnh *rnh; struct stream *s; @@ -797,7 +797,7 @@ static int zserv_rnh_unregister(struct zserv *client, u_short length, zlog_warn( "%s: Specified prefix length %d is to large for a v4 address", __PRETTY_FUNCTION__, p.prefixlen); - return -1; + return; } STREAM_GET(&p.u.prefix4.s_addr, s, IPV4_MAX_BYTELEN); l += IPV4_MAX_BYTELEN; @@ -806,7 +806,7 @@ static int zserv_rnh_unregister(struct zserv *client, u_short length, zlog_warn( "%s: Specified prefix length %d is to large for a v6 address", __PRETTY_FUNCTION__, p.prefixlen); - return -1; + return; } STREAM_GET(&p.u.prefix6, s, IPV6_MAX_BYTELEN); l += IPV6_MAX_BYTELEN; @@ -814,7 +814,7 @@ static int zserv_rnh_unregister(struct zserv *client, u_short length, zlog_err( "rnh_register: Received unknown family type %d\n", p.family); - return -1; + return; } rnh = zebra_lookup_rnh(&p, zvrf_id(zvrf), type); if (rnh) { @@ -823,13 +823,13 @@ static int zserv_rnh_unregister(struct zserv *client, u_short length, } } stream_failure: - return 0; + return; } #define ZEBRA_MIN_FEC_LENGTH 5 /* FEC register */ -static int zserv_fec_register(struct zserv *client, u_short length) +static void zserv_fec_register(struct zserv *client, u_short length) { struct stream *s; struct zebra_vrf *zvrf; @@ -841,7 +841,7 @@ static int zserv_fec_register(struct zserv *client, u_short length) s = client->ibuf; zvrf = vrf_info_lookup(VRF_DEFAULT); if (!zvrf) - return 0; // unexpected + return; /* * The minimum amount of data that can be sent for one fec @@ -851,7 +851,7 @@ static int zserv_fec_register(struct zserv *client, u_short length) zlog_err( "fec_register: Received a fec register of length %d, it is of insufficient size to properly decode", length); - return -1; + return; } while (l < length) { @@ -862,7 +862,7 @@ static int zserv_fec_register(struct zserv *client, u_short length) zlog_err( "fec_register: Received unknown family type %d\n", p.family); - return -1; + return; } STREAM_GETC(s, p.prefixlen); if ((p.family == AF_INET && p.prefixlen > IPV4_MAX_BITLEN) @@ -871,7 +871,7 @@ static int zserv_fec_register(struct zserv *client, u_short length) zlog_warn( "%s: Specified prefix length: %d is to long for %d", __PRETTY_FUNCTION__, p.prefixlen, p.family); - return -1; + return; } l += 5; STREAM_GET(&p.u.prefix, s, PSIZE(p.prefixlen)); @@ -885,11 +885,11 @@ static int zserv_fec_register(struct zserv *client, u_short length) } stream_failure: - return 0; + return; } /* FEC unregister */ -static int zserv_fec_unregister(struct zserv *client, u_short length) +static void zserv_fec_unregister(struct zserv *client, u_short length) { struct stream *s; struct zebra_vrf *zvrf; @@ -900,7 +900,7 @@ static int zserv_fec_unregister(struct zserv *client, u_short length) s = client->ibuf; zvrf = vrf_info_lookup(VRF_DEFAULT); if (!zvrf) - return 0; // unexpected + return; /* * The minimum amount of data that can be sent for one @@ -910,7 +910,7 @@ static int zserv_fec_unregister(struct zserv *client, u_short length) zlog_err( "fec_unregister: Received a fec unregister of length %d, it is of insufficient size to properly decode", length); - return -1; + return; } while (l < length) { @@ -924,7 +924,7 @@ static int zserv_fec_unregister(struct zserv *client, u_short length) zlog_err( "fec_unregister: Received unknown family type %d\n", p.family); - return -1; + return; } STREAM_GETC(s, p.prefixlen); if ((p.family == AF_INET && p.prefixlen > IPV4_MAX_BITLEN) @@ -933,7 +933,7 @@ static int zserv_fec_unregister(struct zserv *client, u_short length) zlog_warn( "%s: Received prefix length %d which is greater than %d can support", __PRETTY_FUNCTION__, p.prefixlen, p.family); - return -1; + return; } l += 5; STREAM_GET(&p.u.prefix, s, PSIZE(p.prefixlen)); @@ -942,7 +942,7 @@ static int zserv_fec_unregister(struct zserv *client, u_short length) } stream_failure: - return 0; + return; } /* @@ -1133,8 +1133,8 @@ int zsend_pw_update(struct zserv *client, struct zebra_pw *pw) /* Register zebra server interface information. Send current all interface and address information. */ -static int zread_interface_add(struct zserv *client, u_short length, - struct zebra_vrf *zvrf) +static void zread_interface_add(struct zserv *client, u_short length, + struct zebra_vrf *zvrf) { struct vrf *vrf; struct interface *ifp; @@ -1149,21 +1149,20 @@ static int zread_interface_add(struct zserv *client, u_short length, continue; if (zsend_interface_add(client, ifp) < 0) - return -1; + return; if (zsend_interface_addresses(client, ifp) < 0) - return -1; + return; } } - return 0; + return; } /* Unregister zebra server interface information. */ -static int zread_interface_delete(struct zserv *client, u_short length, - struct zebra_vrf *zvrf) +static void zread_interface_delete(struct zserv *client, u_short length, + struct zebra_vrf *zvrf) { vrf_bitmap_unset(client->ifinfo, zvrf_id(zvrf)); - return 0; } void zserv_nexthop_num_warn(const char *caller, const struct prefix *p, @@ -1178,8 +1177,8 @@ 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) +static void zread_route_add(struct zserv *client, u_short length, + struct zebra_vrf *zvrf) { struct stream *s; struct zapi_route api; @@ -1193,7 +1192,7 @@ static int zread_route_add(struct zserv *client, u_short length, s = client->ibuf; if (zapi_route_decode(s, &api) < 0) - return -1; + return; /* Allocate new route. */ vrf_id = zvrf_id(zvrf); @@ -1277,7 +1276,7 @@ static int zread_route_add(struct zserv *client, u_short length, __PRETTY_FUNCTION__, api.nexthop_num); nexthops_free(re->ng.nexthop); XFREE(MTYPE_RE, re); - return -1; + return; } /* MPLS labels for BGP-LU or Segment Routing */ if (CHECK_FLAG(api.message, ZAPI_MESSAGE_LABEL) @@ -1309,7 +1308,7 @@ static int zread_route_add(struct zserv *client, u_short length, __PRETTY_FUNCTION__); nexthops_free(re->ng.nexthop); XFREE(MTYPE_RE, re); - return -1; + return; } if (CHECK_FLAG(api.message, ZAPI_MESSAGE_SRCPFX)) src_p = &api.src_prefix; @@ -1331,12 +1330,10 @@ static int zread_route_add(struct zserv *client, u_short length, client->v6_route_upd8_cnt++; break; } - - return 0; } -static int zread_route_del(struct zserv *client, u_short length, - struct zebra_vrf *zvrf) +static void zread_route_del(struct zserv *client, u_short length, + struct zebra_vrf *zvrf) { struct stream *s; struct zapi_route api; @@ -1345,13 +1342,13 @@ static int zread_route_del(struct zserv *client, u_short length, s = client->ibuf; if (zapi_route_decode(s, &api) < 0) - return -1; + return; afi = family2afi(api.prefix.family); if (afi != AFI_IP6 && CHECK_FLAG(api.message, ZAPI_MESSAGE_SRCPFX)) { zlog_warn("%s: Received a src prefix while afi is not v6", __PRETTY_FUNCTION__); - return -1; + return; } if (CHECK_FLAG(api.message, ZAPI_MESSAGE_SRCPFX)) src_p = &api.src_prefix; @@ -1370,7 +1367,7 @@ static int zread_route_del(struct zserv *client, u_short length, break; } - return 0; + return; } /* This function support multiple nexthop. */ @@ -1378,8 +1375,8 @@ static int zread_route_del(struct zserv *client, u_short length, * Parse the ZEBRA_IPV4_ROUTE_ADD sent from client. Update re and * add kernel route. */ -static int zread_ipv4_add(struct zserv *client, u_short length, - struct zebra_vrf *zvrf) +static void zread_ipv4_add(struct zserv *client, u_short length, + struct zebra_vrf *zvrf) { int i; struct route_entry *re; @@ -1409,7 +1406,7 @@ static int zread_ipv4_add(struct zserv *client, u_short length, zlog_warn("%s: Specified route type %d is not a legal value\n", __PRETTY_FUNCTION__, re->type); XFREE(MTYPE_RE, re); - return -1; + return; } STREAM_GETW(s, re->instance); STREAM_GETL(s, re->flags); @@ -1426,7 +1423,7 @@ static int zread_ipv4_add(struct zserv *client, u_short length, "%s: Specified prefix length %d is greater than what v4 can be", __PRETTY_FUNCTION__, p.prefixlen); XFREE(MTYPE_RE, re); - return -1; + return; } STREAM_GET(&p.u.prefix4, s, PSIZE(p.prefixlen)); @@ -1478,7 +1475,7 @@ static int zread_ipv4_add(struct zserv *client, u_short length, __PRETTY_FUNCTION__); nexthops_free(re->ng.nexthop); XFREE(MTYPE_RE, re); - return -1; + return; break; case NEXTHOP_TYPE_BLACKHOLE: route_entry_nexthop_blackhole_add(re, bh_type); @@ -1489,7 +1486,7 @@ static int zread_ipv4_add(struct zserv *client, u_short length, __PRETTY_FUNCTION__, nexthop_type); nexthops_free(re->ng.nexthop); XFREE(MTYPE_RE, re); - return -1; + return; } } } @@ -1524,17 +1521,17 @@ static int zread_ipv4_add(struct zserv *client, u_short length, else if (ret < 0) client->v4_route_upd8_cnt++; - return 0; + return; stream_failure: nexthops_free(re->ng.nexthop); XFREE(MTYPE_RE, re); - return -1; + return; } /* Zebra server IPv4 prefix delete function. */ -static int zread_ipv4_delete(struct zserv *client, u_short length, - struct zebra_vrf *zvrf) +static void zread_ipv4_delete(struct zserv *client, u_short length, + struct zebra_vrf *zvrf) { struct stream *s; struct zapi_ipv4 api; @@ -1557,7 +1554,7 @@ static int zread_ipv4_delete(struct zserv *client, u_short length, if (p.prefixlen > IPV4_MAX_BITLEN) { zlog_warn("%s: Passed in prefixlen %d is impossible", __PRETTY_FUNCTION__, p.prefixlen); - return -1; + return; } STREAM_GET(&p.u.prefix4, s, PSIZE(p.prefixlen)); @@ -1568,28 +1565,29 @@ static int zread_ipv4_delete(struct zserv *client, u_short length, client->v4_route_del_cnt++; stream_failure: - return 0; + return; } /* MRIB Nexthop lookup for IPv4. */ -static int zread_ipv4_nexthop_lookup_mrib(struct zserv *client, u_short length, - struct zebra_vrf *zvrf) +static void zread_ipv4_nexthop_lookup_mrib(struct zserv *client, u_short length, + struct zebra_vrf *zvrf) { struct in_addr addr; struct route_entry *re; STREAM_GET(&addr.s_addr, client->ibuf, IPV4_MAX_BYTELEN); re = rib_match_ipv4_multicast(zvrf_id(zvrf), addr, NULL); - return zsend_ipv4_nexthop_lookup_mrib(client, addr, re, zvrf); + zsend_ipv4_nexthop_lookup_mrib(client, addr, re, zvrf); + return; stream_failure: - return -1; + return; } /* Zebra server IPv6 prefix add function. */ -static int zread_ipv4_route_ipv6_nexthop_add(struct zserv *client, - u_short length, - struct zebra_vrf *zvrf) +static void zread_ipv4_route_ipv6_nexthop_add(struct zserv *client, + u_short length, + struct zebra_vrf *zvrf) { unsigned int i; struct stream *s; @@ -1623,7 +1621,8 @@ static int zread_ipv4_route_ipv6_nexthop_add(struct zserv *client, zlog_warn("%s: Specified route type: %d is not a legal value\n", __PRETTY_FUNCTION__, re->type); XFREE(MTYPE_RE, re); - return -1; + + return; } STREAM_GETW(s, re->instance); STREAM_GETL(s, re->flags); @@ -1640,7 +1639,7 @@ static int zread_ipv4_route_ipv6_nexthop_add(struct zserv *client, "%s: Prefix Length %d is greater than what a v4 address can use", __PRETTY_FUNCTION__, p.prefixlen); XFREE(MTYPE_RE, re); - return -1; + return; } STREAM_GET(&p.u.prefix4, s, PSIZE(p.prefixlen)); @@ -1695,7 +1694,7 @@ static int zread_ipv4_route_ipv6_nexthop_add(struct zserv *client, __PRETTY_FUNCTION__); nexthops_free(re->ng.nexthop); XFREE(MTYPE_RE, re); - return -1; + return; } } @@ -1753,16 +1752,16 @@ static int zread_ipv4_route_ipv6_nexthop_add(struct zserv *client, else if (ret < 0) client->v4_route_upd8_cnt++; - return 0; + return; stream_failure: nexthops_free(re->ng.nexthop); XFREE(MTYPE_RE, re); - return -1; + return; } -static int zread_ipv6_add(struct zserv *client, u_short length, - struct zebra_vrf *zvrf) +static void zread_ipv6_add(struct zserv *client, u_short length, + struct zebra_vrf *zvrf) { unsigned int i; struct stream *s; @@ -1798,7 +1797,7 @@ static int zread_ipv6_add(struct zserv *client, u_short length, zlog_warn("%s: Specified route type: %d is not a legal value\n", __PRETTY_FUNCTION__, re->type); XFREE(MTYPE_RE, re); - return -1; + return; } STREAM_GETW(s, re->instance); STREAM_GETL(s, re->flags); @@ -1815,7 +1814,7 @@ static int zread_ipv6_add(struct zserv *client, u_short length, "%s: Specified prefix length %d is to large for v6 prefix", __PRETTY_FUNCTION__, p.prefixlen); XFREE(MTYPE_RE, re); - return -1; + return; } STREAM_GET(&p.u.prefix6, s, PSIZE(p.prefixlen)); @@ -1828,7 +1827,7 @@ static int zread_ipv6_add(struct zserv *client, u_short length, "%s: Specified src prefix length %d is to large for v6 prefix", __PRETTY_FUNCTION__, src_p.prefixlen); XFREE(MTYPE_RE, re); - return -1; + return; } STREAM_GET(&src_p.prefix, s, PSIZE(src_p.prefixlen)); src_pp = &src_p; @@ -1891,7 +1890,7 @@ static int zread_ipv6_add(struct zserv *client, u_short length, __PRETTY_FUNCTION__); nexthops_free(re->ng.nexthop); XFREE(MTYPE_RE, re); - return -1; + return; } } @@ -1947,18 +1946,18 @@ static int zread_ipv6_add(struct zserv *client, u_short length, else if (ret < 0) client->v6_route_upd8_cnt++; - return 0; + return; stream_failure: nexthops_free(re->ng.nexthop); XFREE(MTYPE_RE, re); - return -1; + return; } /* Zebra server IPv6 prefix delete function. */ -static int zread_ipv6_delete(struct zserv *client, u_short length, - struct zebra_vrf *zvrf) +static void zread_ipv6_delete(struct zserv *client, u_short length, + struct zebra_vrf *zvrf) { struct stream *s; struct zapi_ipv6 api; @@ -1996,12 +1995,12 @@ static int zread_ipv6_delete(struct zserv *client, u_short length, client->v6_route_del_cnt++; stream_failure: - return 0; + return; } /* Register zebra server router-id information. Send current router-id */ -static int zread_router_id_add(struct zserv *client, u_short length, - struct zebra_vrf *zvrf) +static void zread_router_id_add(struct zserv *client, u_short length, + struct zebra_vrf *zvrf) { struct prefix p; @@ -2010,15 +2009,14 @@ static int zread_router_id_add(struct zserv *client, u_short length, router_id_get(&p, zvrf_id(zvrf)); - return zsend_router_id_update(client, &p, zvrf_id(zvrf)); + zsend_router_id_update(client, &p, zvrf_id(zvrf)); } /* Unregister zebra server router-id information. */ -static int zread_router_id_delete(struct zserv *client, u_short length, - struct zebra_vrf *zvrf) +static void zread_router_id_delete(struct zserv *client, u_short length, + struct zebra_vrf *zvrf) { vrf_bitmap_unset(client->ridinfo, zvrf_id(zvrf)); - return 0; } /* Tie up route-type and client->sock */ @@ -2052,8 +2050,8 @@ stream_failure: } /* Unregister all information in a VRF. */ -static int zread_vrf_unregister(struct zserv *client, u_short length, - struct zebra_vrf *zvrf) +static void zread_vrf_unregister(struct zserv *client, u_short length, + struct zebra_vrf *zvrf) { int i; afi_t afi; @@ -2064,8 +2062,6 @@ static int zread_vrf_unregister(struct zserv *client, u_short length, vrf_bitmap_unset(client->redist_default, zvrf_id(zvrf)); vrf_bitmap_unset(client->ifinfo, zvrf_id(zvrf)); vrf_bitmap_unset(client->ridinfo, zvrf_id(zvrf)); - - return 0; } static void zread_mpls_labels(int command, struct zserv *client, u_short length, @@ -2313,8 +2309,8 @@ static void zread_label_manager_request(int cmd, struct zserv *client, } } -static int zread_pseudowire(int command, struct zserv *client, u_short length, - struct zebra_vrf *zvrf) +static void zread_pseudowire(int command, struct zserv *client, u_short length, + struct zebra_vrf *zvrf) { struct stream *s; char ifname[IF_NAMESIZE]; @@ -2345,7 +2341,7 @@ static int zread_pseudowire(int command, struct zserv *client, u_short length, STREAM_GET(&nexthop.ipv6, s, 16); break; default: - return -1; + return; } STREAM_GETL(s, local_label); STREAM_GETL(s, remote_label); @@ -2360,7 +2356,7 @@ static int zread_pseudowire(int command, struct zserv *client, u_short length, zlog_warn("%s: pseudowire %s already exists [%s]", __func__, ifname, zserv_command_string(command)); - return -1; + return; } zebra_pw_add(zvrf, ifname, protocol, client); @@ -2369,7 +2365,7 @@ static int zread_pseudowire(int command, struct zserv *client, u_short length, if (!pw) { zlog_warn("%s: pseudowire %s not found [%s]", __func__, ifname, zserv_command_string(command)); - return -1; + return; } zebra_pw_del(zvrf, pw); @@ -2379,7 +2375,7 @@ static int zread_pseudowire(int command, struct zserv *client, u_short length, if (!pw) { zlog_warn("%s: pseudowire %s not found [%s]", __func__, ifname, zserv_command_string(command)); - return -1; + return; } switch (command) { @@ -2397,7 +2393,7 @@ static int zread_pseudowire(int command, struct zserv *client, u_short length, } stream_failure: - return 0; + return; } /* Cleanup registered nexthops (across VRFs) upon client disconnect. */ @@ -2532,7 +2528,7 @@ static void zebra_client_create(int sock) zebra_vrf_update_all(client); } -static int zread_interface_set_master(struct zserv *client, u_short length) +static void zread_interface_set_master(struct zserv *client, u_short length) { struct interface *master; struct interface *slave; @@ -2549,12 +2545,12 @@ static int zread_interface_set_master(struct zserv *client, u_short length) slave = if_lookup_by_index(ifindex, vrf_id); if (!master || !slave) - return 0; + return; kernel_interface_set_master(master, slave); stream_failure: - return 1; + return; } From 9bcbcae2e428bfd2b8d3a95368e459a338c14eed Mon Sep 17 00:00:00 2001 From: Quentin Young Date: Tue, 6 Mar 2018 17:09:36 -0500 Subject: [PATCH 17/25] zebra: add struct zmsghdr Formalize the ZAPI header by documenting it in code and providing it to message handlers free of charge to reduce complexity. Signed-off-by: Quentin Young --- zebra/zserv.c | 21 +++++++++++++++++++++ zebra/zserv.h | 9 +++++++++ 2 files changed, 30 insertions(+) diff --git a/zebra/zserv.c b/zebra/zserv.c index f3ee38fef1..3ecc82be42 100644 --- a/zebra/zserv.c +++ b/zebra/zserv.c @@ -2681,10 +2681,31 @@ stream_failure: return; } +/* + * Reads header from zmsg stream. + * + * Note this advances the stream getp by the size of the header. + */ +static bool zserv_read_header(struct stream *msg, struct zmsghdr *hdr) +{ + STREAM_GETW(msg, hdr->length); + STREAM_GETC(msg, hdr->marker); + STREAM_GETC(msg, hdr->version); + STREAM_GETL(msg, hdr->vrf_id); + STREAM_GETW(msg, hdr->command); + return true; +stream_failure: + return false; +} + static inline void zserv_handle_commands(struct zserv *client, uint16_t command, uint16_t length, struct zebra_vrf *zvrf) { + struct zmsghdr hdr; + stream_set_getp(client->ibuf, 0); + zserv_read_header(client->ibuf, &hdr); + switch (command) { case ZEBRA_ROUTER_ID_ADD: zread_router_id_add(client, length, zvrf); diff --git a/zebra/zserv.h b/zebra/zserv.h index 8519693726..a09baeff7a 100644 --- a/zebra/zserv.h +++ b/zebra/zserv.h @@ -129,6 +129,15 @@ struct zserv { int last_write_cmd; }; +/* ZAPI protocol message header */ +struct zmsghdr { + uint16_t length; + uint8_t marker; + uint8_t version; + uint32_t vrf_id; + uint16_t command; +}; + /* Zebra instance */ struct zebra_t { /* Thread master */ From 89f4e5077bd8162dbda0e10a3bbd594c2c698d77 Mon Sep 17 00:00:00 2001 From: Quentin Young Date: Tue, 6 Mar 2018 17:57:33 -0500 Subject: [PATCH 18/25] zebra: standardize ZAPI message handler args A lot of the handler functions that are called directly from the ZAPI input processing code take different argument sets where they don't need to. These functions are called from only one place and all have the same fundamental information available to them to do their work. There is no need to specialize what information is passed to them; it is cleaner and easier to understand when they all accept the same base set of information and extract what they need inline. Signed-off-by: Quentin Young --- zebra/redistribute.c | 12 +- zebra/redistribute.h | 14 +- zebra/rtadv.c | 23 ++- zebra/rtadv.h | 5 +- zebra/zebra_mroute.c | 4 +- zebra/zebra_mroute.h | 5 +- zebra/zebra_ptm.c | 16 +- zebra/zebra_ptm.h | 11 +- zebra/zebra_vxlan.c | 31 ++-- zebra/zebra_vxlan.h | 23 ++- zebra/zserv.c | 341 ++++++++++++++++--------------------------- zebra/zserv.h | 3 + 12 files changed, 194 insertions(+), 294 deletions(-) diff --git a/zebra/redistribute.c b/zebra/redistribute.c index a7b2361ac6..93862cadc9 100644 --- a/zebra/redistribute.c +++ b/zebra/redistribute.c @@ -243,8 +243,7 @@ void redistribute_delete(struct prefix *p, struct prefix *src_p, } } -void zebra_redistribute_add(int command, struct zserv *client, int length, - struct zebra_vrf *zvrf) +void zebra_redistribute_add(ZAPI_HANDLER_ARGS) { afi_t afi = 0; int type = 0; @@ -287,8 +286,7 @@ stream_failure: return; } -void zebra_redistribute_delete(int command, struct zserv *client, int length, - struct zebra_vrf *zvrf) +void zebra_redistribute_delete(ZAPI_HANDLER_ARGS) { afi_t afi = 0; int type = 0; @@ -325,15 +323,13 @@ stream_failure: return; } -void zebra_redistribute_default_add(int command, struct zserv *client, - int length, struct zebra_vrf *zvrf) +void zebra_redistribute_default_add(ZAPI_HANDLER_ARGS) { vrf_bitmap_set(client->redist_default, zvrf_id(zvrf)); zebra_redistribute_default(client, zvrf_id(zvrf)); } -void zebra_redistribute_default_delete(int command, struct zserv *client, - int length, struct zebra_vrf *zvrf) +void zebra_redistribute_default_delete(ZAPI_HANDLER_ARGS) { vrf_bitmap_unset(client->redist_default, zvrf_id(zvrf)); } diff --git a/zebra/redistribute.h b/zebra/redistribute.h index 5edb06c3da..6ca3b57d4d 100644 --- a/zebra/redistribute.h +++ b/zebra/redistribute.h @@ -27,15 +27,11 @@ #include "vty.h" #include "vrf.h" -extern void zebra_redistribute_add(int, struct zserv *, int, - struct zebra_vrf *zvrf); -extern void zebra_redistribute_delete(int, struct zserv *, int, - struct zebra_vrf *zvrf); - -extern void zebra_redistribute_default_add(int, struct zserv *, int, - struct zebra_vrf *zvrf); -extern void zebra_redistribute_default_delete(int, struct zserv *, int, - struct zebra_vrf *zvrf); +/* zapi handlers */ +extern void zebra_redistribute_add(ZAPI_HANDLER_ARGS); +extern void zebra_redistribute_delete(ZAPI_HANDLER_ARGS); +extern void zebra_redistribute_default_add(ZAPI_HANDLER_ARGS); +extern void zebra_redistribute_default_delete(ZAPI_HANDLER_ARGS); extern void redistribute_update(struct prefix *, struct prefix *, struct route_entry *, struct route_entry *); diff --git a/zebra/rtadv.c b/zebra/rtadv.c index 5eebca163b..56decdcdba 100644 --- a/zebra/rtadv.c +++ b/zebra/rtadv.c @@ -43,6 +43,7 @@ #include "zebra/zserv.h" #include "zebra/zebra_ns.h" #include "zebra/zebra_vrf.h" +#include "zebra/zserv.h" extern struct zebra_privs_t zserv_privs; @@ -801,8 +802,7 @@ static void ipv6_nd_suppress_ra_set(struct interface *ifp, * if the operator has explicitly enabled RA. The enable request can also * specify a RA interval (in seconds). */ -void zebra_interface_radv_set(struct zserv *client, u_short length, - struct zebra_vrf *zvrf, int enable) +void zebra_interface_radv_set(ZAPI_HANDLER_ARGS, int set) { struct stream *s; ifindex_t ifindex; @@ -818,27 +818,26 @@ void zebra_interface_radv_set(struct zserv *client, u_short length, if (IS_ZEBRA_DEBUG_EVENT) zlog_debug("%u: IF %u RA %s from client %s, interval %ds", - zvrf_id(zvrf), ifindex, - enable ? "enable" : "disable", + zvrf_id(zvrf), ifindex, set ? "enable" : "disable", zebra_route_string(client->proto), ra_interval); /* Locate interface and check VRF match. */ ifp = if_lookup_by_index_per_ns(zebra_ns_lookup(NS_DEFAULT), ifindex); if (!ifp) { zlog_warn("%u: IF %u RA %s client %s - interface unknown", - zvrf_id(zvrf), ifindex, enable ? "enable" : "disable", + zvrf_id(zvrf), ifindex, set ? "enable" : "disable", zebra_route_string(client->proto)); return; } if (ifp->vrf_id != zvrf_id(zvrf)) { zlog_warn("%u: IF %u RA %s client %s - VRF mismatch, IF VRF %u", - zvrf_id(zvrf), ifindex, enable ? "enable" : "disable", + zvrf_id(zvrf), ifindex, set ? "enable" : "disable", zebra_route_string(client->proto), ifp->vrf_id); return; } zif = ifp->info; - if (enable) { + if (set) { SET_FLAG(zif->rtadv.ra_configured, BGP_RA_CONFIGURED); ipv6_nd_suppress_ra_set(ifp, RA_ENABLE); if (ra_interval @@ -859,6 +858,16 @@ stream_failure: return; } +void zebra_interface_radv_disable(ZAPI_HANDLER_ARGS) +{ + zebra_interface_radv_set(client, hdr, zvrf, 0); +} + +void zebra_interface_radv_enable(ZAPI_HANDLER_ARGS) +{ + zebra_interface_radv_set(client, hdr, zvrf, 1); +} + DEFUN (ipv6_nd_suppress_ra, ipv6_nd_suppress_ra_cmd, "ipv6 nd suppress-ra", diff --git a/zebra/rtadv.h b/zebra/rtadv.h index 2cae6d06f9..28019a3237 100644 --- a/zebra/rtadv.h +++ b/zebra/rtadv.h @@ -103,7 +103,8 @@ typedef enum { extern void rtadv_init(struct zebra_ns *); extern void rtadv_terminate(struct zebra_ns *); extern void rtadv_cmd_init(void); -extern void zebra_interface_radv_set(struct zserv *client, u_short length, - struct zebra_vrf *zvrf, int enable); +extern void zebra_interface_radv_set(ZAPI_HANDLER_ARGS, int enable); +extern void zebra_interface_radv_disable(ZAPI_HANDLER_ARGS); +extern void zebra_interface_radv_enable(ZAPI_HANDLER_ARGS); #endif /* _ZEBRA_RTADV_H */ diff --git a/zebra/zebra_mroute.c b/zebra/zebra_mroute.c index 1143451d62..e70b963cfd 100644 --- a/zebra/zebra_mroute.c +++ b/zebra/zebra_mroute.c @@ -31,9 +31,9 @@ #include "zebra/zebra_mroute.h" #include "zebra/rt.h" #include "zebra/debug.h" +#include "zebra/zserv.h" -void zebra_ipmr_route_stats(struct zserv *client, u_short length, - struct zebra_vrf *zvrf) +void zebra_ipmr_route_stats(ZAPI_HANDLER_ARGS) { struct mcast_route_data mroute; struct stream *s; diff --git a/zebra/zebra_mroute.h b/zebra/zebra_mroute.h index 5bee7b03d6..3385153600 100644 --- a/zebra/zebra_mroute.h +++ b/zebra/zebra_mroute.h @@ -22,13 +22,14 @@ #ifndef __ZEBRA_MROUTE_H__ #define __ZEBRA_MROUTE_H__ +#include "zebra/zserv.h" + struct mcast_route_data { struct prefix_sg sg; unsigned int ifindex; unsigned long long lastused; }; -void zebra_ipmr_route_stats(struct zserv *client, u_short length, - struct zebra_vrf *zvf); +void zebra_ipmr_route_stats(ZAPI_HANDLER_ARGS); #endif diff --git a/zebra/zebra_ptm.c b/zebra/zebra_ptm.c index b0295d127e..0c48473aad 100644 --- a/zebra/zebra_ptm.c +++ b/zebra/zebra_ptm.c @@ -661,8 +661,7 @@ int zebra_ptm_sock_read(struct thread *thread) } /* BFD peer/dst register/update */ -void zebra_ptm_bfd_dst_register(struct zserv *client, u_short length, - int command, struct zebra_vrf *zvrf) +void zebra_ptm_bfd_dst_register(ZAPI_HANDLER_ARGS) { struct stream *s; struct prefix src_p; @@ -680,14 +679,14 @@ void zebra_ptm_bfd_dst_register(struct zserv *client, u_short length, int data_len = ZEBRA_PTM_SEND_MAX_SOCKBUF; unsigned int pid; - if (command == ZEBRA_BFD_DEST_UPDATE) + if (hdr->command == ZEBRA_BFD_DEST_UPDATE) client->bfd_peer_upd8_cnt++; else client->bfd_peer_add_cnt++; if (IS_ZEBRA_DEBUG_EVENT) zlog_debug("bfd_dst_register msg from client %s: length=%d", - zebra_route_string(client->proto), length); + zebra_route_string(client->proto), hdr->length); if (ptm_cb.ptm_sock == -1) { ptm_cb.t_timer = NULL; @@ -824,8 +823,7 @@ stream_failure: } /* BFD peer/dst deregister */ -void zebra_ptm_bfd_dst_deregister(struct zserv *client, u_short length, - struct zebra_vrf *zvrf) +void zebra_ptm_bfd_dst_deregister(ZAPI_HANDLER_ARGS) { struct stream *s; struct prefix src_p; @@ -843,7 +841,7 @@ void zebra_ptm_bfd_dst_deregister(struct zserv *client, u_short length, if (IS_ZEBRA_DEBUG_EVENT) zlog_debug("bfd_dst_deregister msg from client %s: length=%d", - zebra_route_string(client->proto), length); + zebra_route_string(client->proto), hdr->length); if (ptm_cb.ptm_sock == -1) { ptm_cb.t_timer = NULL; @@ -956,7 +954,7 @@ stream_failure: } /* BFD client register */ -void zebra_ptm_bfd_client_register(struct zserv *client, u_short length) +void zebra_ptm_bfd_client_register(ZAPI_HANDLER_ARGS) { struct stream *s; unsigned int pid; @@ -968,7 +966,7 @@ void zebra_ptm_bfd_client_register(struct zserv *client, u_short length) if (IS_ZEBRA_DEBUG_EVENT) zlog_debug("bfd_client_register msg from client %s: length=%d", - zebra_route_string(client->proto), length); + zebra_route_string(client->proto), hdr->length); s = client->ibuf; STREAM_GETL(s, pid); diff --git a/zebra/zebra_ptm.h b/zebra/zebra_ptm.h index 2397d53845..22cacd6fc0 100644 --- a/zebra/zebra_ptm.h +++ b/zebra/zebra_ptm.h @@ -22,6 +22,8 @@ #ifndef _ZEBRA_PTM_H #define _ZEBRA_PTM_H +#include "zebra/zserv.h" + extern const char ZEBRA_PTM_SOCK_NAME[]; #define ZEBRA_PTM_MAX_SOCKBUF 3200 /* 25B *128 ports */ #define ZEBRA_PTM_SEND_MAX_SOCKBUF 512 @@ -62,12 +64,11 @@ int zebra_ptm_connect(struct thread *t); void zebra_ptm_write(struct vty *vty); int zebra_ptm_get_enable_state(void); -void zebra_ptm_bfd_dst_register(struct zserv *client, u_short length, - int command, struct zebra_vrf *zvrf); -void zebra_ptm_bfd_dst_deregister(struct zserv *client, u_short length, - struct zebra_vrf *zvrf); +void zebra_ptm_bfd_dst_register(ZAPI_HANDLER_ARGS); +void zebra_ptm_bfd_dst_deregister(ZAPI_HANDLER_ARGS); +void zebra_ptm_bfd_client_register(ZAPI_HANDLER_ARGS); + void zebra_ptm_show_status(struct vty *vty, struct interface *ifp); -void zebra_ptm_bfd_client_register(struct zserv *client, u_short length); void zebra_ptm_if_init(struct zebra_if *zebra_ifp); void zebra_ptm_if_set_ptm_state(struct interface *ifp, struct zebra_if *zebra_ifp); diff --git a/zebra/zebra_vxlan.c b/zebra/zebra_vxlan.c index bac589a841..f22d5160fb 100644 --- a/zebra/zebra_vxlan.c +++ b/zebra/zebra_vxlan.c @@ -46,6 +46,7 @@ #include "zebra/zebra_vxlan.h" #include "zebra/zebra_memory.h" #include "zebra/zebra_l2.h" +#include "zebra/zserv.h" DEFINE_MTYPE_STATIC(ZEBRA, HOST_PREFIX, "host prefix"); DEFINE_MTYPE_STATIC(ZEBRA, ZVNI, "VNI hash"); @@ -4863,8 +4864,7 @@ int zebra_vxlan_local_neigh_add_update(struct interface *ifp, /* * Handle message from client to delete a remote MACIP for a VNI. */ -void zebra_vxlan_remote_macip_del(struct zserv *client, u_short length, - struct zebra_vrf *zvrf) +void zebra_vxlan_remote_macip_del(ZAPI_HANDLER_ARGS) { struct stream *s; vni_t vni; @@ -4886,7 +4886,7 @@ void zebra_vxlan_remote_macip_del(struct zserv *client, u_short length, s = client->ibuf; - while (l < length) { + while (l < hdr->length) { /* Obtain each remote MACIP and process. */ /* Message contains VNI, followed by MAC followed by IP (if any) * followed by remote VTEP IP. @@ -5016,8 +5016,7 @@ stream_failure: * could be just the add of a MAC address or the add of a neighbor * (IP+MAC). */ -void zebra_vxlan_remote_macip_add(struct zserv *client, u_short length, - struct zebra_vrf *zvrf) +void zebra_vxlan_remote_macip_add(ZAPI_HANDLER_ARGS) { struct stream *s; vni_t vni; @@ -5050,7 +5049,7 @@ void zebra_vxlan_remote_macip_add(struct zserv *client, u_short length, s = client->ibuf; - while (l < length) { + while (l < hdr->length) { /* Obtain each remote MACIP and process. */ /* Message contains VNI, followed by MAC followed by IP (if any) * followed by remote VTEP IP. @@ -5543,8 +5542,7 @@ int zebra_vxlan_local_mac_add_update(struct interface *ifp, /* * Handle message from client to delete a remote VTEP for a VNI. */ -void zebra_vxlan_remote_vtep_del(struct zserv *client, u_short length, - struct zebra_vrf *zvrf) +void zebra_vxlan_remote_vtep_del(ZAPI_HANDLER_ARGS) { struct stream *s; u_short l = 0; @@ -5570,7 +5568,7 @@ void zebra_vxlan_remote_vtep_del(struct zserv *client, u_short length, s = client->ibuf; - while (l < length) { + while (l < hdr->length) { /* Obtain each remote VTEP and process. */ STREAM_GETL(s, vni); l += 4; @@ -5629,8 +5627,7 @@ stream_failure: /* * Handle message from client to add a remote VTEP for a VNI. */ -void zebra_vxlan_remote_vtep_add(struct zserv *client, u_short length, - struct zebra_vrf *zvrf) +void zebra_vxlan_remote_vtep_add(ZAPI_HANDLER_ARGS) { struct stream *s; u_short l = 0; @@ -5655,7 +5652,7 @@ void zebra_vxlan_remote_vtep_add(struct zserv *client, u_short length, s = client->ibuf; - while (l < length) { + while (l < hdr->length) { /* Obtain each remote VTEP and process. */ STREAM_GETL(s, vni); l += 4; @@ -6512,8 +6509,7 @@ int zebra_vxlan_vrf_delete(struct zebra_vrf *zvrf) * Handle message from client to enable/disable advertisement of g/w macip * routes */ -void zebra_vxlan_advertise_subnet(struct zserv *client, u_short length, - struct zebra_vrf *zvrf) +void zebra_vxlan_advertise_subnet(ZAPI_HANDLER_ARGS) { struct stream *s; int advertise; @@ -6578,8 +6574,7 @@ void zebra_vxlan_advertise_subnet(struct zserv *client, u_short length, * Handle message from client to enable/disable advertisement of g/w macip * routes */ -void zebra_vxlan_advertise_gw_macip(struct zserv *client, u_short length, - struct zebra_vrf *zvrf) +void zebra_vxlan_advertise_gw_macip(ZAPI_HANDLER_ARGS) { struct stream *s; int advertise; @@ -6686,8 +6681,8 @@ stream_failure: * when disabled, the entries should be deleted and remote VTEPs and MACs * uninstalled from the kernel. */ -void zebra_vxlan_advertise_all_vni(struct zserv *client, u_short length, - struct zebra_vrf *zvrf) +void zebra_vxlan_advertise_all_vni(ZAPI_HANDLER_ARGS) + { struct stream *s = NULL; int advertise = 0; diff --git a/zebra/zebra_vxlan.h b/zebra/zebra_vxlan.h index af76a41d80..62c6519d50 100644 --- a/zebra/zebra_vxlan.h +++ b/zebra/zebra_vxlan.h @@ -33,6 +33,7 @@ #include "lib/json.h" #include "zebra/zebra_vrf.h" +#include "zebra/zserv.h" /* Is EVPN enabled? */ #define EVPN_ENABLED(zvrf) (zvrf)->advertise_all_vni @@ -52,20 +53,14 @@ static inline int is_evpn_enabled() #define VNI_STR_LEN 32 /* zserv handlers */ -extern void zebra_vxlan_remote_macip_add(struct zserv *client, u_short length, - struct zebra_vrf *zvrf); -extern void zebra_vxlan_remote_macip_del(struct zserv *client, u_short length, - struct zebra_vrf *zvrf); -extern void zebra_vxlan_remote_vtep_add(struct zserv *client, u_short length, - struct zebra_vrf *zvrf); -extern void zebra_vxlan_remote_vtep_del(struct zserv *client, u_short length, - struct zebra_vrf *zvrf); -extern void zebra_vxlan_advertise_subnet(struct zserv *client, u_short length, - struct zebra_vrf *zvrf); -extern void zebra_vxlan_advertise_gw_macip(struct zserv *client, u_short length, - struct zebra_vrf *zvrf); -extern void zebra_vxlan_advertise_all_vni(struct zserv *client, u_short length, - struct zebra_vrf *zvrf); +extern void zebra_vxlan_remote_macip_add(ZAPI_HANDLER_ARGS); +extern void zebra_vxlan_remote_macip_del(ZAPI_HANDLER_ARGS); +extern void zebra_vxlan_remote_vtep_add(ZAPI_HANDLER_ARGS); +extern void zebra_vxlan_remote_vtep_del(ZAPI_HANDLER_ARGS); +extern void zebra_vxlan_advertise_subnet(ZAPI_HANDLER_ARGS); +extern void zebra_vxlan_advertise_gw_macip(ZAPI_HANDLER_ARGS); +extern void zebra_vxlan_advertise_all_vni(ZAPI_HANDLER_ARGS); + extern int is_l3vni_for_prefix_routes_only(vni_t vni); extern ifindex_t get_l3vni_svi_ifindex(vrf_id_t vrf_id); diff --git a/zebra/zserv.c b/zebra/zserv.c index 3ecc82be42..127913a63a 100644 --- a/zebra/zserv.c +++ b/zebra/zserv.c @@ -692,27 +692,34 @@ static int zsend_write_nexthop(struct stream *s, struct nexthop *nexthop) return 1; } +int cmd2type[] = { + [ZEBRA_NEXTHOP_REGISTER] = RNH_NEXTHOP_TYPE, + [ZEBRA_NEXTHOP_UNREGISTER] = RNH_NEXTHOP_TYPE, + [ZEBRA_IMPORT_ROUTE_REGISTER] = RNH_IMPORT_CHECK_TYPE, + [ZEBRA_IMPORT_ROUTE_UNREGISTER] = RNH_IMPORT_CHECK_TYPE, +}; + /* Nexthop register */ -static void zserv_rnh_register(struct zserv *client, u_short length, - rnh_type_t type, struct zebra_vrf *zvrf) +static void zserv_rnh_register(ZAPI_HANDLER_ARGS) { struct rnh *rnh; struct stream *s; struct prefix p; u_short l = 0; u_char flags = 0; + uint16_t type = cmd2type[hdr->command]; if (IS_ZEBRA_DEBUG_NHT) zlog_debug( "rnh_register msg from client %s: length=%d, type=%s\n", - zebra_route_string(client->proto), length, + zebra_route_string(client->proto), hdr->length, (type == RNH_NEXTHOP_TYPE) ? "nexthop" : "route"); s = client->ibuf; client->nh_reg_time = monotime(NULL); - while (l < length) { + while (l < hdr->length) { STREAM_GETC(s, flags); STREAM_GETW(s, p.family); STREAM_GETC(s, p.prefixlen); @@ -768,21 +775,21 @@ stream_failure: } /* Nexthop register */ -static void zserv_rnh_unregister(struct zserv *client, u_short length, - rnh_type_t type, struct zebra_vrf *zvrf) +static void zserv_rnh_unregister(ZAPI_HANDLER_ARGS) { struct rnh *rnh; struct stream *s; struct prefix p; u_short l = 0; + uint16_t type = cmd2type[hdr->command]; if (IS_ZEBRA_DEBUG_NHT) zlog_debug("rnh_unregister msg from client %s: length=%d\n", - zebra_route_string(client->proto), length); + zebra_route_string(client->proto), hdr->length); s = client->ibuf; - while (l < length) { + while (l < hdr->length) { uint8_t flags; STREAM_GETC(s, flags); @@ -829,10 +836,9 @@ stream_failure: #define ZEBRA_MIN_FEC_LENGTH 5 /* FEC register */ -static void zserv_fec_register(struct zserv *client, u_short length) +static void zserv_fec_register(ZAPI_HANDLER_ARGS) { struct stream *s; - struct zebra_vrf *zvrf; u_short l = 0; struct prefix p; u_int16_t flags; @@ -847,14 +853,14 @@ static void zserv_fec_register(struct zserv *client, u_short length) * The minimum amount of data that can be sent for one fec * registration */ - if (length < ZEBRA_MIN_FEC_LENGTH) { + if (hdr->length < ZEBRA_MIN_FEC_LENGTH) { zlog_err( "fec_register: Received a fec register of length %d, it is of insufficient size to properly decode", - length); + hdr->length); return; } - while (l < length) { + while (l < hdr->length) { STREAM_GETW(s, flags); memset(&p, 0, sizeof(p)); STREAM_GETW(s, p.family); @@ -889,10 +895,9 @@ stream_failure: } /* FEC unregister */ -static void zserv_fec_unregister(struct zserv *client, u_short length) +static void zserv_fec_unregister(ZAPI_HANDLER_ARGS) { struct stream *s; - struct zebra_vrf *zvrf; u_short l = 0; struct prefix p; uint16_t flags; @@ -906,14 +911,14 @@ static void zserv_fec_unregister(struct zserv *client, u_short length) * The minimum amount of data that can be sent for one * fec unregistration */ - if (length < ZEBRA_MIN_FEC_LENGTH) { + if (hdr->length < ZEBRA_MIN_FEC_LENGTH) { zlog_err( "fec_unregister: Received a fec unregister of length %d, it is of insufficient size to properly decode", - length); + hdr->length); return; } - while (l < length) { + while (l < hdr->length) { STREAM_GETW(s, flags); if (flags != 0) goto stream_failure; @@ -1133,8 +1138,8 @@ int zsend_pw_update(struct zserv *client, struct zebra_pw *pw) /* Register zebra server interface information. Send current all interface and address information. */ -static void zread_interface_add(struct zserv *client, u_short length, - struct zebra_vrf *zvrf) +static void zread_interface_add(ZAPI_HANDLER_ARGS) + { struct vrf *vrf; struct interface *ifp; @@ -1159,8 +1164,7 @@ static void zread_interface_add(struct zserv *client, u_short length, } /* Unregister zebra server interface information. */ -static void zread_interface_delete(struct zserv *client, u_short length, - struct zebra_vrf *zvrf) +static void zread_interface_delete(ZAPI_HANDLER_ARGS) { vrf_bitmap_unset(client->ifinfo, zvrf_id(zvrf)); } @@ -1177,8 +1181,7 @@ void zserv_nexthop_num_warn(const char *caller, const struct prefix *p, } } -static void zread_route_add(struct zserv *client, u_short length, - struct zebra_vrf *zvrf) +static void zread_route_add(ZAPI_HANDLER_ARGS) { struct stream *s; struct zapi_route api; @@ -1332,8 +1335,7 @@ static void zread_route_add(struct zserv *client, u_short length, } } -static void zread_route_del(struct zserv *client, u_short length, - struct zebra_vrf *zvrf) +static void zread_route_del(ZAPI_HANDLER_ARGS) { struct stream *s; struct zapi_route api; @@ -1375,8 +1377,7 @@ static void zread_route_del(struct zserv *client, u_short length, * Parse the ZEBRA_IPV4_ROUTE_ADD sent from client. Update re and * add kernel route. */ -static void zread_ipv4_add(struct zserv *client, u_short length, - struct zebra_vrf *zvrf) +static void zread_ipv4_add(ZAPI_HANDLER_ARGS) { int i; struct route_entry *re; @@ -1530,8 +1531,7 @@ stream_failure: } /* Zebra server IPv4 prefix delete function. */ -static void zread_ipv4_delete(struct zserv *client, u_short length, - struct zebra_vrf *zvrf) +static void zread_ipv4_delete(ZAPI_HANDLER_ARGS) { struct stream *s; struct zapi_ipv4 api; @@ -1569,8 +1569,7 @@ stream_failure: } /* MRIB Nexthop lookup for IPv4. */ -static void zread_ipv4_nexthop_lookup_mrib(struct zserv *client, u_short length, - struct zebra_vrf *zvrf) +static void zread_ipv4_nexthop_lookup_mrib(ZAPI_HANDLER_ARGS) { struct in_addr addr; struct route_entry *re; @@ -1585,9 +1584,7 @@ stream_failure: } /* Zebra server IPv6 prefix add function. */ -static void zread_ipv4_route_ipv6_nexthop_add(struct zserv *client, - u_short length, - struct zebra_vrf *zvrf) +static void zread_ipv4_route_ipv6_nexthop_add(ZAPI_HANDLER_ARGS) { unsigned int i; struct stream *s; @@ -1760,8 +1757,7 @@ stream_failure: return; } -static void zread_ipv6_add(struct zserv *client, u_short length, - struct zebra_vrf *zvrf) +static void zread_ipv6_add(ZAPI_HANDLER_ARGS) { unsigned int i; struct stream *s; @@ -1956,8 +1952,7 @@ stream_failure: } /* Zebra server IPv6 prefix delete function. */ -static void zread_ipv6_delete(struct zserv *client, u_short length, - struct zebra_vrf *zvrf) +static void zread_ipv6_delete(ZAPI_HANDLER_ARGS) { struct stream *s; struct zapi_ipv6 api; @@ -1999,8 +1994,7 @@ stream_failure: } /* Register zebra server router-id information. Send current router-id */ -static void zread_router_id_add(struct zserv *client, u_short length, - struct zebra_vrf *zvrf) +static void zread_router_id_add(ZAPI_HANDLER_ARGS) { struct prefix p; @@ -2013,14 +2007,13 @@ static void zread_router_id_add(struct zserv *client, u_short length, } /* Unregister zebra server router-id information. */ -static void zread_router_id_delete(struct zserv *client, u_short length, - struct zebra_vrf *zvrf) +static void zread_router_id_delete(ZAPI_HANDLER_ARGS) { vrf_bitmap_unset(client->ridinfo, zvrf_id(zvrf)); } /* Tie up route-type and client->sock */ -static void zread_hello(struct zserv *client) +static void zread_hello(ZAPI_HANDLER_ARGS) { /* type of protocol (lib/zebra.h) */ u_char proto; @@ -2050,8 +2043,7 @@ stream_failure: } /* Unregister all information in a VRF. */ -static void zread_vrf_unregister(struct zserv *client, u_short length, - struct zebra_vrf *zvrf) +static void zread_vrf_unregister(ZAPI_HANDLER_ARGS) { int i; afi_t afi; @@ -2064,8 +2056,7 @@ static void zread_vrf_unregister(struct zserv *client, u_short length, vrf_bitmap_unset(client->ridinfo, zvrf_id(zvrf)); } -static void zread_mpls_labels(int command, struct zserv *client, u_short length, - struct zebra_vrf *zvrf) +static void zread_mpls_labels(ZAPI_HANDLER_ARGS) { struct stream *s; enum lsp_types_t type; @@ -2135,12 +2126,12 @@ static void zread_mpls_labels(int command, struct zserv *client, u_short length, if (!mpls_enabled) return; - if (command == ZEBRA_MPLS_LABELS_ADD) { + if (hdr->command == ZEBRA_MPLS_LABELS_ADD) { mpls_lsp_install(zvrf, type, in_label, out_label, gtype, &gate, ifindex); mpls_ftn_update(1, zvrf, type, &prefix, gtype, &gate, ifindex, distance, out_label); - } else if (command == ZEBRA_MPLS_LABELS_DELETE) { + } else if (hdr->command == ZEBRA_MPLS_LABELS_DELETE) { mpls_lsp_uninstall(zvrf, type, in_label, gtype, &gate, ifindex); mpls_ftn_update(0, zvrf, type, &prefix, gtype, &gate, ifindex, distance, out_label); @@ -2280,19 +2271,19 @@ static void zread_release_label_chunk(struct zserv *client) stream_failure: return; } -static void zread_label_manager_request(int cmd, struct zserv *client, - struct zebra_vrf *zvrf) +static void zread_label_manager_request(ZAPI_HANDLER_ARGS) { /* to avoid sending other messages like ZERBA_INTERFACE_UP */ - if (cmd == ZEBRA_LABEL_MANAGER_CONNECT) + if (hdr->command == ZEBRA_LABEL_MANAGER_CONNECT) client->is_synchronous = 1; /* external label manager */ if (lm_is_external) - zread_relay_label_manager_request(cmd, client, zvrf_id(zvrf)); + zread_relay_label_manager_request(hdr->command, client, + zvrf_id(zvrf)); /* this is a label manager */ else { - if (cmd == ZEBRA_LABEL_MANAGER_CONNECT) + if (hdr->command == ZEBRA_LABEL_MANAGER_CONNECT) zread_label_manager_connect(client, zvrf_id(zvrf)); else { /* Sanity: don't allow 'unidentified' requests */ @@ -2301,16 +2292,15 @@ static void zread_label_manager_request(int cmd, struct zserv *client, "Got label request from an unidentified client"); return; } - if (cmd == ZEBRA_GET_LABEL_CHUNK) + if (hdr->command == ZEBRA_GET_LABEL_CHUNK) zread_get_label_chunk(client, zvrf_id(zvrf)); - else if (cmd == ZEBRA_RELEASE_LABEL_CHUNK) + else if (hdr->command == ZEBRA_RELEASE_LABEL_CHUNK) zread_release_label_chunk(client); } } } -static void zread_pseudowire(int command, struct zserv *client, u_short length, - struct zebra_vrf *zvrf) +static void zread_pseudowire(ZAPI_HANDLER_ARGS) { struct stream *s; char ifname[IF_NAMESIZE]; @@ -2350,12 +2340,12 @@ static void zread_pseudowire(int command, struct zserv *client, u_short length, protocol = client->proto; pw = zebra_pw_find(zvrf, ifname); - switch (command) { + switch (hdr->command) { case ZEBRA_PW_ADD: if (pw) { zlog_warn("%s: pseudowire %s already exists [%s]", __func__, ifname, - zserv_command_string(command)); + zserv_command_string(hdr->command)); return; } @@ -2364,7 +2354,7 @@ static void zread_pseudowire(int command, struct zserv *client, u_short length, case ZEBRA_PW_DELETE: if (!pw) { zlog_warn("%s: pseudowire %s not found [%s]", __func__, - ifname, zserv_command_string(command)); + ifname, zserv_command_string(hdr->command)); return; } @@ -2374,11 +2364,11 @@ static void zread_pseudowire(int command, struct zserv *client, u_short length, case ZEBRA_PW_UNSET: if (!pw) { zlog_warn("%s: pseudowire %s not found [%s]", __func__, - ifname, zserv_command_string(command)); + ifname, zserv_command_string(hdr->command)); return; } - switch (command) { + switch (hdr->command) { case ZEBRA_PW_SET: pw->enabled = 1; break; @@ -2528,7 +2518,7 @@ static void zebra_client_create(int sock) zebra_vrf_update_all(client); } -static void zread_interface_set_master(struct zserv *client, u_short length) +static void zread_interface_set_master(ZAPI_HANDLER_ARGS) { struct interface *master; struct interface *slave; @@ -2554,7 +2544,7 @@ stream_failure: } -static void zread_vrf_label(struct zserv *client, struct zebra_vrf *zvrf) +static void zread_vrf_label(ZAPI_HANDLER_ARGS) { struct interface *ifp; mpls_label_t nlabel; @@ -2622,8 +2612,7 @@ stream_failure: return; } -static inline void zread_rule(uint16_t command, struct zserv *client, - uint16_t length, struct zebra_vrf *zvrf) +static inline void zread_rule(ZAPI_HANDLER_ARGS) { struct zebra_pbr_rule zpr; struct stream *s; @@ -2671,7 +2660,7 @@ static inline void zread_rule(uint16_t command, struct zserv *client, if (zpr.filter.dst_port) zpr.filter.filter_bm |= PBR_FILTER_DST_PORT; - if (command == ZEBRA_RULE_ADD) + if (hdr->command == ZEBRA_RULE_ADD) zebra_pbr_add_rule(zvrf->zns, &zpr); else zebra_pbr_del_rule(zvrf->zns, &zpr); @@ -2698,162 +2687,78 @@ stream_failure: return false; } +void (*zserv_handlers[])(ZAPI_HANDLER_ARGS) = { + [ZEBRA_ROUTER_ID_ADD] = zread_router_id_add, + [ZEBRA_ROUTER_ID_DELETE] = zread_router_id_delete, + [ZEBRA_INTERFACE_ADD] = zread_interface_add, + [ZEBRA_INTERFACE_DELETE] = zread_interface_delete, + [ZEBRA_ROUTE_ADD] = zread_route_add, + [ZEBRA_ROUTE_DELETE] = zread_route_del, + [ZEBRA_IPV4_ROUTE_ADD] = zread_ipv4_add, + [ZEBRA_IPV4_ROUTE_DELETE] = zread_ipv4_delete, + [ZEBRA_IPV4_ROUTE_IPV6_NEXTHOP_ADD] = zread_ipv4_route_ipv6_nexthop_add, + [ZEBRA_IPV6_ROUTE_ADD] = zread_ipv6_add, + [ZEBRA_IPV6_ROUTE_DELETE] = zread_ipv6_delete, + [ZEBRA_REDISTRIBUTE_ADD] = zebra_redistribute_add, + [ZEBRA_REDISTRIBUTE_DELETE] = zebra_redistribute_delete, + [ZEBRA_REDISTRIBUTE_DEFAULT_ADD] = zebra_redistribute_default_add, + [ZEBRA_REDISTRIBUTE_DEFAULT_DELETE] = zebra_redistribute_default_delete, + [ZEBRA_IPV4_NEXTHOP_LOOKUP_MRIB] = zread_ipv4_nexthop_lookup_mrib, + [ZEBRA_HELLO] = zread_hello, + [ZEBRA_NEXTHOP_REGISTER] = zserv_rnh_register, + [ZEBRA_NEXTHOP_UNREGISTER] = zserv_rnh_unregister, + [ZEBRA_IMPORT_ROUTE_REGISTER] = zserv_rnh_register, + [ZEBRA_IMPORT_ROUTE_UNREGISTER] = zserv_rnh_unregister, + [ZEBRA_BFD_DEST_UPDATE] = zebra_ptm_bfd_dst_register, + [ZEBRA_BFD_DEST_REGISTER] = zebra_ptm_bfd_dst_register, + [ZEBRA_BFD_DEST_DEREGISTER] = zebra_ptm_bfd_dst_deregister, + [ZEBRA_VRF_UNREGISTER] = zread_vrf_unregister, + [ZEBRA_VRF_LABEL] = zread_vrf_label, + [ZEBRA_BFD_CLIENT_REGISTER] = zebra_ptm_bfd_client_register, +#if defined(HAVE_RTADV) + [ZEBRA_INTERFACE_ENABLE_RADV] = zebra_interface_radv_enable, + [ZEBRA_INTERFACE_DISABLE_RADV] = zebra_interface_radv_disable, +#else + [ZEBRA_INTERFACE_ENABLE_RADV] = NULL, + [ZEBRA_INTERFACE_DISABLE_RADV] = NULL, +#endif + [ZEBRA_MPLS_LABELS_ADD] = zread_mpls_labels, + [ZEBRA_MPLS_LABELS_DELETE] = zread_mpls_labels, + [ZEBRA_IPMR_ROUTE_STATS] = zebra_ipmr_route_stats, + [ZEBRA_LABEL_MANAGER_CONNECT] = zread_label_manager_request, + [ZEBRA_GET_LABEL_CHUNK] = zread_label_manager_request, + [ZEBRA_RELEASE_LABEL_CHUNK] = zread_label_manager_request, + [ZEBRA_FEC_REGISTER] = zserv_fec_register, + [ZEBRA_FEC_UNREGISTER] = zserv_fec_unregister, + [ZEBRA_ADVERTISE_DEFAULT_GW] = zebra_vxlan_advertise_gw_macip, + [ZEBRA_ADVERTISE_SUBNET] = zebra_vxlan_advertise_subnet, + [ZEBRA_ADVERTISE_ALL_VNI] = zebra_vxlan_advertise_all_vni, + [ZEBRA_REMOTE_VTEP_ADD] = zebra_vxlan_remote_vtep_add, + [ZEBRA_REMOTE_VTEP_DEL] = zebra_vxlan_remote_vtep_del, + [ZEBRA_REMOTE_MACIP_ADD] = zebra_vxlan_remote_macip_add, + [ZEBRA_REMOTE_MACIP_DEL] = zebra_vxlan_remote_macip_del, + [ZEBRA_INTERFACE_SET_MASTER] = zread_interface_set_master, + [ZEBRA_PW_ADD] = zread_pseudowire, + [ZEBRA_PW_DELETE] = zread_pseudowire, + [ZEBRA_PW_SET] = zread_pseudowire, + [ZEBRA_PW_UNSET] = zread_pseudowire, + [ZEBRA_RULE_ADD] = zread_rule, + [ZEBRA_RULE_DELETE] = zread_rule, +}; + static inline void zserv_handle_commands(struct zserv *client, uint16_t command, uint16_t length, struct zebra_vrf *zvrf) { struct zmsghdr hdr; + stream_set_getp(client->ibuf, 0); zserv_read_header(client->ibuf, &hdr); - - switch (command) { - case ZEBRA_ROUTER_ID_ADD: - zread_router_id_add(client, length, zvrf); - break; - case ZEBRA_ROUTER_ID_DELETE: - zread_router_id_delete(client, length, zvrf); - break; - case ZEBRA_INTERFACE_ADD: - zread_interface_add(client, length, zvrf); - break; - 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; - case ZEBRA_IPV4_ROUTE_DELETE: - zread_ipv4_delete(client, length, zvrf); - break; - case ZEBRA_IPV4_ROUTE_IPV6_NEXTHOP_ADD: - zread_ipv4_route_ipv6_nexthop_add(client, length, zvrf); - break; - case ZEBRA_IPV6_ROUTE_ADD: - zread_ipv6_add(client, length, zvrf); - break; - case ZEBRA_IPV6_ROUTE_DELETE: - zread_ipv6_delete(client, length, zvrf); - break; - case ZEBRA_REDISTRIBUTE_ADD: - zebra_redistribute_add(command, client, length, zvrf); - break; - case ZEBRA_REDISTRIBUTE_DELETE: - zebra_redistribute_delete(command, client, length, zvrf); - break; - case ZEBRA_REDISTRIBUTE_DEFAULT_ADD: - zebra_redistribute_default_add(command, client, length, zvrf); - break; - case ZEBRA_REDISTRIBUTE_DEFAULT_DELETE: - zebra_redistribute_default_delete(command, client, length, - zvrf); - break; - case ZEBRA_IPV4_NEXTHOP_LOOKUP_MRIB: - zread_ipv4_nexthop_lookup_mrib(client, length, zvrf); - break; - case ZEBRA_HELLO: - zread_hello(client); - break; - case ZEBRA_NEXTHOP_REGISTER: - zserv_rnh_register(client, length, RNH_NEXTHOP_TYPE, zvrf); - break; - case ZEBRA_NEXTHOP_UNREGISTER: - zserv_rnh_unregister(client, length, RNH_NEXTHOP_TYPE, zvrf); - break; - case ZEBRA_IMPORT_ROUTE_REGISTER: - zserv_rnh_register(client, length, RNH_IMPORT_CHECK_TYPE, zvrf); - break; - case ZEBRA_IMPORT_ROUTE_UNREGISTER: - zserv_rnh_unregister(client, length, RNH_IMPORT_CHECK_TYPE, - zvrf); - break; - case ZEBRA_BFD_DEST_UPDATE: - case ZEBRA_BFD_DEST_REGISTER: - zebra_ptm_bfd_dst_register(client, length, command, zvrf); - break; - case ZEBRA_BFD_DEST_DEREGISTER: - zebra_ptm_bfd_dst_deregister(client, length, zvrf); - break; - case ZEBRA_VRF_UNREGISTER: - zread_vrf_unregister(client, length, zvrf); - break; - case ZEBRA_VRF_LABEL: - zread_vrf_label(client, zvrf); - break; - case ZEBRA_BFD_CLIENT_REGISTER: - zebra_ptm_bfd_client_register(client, length); - break; - case ZEBRA_INTERFACE_ENABLE_RADV: -#if defined(HAVE_RTADV) - zebra_interface_radv_set(client, length, zvrf, 1); -#endif - break; - case ZEBRA_INTERFACE_DISABLE_RADV: -#if defined(HAVE_RTADV) - zebra_interface_radv_set(client, length, zvrf, 0); -#endif - break; - case ZEBRA_MPLS_LABELS_ADD: - case ZEBRA_MPLS_LABELS_DELETE: - zread_mpls_labels(command, client, length, zvrf); - break; - case ZEBRA_IPMR_ROUTE_STATS: - zebra_ipmr_route_stats(client, length, zvrf); - break; - case ZEBRA_LABEL_MANAGER_CONNECT: - case ZEBRA_GET_LABEL_CHUNK: - case ZEBRA_RELEASE_LABEL_CHUNK: - zread_label_manager_request(command, client, zvrf); - break; - case ZEBRA_FEC_REGISTER: - zserv_fec_register(client, length); - break; - case ZEBRA_FEC_UNREGISTER: - zserv_fec_unregister(client, length); - break; - case ZEBRA_ADVERTISE_DEFAULT_GW: - zebra_vxlan_advertise_gw_macip(client, length, zvrf); - break; - case ZEBRA_ADVERTISE_SUBNET: - zebra_vxlan_advertise_subnet(client, length, zvrf); - break; - case ZEBRA_ADVERTISE_ALL_VNI: - zebra_vxlan_advertise_all_vni(client, length, zvrf); - break; - case ZEBRA_REMOTE_VTEP_ADD: - zebra_vxlan_remote_vtep_add(client, length, zvrf); - break; - case ZEBRA_REMOTE_VTEP_DEL: - zebra_vxlan_remote_vtep_del(client, length, zvrf); - break; - case ZEBRA_REMOTE_MACIP_ADD: - zebra_vxlan_remote_macip_add(client, length, zvrf); - break; - case ZEBRA_REMOTE_MACIP_DEL: - zebra_vxlan_remote_macip_del(client, length, zvrf); - break; - case ZEBRA_INTERFACE_SET_MASTER: - zread_interface_set_master(client, length); - break; - case ZEBRA_PW_ADD: - case ZEBRA_PW_DELETE: - case ZEBRA_PW_SET: - case ZEBRA_PW_UNSET: - zread_pseudowire(command, client, length, zvrf); - break; - case ZEBRA_RULE_ADD: - case ZEBRA_RULE_DELETE: - zread_rule(command, client, length, zvrf); - break; - default: - zlog_info("Zebra received unknown command %d", command); - break; - } + if (hdr.command > sizeof(zserv_handlers) + || zserv_handlers[hdr.command] == NULL) + zlog_info("Zebra received unknown command %d", hdr.command); + else + zserv_handlers[hdr.command](client, &hdr, zvrf); } #if defined(HANDLE_ZAPI_FUZZING) diff --git a/zebra/zserv.h b/zebra/zserv.h index a09baeff7a..74ff31bcf9 100644 --- a/zebra/zserv.h +++ b/zebra/zserv.h @@ -138,6 +138,9 @@ struct zmsghdr { uint16_t command; }; +#define ZAPI_HANDLER_ARGS \ + struct zserv *client, struct zmsghdr *hdr, struct zebra_vrf *zvrf + /* Zebra instance */ struct zebra_t { /* Thread master */ From 1002497af5aedffc661cb457c8775634a65c3a19 Mon Sep 17 00:00:00 2001 From: Quentin Young Date: Tue, 6 Mar 2018 18:08:37 -0500 Subject: [PATCH 19/25] zebra: reorganize zserv, batch i/o Group send and receive functions together, change handlers to take a message instead of looking at ->ibuf and ->obuf, allow zebra to read multiple packets off the wire at a time. Signed-off-by: Quentin Young --- zebra/label_manager.c | 22 +- zebra/redistribute.c | 12 +- zebra/redistribute.h | 3 +- zebra/rtadv.c | 19 +- zebra/rtadv.h | 2 +- zebra/zebra_mpls.c | 5 +- zebra/zebra_mroute.c | 11 +- zebra/zebra_ptm.c | 8 +- zebra/zebra_ptm.h | 5 +- zebra/zebra_ptm_redistribute.c | 10 +- zebra/zebra_rnh.c | 5 +- zebra/zebra_vxlan.c | 49 +- zebra/zebra_vxlan.h | 3 +- zebra/zebra_vxlan_null.c | 20 +- zebra/zserv.c | 1585 ++++++++++++++++---------------- zebra/zserv.h | 15 +- 16 files changed, 910 insertions(+), 864 deletions(-) diff --git a/zebra/label_manager.c b/zebra/label_manager.c index 5bf0fce094..b58f0c9ff8 100644 --- a/zebra/label_manager.c +++ b/zebra/label_manager.c @@ -50,6 +50,8 @@ DEFINE_MTYPE_STATIC(LBL_MGR, LM_CHUNK, "Label Manager Chunk"); * it will be a proxy to relay messages to external label manager * This zclient thus is to connect to it */ +static struct stream *ibuf; +static struct stream *obuf; static struct zclient *zclient; bool lm_is_external; @@ -69,7 +71,7 @@ static int relay_response_back(struct zserv *zserv) u_int16_t resp_cmd; src = zclient->ibuf; - dst = zserv->obuf; + dst = obuf; stream_reset(src); @@ -87,7 +89,7 @@ static int relay_response_back(struct zserv *zserv) /* send response back */ stream_copy(dst, src); - ret = writen(zserv->sock, dst->data, stream_get_endp(dst)); + ret = writen(zserv->sock, src->data, stream_get_endp(src)); if (ret <= 0) { zlog_err("%s: Error sending Label Manager response back: %s", __func__, strerror(errno)); @@ -116,10 +118,10 @@ static int lm_zclient_read(struct thread *t) static int reply_error(int cmd, struct zserv *zserv, vrf_id_t vrf_id) { + int ret; struct stream *s; - s = zserv->obuf; - stream_reset(s); + s = stream_new(ZEBRA_MAX_PACKET_SIZ); zclient_create_header(s, cmd, vrf_id); @@ -129,7 +131,10 @@ static int reply_error(int cmd, struct zserv *zserv, vrf_id_t vrf_id) /* Write packet size. */ stream_putw_at(s, 0, stream_get_endp(s)); - return writen(zserv->sock, s->data, stream_get_endp(s)); + ret = writen(zserv->sock, s->data, stream_get_endp(s)); + + stream_free(s); + return ret; } /** * Receive a request to get or release a label chunk and forward it to external @@ -161,7 +166,7 @@ int zread_relay_label_manager_request(int cmd, struct zserv *zserv, ret = relay_response_back(zserv); /* Send request to external label manager */ - src = zserv->ibuf; + src = ibuf; dst = zclient->obuf; stream_copy(dst, src); @@ -247,6 +252,9 @@ void label_manager_init(char *lm_zserv_path) lm_is_external = true; lm_zclient_init(lm_zserv_path); } + + ibuf = stream_new(ZEBRA_MAX_PACKET_SIZ); + obuf = stream_new(ZEBRA_MAX_PACKET_SIZ); } /** @@ -379,4 +387,6 @@ int release_daemon_chunks(u_char proto, u_short instance) void label_manager_close() { list_delete_and_null(&lbl_mgr.lc_list); + stream_free(ibuf); + stream_free(obuf); } diff --git a/zebra/redistribute.c b/zebra/redistribute.c index 93862cadc9..5a239306fb 100644 --- a/zebra/redistribute.c +++ b/zebra/redistribute.c @@ -249,9 +249,9 @@ void zebra_redistribute_add(ZAPI_HANDLER_ARGS) int type = 0; u_short instance; - STREAM_GETC(client->ibuf, afi); - STREAM_GETC(client->ibuf, type); - STREAM_GETW(client->ibuf, instance); + STREAM_GETC(msg, afi); + STREAM_GETC(msg, type); + STREAM_GETW(msg, instance); if (afi == 0 || afi > AFI_MAX) { zlog_warn("%s: Specified afi %d does not exist", @@ -292,9 +292,9 @@ void zebra_redistribute_delete(ZAPI_HANDLER_ARGS) int type = 0; u_short instance; - STREAM_GETC(client->ibuf, afi); - STREAM_GETC(client->ibuf, type); - STREAM_GETW(client->ibuf, instance); + STREAM_GETC(msg, afi); + STREAM_GETC(msg, type); + STREAM_GETW(msg, instance); if (afi == 0 || afi > AFI_MAX) { zlog_warn("%s: Specified afi %d does not exist", diff --git a/zebra/redistribute.h b/zebra/redistribute.h index 6ca3b57d4d..e551f820cc 100644 --- a/zebra/redistribute.h +++ b/zebra/redistribute.h @@ -27,11 +27,12 @@ #include "vty.h" #include "vrf.h" -/* zapi handlers */ +/* ZAPI command handlers */ extern void zebra_redistribute_add(ZAPI_HANDLER_ARGS); extern void zebra_redistribute_delete(ZAPI_HANDLER_ARGS); extern void zebra_redistribute_default_add(ZAPI_HANDLER_ARGS); extern void zebra_redistribute_default_delete(ZAPI_HANDLER_ARGS); +/* ----------------- */ extern void redistribute_update(struct prefix *, struct prefix *, struct route_entry *, struct route_entry *); diff --git a/zebra/rtadv.c b/zebra/rtadv.c index 56decdcdba..d0b821bfd2 100644 --- a/zebra/rtadv.c +++ b/zebra/rtadv.c @@ -43,7 +43,6 @@ #include "zebra/zserv.h" #include "zebra/zebra_ns.h" #include "zebra/zebra_vrf.h" -#include "zebra/zserv.h" extern struct zebra_privs_t zserv_privs; @@ -802,7 +801,7 @@ static void ipv6_nd_suppress_ra_set(struct interface *ifp, * if the operator has explicitly enabled RA. The enable request can also * specify a RA interval (in seconds). */ -void zebra_interface_radv_set(ZAPI_HANDLER_ARGS, int set) +static void zebra_interface_radv_set(ZAPI_HANDLER_ARGS, int enable) { struct stream *s; ifindex_t ifindex; @@ -810,7 +809,7 @@ void zebra_interface_radv_set(ZAPI_HANDLER_ARGS, int set) struct zebra_if *zif; int ra_interval; - s = client->ibuf; + s = msg; /* Get interface index and RA interval. */ STREAM_GETL(s, ifindex); @@ -818,26 +817,27 @@ void zebra_interface_radv_set(ZAPI_HANDLER_ARGS, int set) if (IS_ZEBRA_DEBUG_EVENT) zlog_debug("%u: IF %u RA %s from client %s, interval %ds", - zvrf_id(zvrf), ifindex, set ? "enable" : "disable", + zvrf_id(zvrf), ifindex, + enable ? "enable" : "disable", zebra_route_string(client->proto), ra_interval); /* Locate interface and check VRF match. */ ifp = if_lookup_by_index_per_ns(zebra_ns_lookup(NS_DEFAULT), ifindex); if (!ifp) { zlog_warn("%u: IF %u RA %s client %s - interface unknown", - zvrf_id(zvrf), ifindex, set ? "enable" : "disable", + zvrf_id(zvrf), ifindex, enable ? "enable" : "disable", zebra_route_string(client->proto)); return; } if (ifp->vrf_id != zvrf_id(zvrf)) { zlog_warn("%u: IF %u RA %s client %s - VRF mismatch, IF VRF %u", - zvrf_id(zvrf), ifindex, set ? "enable" : "disable", + zvrf_id(zvrf), ifindex, enable ? "enable" : "disable", zebra_route_string(client->proto), ifp->vrf_id); return; } zif = ifp->info; - if (set) { + if (enable) { SET_FLAG(zif->rtadv.ra_configured, BGP_RA_CONFIGURED); ipv6_nd_suppress_ra_set(ifp, RA_ENABLE); if (ra_interval @@ -860,12 +860,11 @@ stream_failure: void zebra_interface_radv_disable(ZAPI_HANDLER_ARGS) { - zebra_interface_radv_set(client, hdr, zvrf, 0); + zebra_interface_radv_set(client, hdr, msg, zvrf, 0); } - void zebra_interface_radv_enable(ZAPI_HANDLER_ARGS) { - zebra_interface_radv_set(client, hdr, zvrf, 1); + zebra_interface_radv_set(client, hdr, msg, zvrf, 1); } DEFUN (ipv6_nd_suppress_ra, diff --git a/zebra/rtadv.h b/zebra/rtadv.h index 28019a3237..8fd67c8a63 100644 --- a/zebra/rtadv.h +++ b/zebra/rtadv.h @@ -103,8 +103,8 @@ typedef enum { extern void rtadv_init(struct zebra_ns *); extern void rtadv_terminate(struct zebra_ns *); extern void rtadv_cmd_init(void); -extern void zebra_interface_radv_set(ZAPI_HANDLER_ARGS, int enable); extern void zebra_interface_radv_disable(ZAPI_HANDLER_ARGS); extern void zebra_interface_radv_enable(ZAPI_HANDLER_ARGS); + #endif /* _ZEBRA_RTADV_H */ diff --git a/zebra/zebra_mpls.c b/zebra/zebra_mpls.c index 0af06806d3..1868b4676d 100644 --- a/zebra/zebra_mpls.c +++ b/zebra/zebra_mpls.c @@ -455,8 +455,7 @@ static int fec_send(zebra_fec_t *fec, struct zserv *client) rn = fec->rn; /* Get output stream. */ - s = client->obuf; - stream_reset(s); + s = stream_new(ZEBRA_MAX_PACKET_SIZ); zclient_create_header(s, ZEBRA_FEC_UPDATE, VRF_DEFAULT); @@ -464,7 +463,7 @@ static int fec_send(zebra_fec_t *fec, struct zserv *client) stream_put_prefix(s, &rn->p); stream_putl(s, fec->label); stream_putw_at(s, 0, stream_get_endp(s)); - return zebra_server_send_message(client); + return zebra_server_send_message(client, s); } /* diff --git a/zebra/zebra_mroute.c b/zebra/zebra_mroute.c index e70b963cfd..042bd3769e 100644 --- a/zebra/zebra_mroute.c +++ b/zebra/zebra_mroute.c @@ -31,7 +31,6 @@ #include "zebra/zebra_mroute.h" #include "zebra/rt.h" #include "zebra/debug.h" -#include "zebra/zserv.h" void zebra_ipmr_route_stats(ZAPI_HANDLER_ARGS) { @@ -40,9 +39,9 @@ void zebra_ipmr_route_stats(ZAPI_HANDLER_ARGS) int suc = -1; memset(&mroute, 0, sizeof(mroute)); - STREAM_GET(&mroute.sg.src, client->ibuf, 4); - STREAM_GET(&mroute.sg.grp, client->ibuf, 4); - STREAM_GETL(client->ibuf, mroute.ifindex); + STREAM_GET(&mroute.sg.src, msg, 4); + STREAM_GET(&mroute.sg.grp, msg, 4); + STREAM_GETL(msg, mroute.ifindex); if (IS_ZEBRA_DEBUG_KERNEL) { char sbuf[40]; @@ -57,7 +56,7 @@ void zebra_ipmr_route_stats(ZAPI_HANDLER_ARGS) suc = kernel_get_ipmr_sg_stats(zvrf, &mroute); stream_failure: - s = client->obuf; + s = stream_new(ZEBRA_MAX_PACKET_SIZ); stream_reset(s); @@ -68,5 +67,5 @@ stream_failure: stream_putl(s, suc); stream_putw_at(s, 0, stream_get_endp(s)); - zebra_server_send_message(client); + zebra_server_send_message(client, s); } diff --git a/zebra/zebra_ptm.c b/zebra/zebra_ptm.c index 0c48473aad..67c7220b6f 100644 --- a/zebra/zebra_ptm.c +++ b/zebra/zebra_ptm.c @@ -702,7 +702,7 @@ void zebra_ptm_bfd_dst_register(ZAPI_HANDLER_ARGS) ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_BFD_CLIENT_FIELD, tmp_buf); - s = client->ibuf; + s = msg; STREAM_GETL(s, pid); sprintf(tmp_buf, "%d", pid); @@ -819,7 +819,6 @@ void zebra_ptm_bfd_dst_register(ZAPI_HANDLER_ARGS) stream_failure: ptm_lib_cleanup_msg(ptm_hdl, out_ctxt); - return; } /* BFD peer/dst deregister */ @@ -859,7 +858,7 @@ void zebra_ptm_bfd_dst_deregister(ZAPI_HANDLER_ARGS) ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_BFD_CLIENT_FIELD, tmp_buf); - s = client->ibuf; + s = msg; STREAM_GETL(s, pid); sprintf(tmp_buf, "%d", pid); @@ -950,7 +949,6 @@ void zebra_ptm_bfd_dst_deregister(ZAPI_HANDLER_ARGS) stream_failure: ptm_lib_cleanup_msg(ptm_hdl, out_ctxt); - return; } /* BFD client register */ @@ -968,7 +966,7 @@ void zebra_ptm_bfd_client_register(ZAPI_HANDLER_ARGS) zlog_debug("bfd_client_register msg from client %s: length=%d", zebra_route_string(client->proto), hdr->length); - s = client->ibuf; + s = msg; STREAM_GETL(s, pid); if (ptm_cb.ptm_sock == -1) { diff --git a/zebra/zebra_ptm.h b/zebra/zebra_ptm.h index 22cacd6fc0..0b41410bec 100644 --- a/zebra/zebra_ptm.h +++ b/zebra/zebra_ptm.h @@ -22,14 +22,14 @@ #ifndef _ZEBRA_PTM_H #define _ZEBRA_PTM_H -#include "zebra/zserv.h" - extern const char ZEBRA_PTM_SOCK_NAME[]; #define ZEBRA_PTM_MAX_SOCKBUF 3200 /* 25B *128 ports */ #define ZEBRA_PTM_SEND_MAX_SOCKBUF 512 #define ZEBRA_PTM_BFD_CLIENT_FLAG_REG (1 << 1) /* client registered with BFD */ +#include "zebra/zserv.h" + /* Zebra ptm context block */ struct zebra_ptm_cb { int ptm_sock; /* ptm file descriptor. */ @@ -64,6 +64,7 @@ int zebra_ptm_connect(struct thread *t); void zebra_ptm_write(struct vty *vty); int zebra_ptm_get_enable_state(void); +/* ZAPI message handlers */ void zebra_ptm_bfd_dst_register(ZAPI_HANDLER_ARGS); void zebra_ptm_bfd_dst_deregister(ZAPI_HANDLER_ARGS); void zebra_ptm_bfd_client_register(ZAPI_HANDLER_ARGS); diff --git a/zebra/zebra_ptm_redistribute.c b/zebra/zebra_ptm_redistribute.c index 8fddd400cc..fe788ac4d7 100644 --- a/zebra/zebra_ptm_redistribute.c +++ b/zebra/zebra_ptm_redistribute.c @@ -38,8 +38,7 @@ static int zsend_interface_bfd_update(int cmd, struct zserv *client, if (!client->ifinfo) return 0; - s = client->obuf; - stream_reset(s); + s = stream_new(ZEBRA_MAX_PACKET_SIZ); zclient_create_header(s, cmd, vrf_id); if (ifp) @@ -66,7 +65,7 @@ static int zsend_interface_bfd_update(int cmd, struct zserv *client, stream_putw_at(s, 0, stream_get_endp(s)); client->if_bfd_cnt++; - return zebra_server_send_message(client); + return zebra_server_send_message(client, s); } void zebra_interface_bfd_update(struct interface *ifp, struct prefix *dp, @@ -93,8 +92,7 @@ static int zsend_bfd_peer_replay(int cmd, struct zserv *client) { struct stream *s; - s = client->obuf; - stream_reset(s); + s = stream_new(ZEBRA_MAX_PACKET_SIZ); zclient_create_header(s, cmd, VRF_DEFAULT); @@ -102,7 +100,7 @@ static int zsend_bfd_peer_replay(int cmd, struct zserv *client) stream_putw_at(s, 0, stream_get_endp(s)); client->bfd_peer_replay_cnt++; - return zebra_server_send_message(client); + return zebra_server_send_message(client, s); } void zebra_bfd_peer_replay_req(void) diff --git a/zebra/zebra_rnh.c b/zebra/zebra_rnh.c index dd3fe17702..c9fb782ba6 100644 --- a/zebra/zebra_rnh.c +++ b/zebra/zebra_rnh.c @@ -995,8 +995,7 @@ static int send_client(struct rnh *rnh, struct zserv *client, rnh_type_t type, re = rnh->state; /* Get output stream. */ - s = client->obuf; - stream_reset(s); + s = stream_new(ZEBRA_MAX_PACKET_SIZ); zclient_create_header(s, cmd, vrf_id); @@ -1063,7 +1062,7 @@ static int send_client(struct rnh *rnh, struct zserv *client, rnh_type_t type, client->nh_last_upd_time = monotime(NULL); client->last_write_cmd = cmd; - return zebra_server_send_message(client); + return zebra_server_send_message(client, s); } static void print_nh(struct nexthop *nexthop, struct vty *vty) diff --git a/zebra/zebra_vxlan.c b/zebra/zebra_vxlan.c index f22d5160fb..a8d1848723 100644 --- a/zebra/zebra_vxlan.c +++ b/zebra/zebra_vxlan.c @@ -46,7 +46,6 @@ #include "zebra/zebra_vxlan.h" #include "zebra/zebra_memory.h" #include "zebra/zebra_l2.h" -#include "zebra/zserv.h" DEFINE_MTYPE_STATIC(ZEBRA, HOST_PREFIX, "host prefix"); DEFINE_MTYPE_STATIC(ZEBRA, ZVNI, "VNI hash"); @@ -1158,8 +1157,7 @@ static int zvni_macip_send_msg_to_client(vni_t vni, struct ethaddr *macaddr, if (!client) return 0; - s = client->obuf; - stream_reset(s); + s = stream_new(ZEBRA_MAX_PACKET_SIZ); zclient_create_header(s, cmd, VRF_DEFAULT); stream_putl(s, vni); @@ -1196,7 +1194,7 @@ static int zvni_macip_send_msg_to_client(vni_t vni, struct ethaddr *macaddr, else client->macipdel_cnt++; - return zebra_server_send_message(client); + return zebra_server_send_message(client, s); } /* @@ -2566,8 +2564,7 @@ static int zvni_send_add_to_client(zebra_vni_t *zvni) if (!client) return 0; - s = client->obuf; - stream_reset(s); + s = stream_new(ZEBRA_MAX_PACKET_SIZ); zclient_create_header(s, ZEBRA_VNI_ADD, VRF_DEFAULT); stream_putl(s, zvni->vni); @@ -2584,7 +2581,7 @@ static int zvni_send_add_to_client(zebra_vni_t *zvni) zebra_route_string(client->proto)); client->vniadd_cnt++; - return zebra_server_send_message(client); + return zebra_server_send_message(client, s); } /* @@ -2600,7 +2597,7 @@ static int zvni_send_del_to_client(vni_t vni) if (!client) return 0; - s = client->obuf; + s = stream_new(ZEBRA_MAX_PACKET_SIZ); stream_reset(s); zclient_create_header(s, ZEBRA_VNI_DEL, VRF_DEFAULT); @@ -2614,7 +2611,7 @@ static int zvni_send_del_to_client(vni_t vni) zebra_route_string(client->proto)); client->vnidel_cnt++; - return zebra_server_send_message(client); + return zebra_server_send_message(client, s); } /* @@ -3551,8 +3548,7 @@ static int zl3vni_send_add_to_client(zebra_l3vni_t *zl3vni) memset(&rmac, 0, sizeof(struct ethaddr)); zl3vni_get_rmac(zl3vni, &rmac); - s = client->obuf; - stream_reset(s); + s = stream_new(ZEBRA_MAX_PACKET_SIZ); zclient_create_header(s, ZEBRA_L3VNI_ADD, zl3vni_vrf_id(zl3vni)); stream_putl(s, zl3vni->vni); @@ -3575,7 +3571,7 @@ static int zl3vni_send_add_to_client(zebra_l3vni_t *zl3vni) zebra_route_string(client->proto)); client->l3vniadd_cnt++; - return zebra_server_send_message(client); + return zebra_server_send_message(client, s); } /* @@ -3591,8 +3587,7 @@ static int zl3vni_send_del_to_client(zebra_l3vni_t *zl3vni) if (!client) return 0; - s = client->obuf; - stream_reset(s); + s = stream_new(ZEBRA_MAX_PACKET_SIZ); zclient_create_header(s, ZEBRA_L3VNI_DEL, zl3vni_vrf_id(zl3vni)); stream_putl(s, zl3vni->vni); @@ -3606,7 +3601,7 @@ static int zl3vni_send_del_to_client(zebra_l3vni_t *zl3vni) zebra_route_string(client->proto)); client->l3vnidel_cnt++; - return zebra_server_send_message(client); + return zebra_server_send_message(client, s); } static void zebra_vxlan_process_l3vni_oper_up(zebra_l3vni_t *zl3vni) @@ -3724,8 +3719,7 @@ static int ip_prefix_send_to_client(vrf_id_t vrf_id, struct prefix *p, if (!client) return 0; - s = client->obuf; - stream_reset(s); + s = stream_new(ZEBRA_MAX_PACKET_SIZ); zclient_create_header(s, cmd, vrf_id); stream_put(s, p, sizeof(struct prefix)); @@ -3744,7 +3738,7 @@ static int ip_prefix_send_to_client(vrf_id_t vrf_id, struct prefix *p, else client->prefixdel_cnt++; - return zebra_server_send_message(client); + return zebra_server_send_message(client, s); } /* re-add remote rmac if needed */ @@ -4884,7 +4878,7 @@ void zebra_vxlan_remote_macip_del(ZAPI_HANDLER_ARGS) memset(&ip, 0, sizeof(struct ipaddr)); memset(&vtep_ip, 0, sizeof(struct in_addr)); - s = client->ibuf; + s = msg; while (l < hdr->length) { /* Obtain each remote MACIP and process. */ @@ -5047,7 +5041,7 @@ void zebra_vxlan_remote_macip_add(ZAPI_HANDLER_ARGS) return; } - s = client->ibuf; + s = msg; while (l < hdr->length) { /* Obtain each remote MACIP and process. */ @@ -5566,7 +5560,7 @@ void zebra_vxlan_remote_vtep_del(ZAPI_HANDLER_ARGS) return; } - s = client->ibuf; + s = msg; while (l < hdr->length) { /* Obtain each remote VTEP and process. */ @@ -5650,7 +5644,7 @@ void zebra_vxlan_remote_vtep_add(ZAPI_HANDLER_ARGS) return; } - s = client->ibuf; + s = msg; while (l < hdr->length) { /* Obtain each remote VTEP and process. */ @@ -6526,7 +6520,7 @@ void zebra_vxlan_advertise_subnet(ZAPI_HANDLER_ARGS) return; } - s = client->ibuf; + s = msg; advertise = stream_getc(s); vni = stream_get3(s); @@ -6566,8 +6560,6 @@ void zebra_vxlan_advertise_subnet(ZAPI_HANDLER_ARGS) zvni_advertise_subnet(zvni, vlan_if, 1); else zvni_advertise_subnet(zvni, vlan_if, 0); - - return; } /* @@ -6588,7 +6580,7 @@ void zebra_vxlan_advertise_gw_macip(ZAPI_HANDLER_ARGS) return; } - s = client->ibuf; + s = msg; STREAM_GETC(s, advertise); STREAM_GET(&vni, s, 3); @@ -6620,7 +6612,7 @@ void zebra_vxlan_advertise_gw_macip(ZAPI_HANDLER_ARGS) zvni = zvni_lookup(vni); if (!zvni) - return; + return 0; if (IS_ZEBRA_DEBUG_VXLAN) zlog_debug( @@ -6682,7 +6674,6 @@ stream_failure: * uninstalled from the kernel. */ void zebra_vxlan_advertise_all_vni(ZAPI_HANDLER_ARGS) - { struct stream *s = NULL; int advertise = 0; @@ -6693,7 +6684,7 @@ void zebra_vxlan_advertise_all_vni(ZAPI_HANDLER_ARGS) return; } - s = client->ibuf; + s = msg; STREAM_GETC(s, advertise); if (IS_ZEBRA_DEBUG_VXLAN) diff --git a/zebra/zebra_vxlan.h b/zebra/zebra_vxlan.h index 62c6519d50..6f25ad1e24 100644 --- a/zebra/zebra_vxlan.h +++ b/zebra/zebra_vxlan.h @@ -52,7 +52,7 @@ static inline int is_evpn_enabled() #define VNI_STR_LEN 32 -/* zserv handlers */ +/* ZAPI message handlers */ extern void zebra_vxlan_remote_macip_add(ZAPI_HANDLER_ARGS); extern void zebra_vxlan_remote_macip_del(ZAPI_HANDLER_ARGS); extern void zebra_vxlan_remote_vtep_add(ZAPI_HANDLER_ARGS); @@ -61,7 +61,6 @@ extern void zebra_vxlan_advertise_subnet(ZAPI_HANDLER_ARGS); extern void zebra_vxlan_advertise_gw_macip(ZAPI_HANDLER_ARGS); extern void zebra_vxlan_advertise_all_vni(ZAPI_HANDLER_ARGS); - extern int is_l3vni_for_prefix_routes_only(vni_t vni); extern ifindex_t get_l3vni_svi_ifindex(vrf_id_t vrf_id); extern int zebra_vxlan_vrf_delete(struct zebra_vrf *zvrf); diff --git a/zebra/zebra_vxlan_null.c b/zebra/zebra_vxlan_null.c index e6a3dd674e..1bac2cafb6 100644 --- a/zebra/zebra_vxlan_null.c +++ b/zebra/zebra_vxlan_null.c @@ -117,14 +117,14 @@ int zebra_vxlan_svi_down(struct interface *ifp, struct interface *link_if) return 0; } -void zebra_vxlan_remote_macip_add(struct zserv *client, int sock, - u_short length, struct zebra_vrf *zvrf) +int zebra_vxlan_remote_macip_add(struct zserv *client, int sock, u_short length, + struct zebra_vrf *zvrf) { return 0; } -void zebra_vxlan_remote_macip_del(struct zserv *client, int sock, - u_short length, struct zebra_vrf *zvrf) +int zebra_vxlan_remote_macip_del(struct zserv *client, int sock, u_short length, + struct zebra_vrf *zvrf) { return 0; } @@ -182,20 +182,20 @@ int zebra_vxlan_if_del(struct interface *ifp) return 0; } -void zebra_vxlan_remote_vtep_add(struct zserv *client, int sock, u_short length, - struct zebra_vrf *zvrf) +int zebra_vxlan_remote_vtep_add(struct zserv *client, int sock, u_short length, + struct zebra_vrf *zvrf) { return 0; } -void zebra_vxlan_remote_vtep_del(struct zserv *client, int sock, u_short length, - struct zebra_vrf *zvrf) +int zebra_vxlan_remote_vtep_del(struct zserv *client, int sock, u_short length, + struct zebra_vrf *zvrf) { return 0; } -void zebra_vxlan_advertise_all_vni(struct zserv *client, int sock, - u_short length, struct zebra_vrf *zvrf) +int zebra_vxlan_advertise_all_vni(struct zserv *client, int sock, + u_short length, struct zebra_vrf *zvrf) { return 0; } diff --git a/zebra/zserv.c b/zebra/zserv.c index 127913a63a..ac2fe9c0e2 100644 --- a/zebra/zserv.c +++ b/zebra/zserv.c @@ -63,94 +63,23 @@ #include "zebra/zebra_pbr.h" /* Event list of zebra. */ -enum event { ZEBRA_SERV, ZEBRA_READ, ZEBRA_WRITE }; - -static void zebra_event(enum event event, int sock, struct zserv *client); - +enum event { ZEBRA_READ, ZEBRA_WRITE }; +/* privileges */ extern struct zebra_privs_t zserv_privs; +/* post event into client */ +static void zebra_event(struct zserv *client, enum event event); -static void zebra_client_close(struct zserv *client); -static int zserv_delayed_close(struct thread *thread) +/* Public interface ======================================================== */ + +int zebra_server_send_message(struct zserv *client, struct stream *msg) { - struct zserv *client = THREAD_ARG(thread); - - client->t_suicide = NULL; - zebra_client_close(client); + stream_fifo_push(client->obuf_fifo, msg); + zebra_event(client, ZEBRA_WRITE); return 0; } -static int zserv_flush_data(struct thread *thread) -{ - struct zserv *client = THREAD_ARG(thread); - - client->t_write = NULL; - if (client->t_suicide) { - zebra_client_close(client); - return -1; - } - switch (buffer_flush_available(client->wb, client->sock)) { - case BUFFER_ERROR: - zlog_warn( - "%s: buffer_flush_available failed on zserv client fd %d, " - "closing", - __func__, client->sock); - zebra_client_close(client); - client = NULL; - break; - case BUFFER_PENDING: - client->t_write = NULL; - thread_add_write(zebrad.master, zserv_flush_data, client, - client->sock, &client->t_write); - break; - case BUFFER_EMPTY: - break; - } - - if (client) - client->last_write_time = monotime(NULL); - return 0; -} - -int zebra_server_send_message(struct zserv *client) -{ - if (client->t_suicide) - return -1; - - if (client->is_synchronous) - return 0; - - stream_set_getp(client->obuf, 0); - client->last_write_cmd = stream_getw_from(client->obuf, 6); - switch (buffer_write(client->wb, client->sock, - STREAM_DATA(client->obuf), - stream_get_endp(client->obuf))) { - case BUFFER_ERROR: - zlog_warn( - "%s: buffer_write failed to zserv client fd %d, closing", - __func__, client->sock); - /* Schedule a delayed close since many of the functions that - call this - one do not check the return code. They do not allow for the - possibility that an I/O error may have caused the client to - be - deleted. */ - client->t_suicide = NULL; - thread_add_event(zebrad.master, zserv_delayed_close, client, 0, - &client->t_suicide); - return -1; - case BUFFER_EMPTY: - THREAD_OFF(client->t_write); - break; - case BUFFER_PENDING: - thread_add_write(zebrad.master, zserv_flush_data, client, - client->sock, &client->t_write); - break; - } - - client->last_write_time = monotime(NULL); - return 0; -} +/* Encoding helpers -------------------------------------------------------- */ static void zserv_encode_interface(struct stream *s, struct interface *ifp) { @@ -202,6 +131,34 @@ static void zserv_encode_vrf(struct stream *s, struct zebra_vrf *zvrf) stream_putw_at(s, 0, stream_get_endp(s)); } +static int zserv_encode_nexthop(struct stream *s, struct nexthop *nexthop) +{ + stream_putc(s, nexthop->type); + switch (nexthop->type) { + case NEXTHOP_TYPE_IPV4: + case NEXTHOP_TYPE_IPV4_IFINDEX: + stream_put_in_addr(s, &nexthop->gate.ipv4); + stream_putl(s, nexthop->ifindex); + break; + case NEXTHOP_TYPE_IPV6: + stream_put(s, &nexthop->gate.ipv6, 16); + break; + case NEXTHOP_TYPE_IPV6_IFINDEX: + stream_put(s, &nexthop->gate.ipv6, 16); + stream_putl(s, nexthop->ifindex); + break; + case NEXTHOP_TYPE_IFINDEX: + stream_putl(s, nexthop->ifindex); + break; + default: + /* do nothing */ + break; + } + return 1; +} + +/* Send handlers ----------------------------------------------------------- */ + /* Interface is added. Send ZEBRA_INTERFACE_ADD to client. */ /* * This function is called in the following situations: @@ -215,65 +172,54 @@ static void zserv_encode_vrf(struct stream *s, struct zebra_vrf *zvrf) */ int zsend_interface_add(struct zserv *client, struct interface *ifp) { - struct stream *s; - - s = client->obuf; - stream_reset(s); + struct stream *s = stream_new(ZEBRA_MAX_PACKET_SIZ); zclient_create_header(s, ZEBRA_INTERFACE_ADD, ifp->vrf_id); zserv_encode_interface(s, ifp); client->ifadd_cnt++; - return zebra_server_send_message(client); + return zebra_server_send_message(client, s); } /* Interface deletion from zebra daemon. */ int zsend_interface_delete(struct zserv *client, struct interface *ifp) { - struct stream *s; - - s = client->obuf; - stream_reset(s); + struct stream *s = stream_new(ZEBRA_MAX_PACKET_SIZ); zclient_create_header(s, ZEBRA_INTERFACE_DELETE, ifp->vrf_id); zserv_encode_interface(s, ifp); client->ifdel_cnt++; - return zebra_server_send_message(client); + return zebra_server_send_message(client, s); } int zsend_vrf_add(struct zserv *client, struct zebra_vrf *zvrf) { - struct stream *s; - - s = client->obuf; - stream_reset(s); + struct stream *s = stream_new(ZEBRA_MAX_PACKET_SIZ); zclient_create_header(s, ZEBRA_VRF_ADD, zvrf_id(zvrf)); zserv_encode_vrf(s, zvrf); client->vrfadd_cnt++; - return zebra_server_send_message(client); + return zebra_server_send_message(client, s); } /* VRF deletion from zebra daemon. */ int zsend_vrf_delete(struct zserv *client, struct zebra_vrf *zvrf) -{ - struct stream *s; - s = client->obuf; - stream_reset(s); +{ + struct stream *s = stream_new(ZEBRA_MAX_PACKET_SIZ); zclient_create_header(s, ZEBRA_VRF_DELETE, zvrf_id(zvrf)); zserv_encode_vrf(s, zvrf); client->vrfdel_cnt++; - return zebra_server_send_message(client); + return zebra_server_send_message(client, s); } int zsend_interface_link_params(struct zserv *client, struct interface *ifp) { - struct stream *s; + struct stream *s = stream_new(ZEBRA_MAX_PACKET_SIZ); /* Check this client need interface information. */ if (!client->ifinfo) @@ -281,8 +227,6 @@ int zsend_interface_link_params(struct zserv *client, struct interface *ifp) if (!ifp->link_params) return 0; - s = client->obuf; - stream_reset(s); zclient_create_header(s, ZEBRA_INTERFACE_LINK_PARAMS, ifp->vrf_id); @@ -296,7 +240,7 @@ int zsend_interface_link_params(struct zserv *client, struct interface *ifp) /* Write packet size. */ stream_putw_at(s, 0, stream_get_endp(s)); - return zebra_server_send_message(client); + return zebra_server_send_message(client, s); } /* Interface address is added/deleted. Send ZEBRA_INTERFACE_ADDRESS_ADD or @@ -341,11 +285,8 @@ int zsend_interface_address(int cmd, struct zserv *client, struct interface *ifp, struct connected *ifc) { int blen; - struct stream *s; struct prefix *p; - - s = client->obuf; - stream_reset(s); + struct stream *s = stream_new(ZEBRA_MAX_PACKET_SIZ); zclient_create_header(s, cmd, ifp->vrf_id); stream_putl(s, ifp->ifindex); @@ -378,7 +319,7 @@ int zsend_interface_address(int cmd, struct zserv *client, stream_putw_at(s, 0, stream_get_endp(s)); client->connected_rt_add_cnt++; - return zebra_server_send_message(client); + return zebra_server_send_message(client, s); } static int zsend_interface_nbr_address(int cmd, struct zserv *client, @@ -386,12 +327,9 @@ static int zsend_interface_nbr_address(int cmd, struct zserv *client, struct nbr_connected *ifc) { int blen; - struct stream *s; + struct stream *s = stream_new(ZEBRA_MAX_PACKET_SIZ); struct prefix *p; - s = client->obuf; - stream_reset(s); - zclient_create_header(s, cmd, ifp->vrf_id); stream_putl(s, ifp->ifindex); @@ -412,7 +350,7 @@ static int zsend_interface_nbr_address(int cmd, struct zserv *client, /* Write packet size. */ stream_putw_at(s, 0, stream_get_endp(s)); - return zebra_server_send_message(client); + return zebra_server_send_message(client, s); } /* Interface address addition. */ @@ -498,10 +436,7 @@ int zsend_interface_addresses(struct zserv *client, struct interface *ifp) int zsend_interface_vrf_update(struct zserv *client, struct interface *ifp, vrf_id_t vrf_id) { - struct stream *s; - - s = client->obuf; - stream_reset(s); + struct stream *s = stream_new(ZEBRA_MAX_PACKET_SIZ); zclient_create_header(s, ZEBRA_INTERFACE_VRF_UPDATE, ifp->vrf_id); @@ -513,7 +448,7 @@ int zsend_interface_vrf_update(struct zserv *client, struct interface *ifp, stream_putw_at(s, 0, stream_get_endp(s)); client->if_vrfchg_cnt++; - return zebra_server_send_message(client); + return zebra_server_send_message(client, s); } /* Add new nbr connected IPv6 address */ @@ -575,10 +510,7 @@ void nbr_connected_delete_ipv6(struct interface *ifp, struct in6_addr *address) */ int zsend_interface_update(int cmd, struct zserv *client, struct interface *ifp) { - struct stream *s; - - s = client->obuf; - stream_reset(s); + struct stream *s = stream_new(ZEBRA_MAX_PACKET_SIZ); zclient_create_header(s, cmd, ifp->vrf_id); zserv_encode_interface(s, ifp); @@ -588,7 +520,7 @@ int zsend_interface_update(int cmd, struct zserv *client, struct interface *ifp) else client->ifdown_cnt++; - return zebra_server_send_message(client); + return zebra_server_send_message(client, s); } int zsend_redistribute_route(int cmd, struct zserv *client, struct prefix *p, @@ -660,301 +592,19 @@ int zsend_redistribute_route(int cmd, struct zserv *client, struct prefix *p, SET_FLAG(api.message, ZAPI_MESSAGE_MTU); api.mtu = re->mtu; + struct stream *s = stream_new(ZEBRA_MAX_PACKET_SIZ); + /* Encode route and send. */ - if (zapi_route_encode(cmd, client->obuf, &api) < 0) + if (zapi_route_encode(cmd, s, &api) < 0) return -1; - return zebra_server_send_message(client); -} - -static int zsend_write_nexthop(struct stream *s, struct nexthop *nexthop) -{ - stream_putc(s, nexthop->type); - switch (nexthop->type) { - case NEXTHOP_TYPE_IPV4: - case NEXTHOP_TYPE_IPV4_IFINDEX: - stream_put_in_addr(s, &nexthop->gate.ipv4); - stream_putl(s, nexthop->ifindex); - break; - case NEXTHOP_TYPE_IPV6: - stream_put(s, &nexthop->gate.ipv6, 16); - break; - case NEXTHOP_TYPE_IPV6_IFINDEX: - stream_put(s, &nexthop->gate.ipv6, 16); - stream_putl(s, nexthop->ifindex); - break; - case NEXTHOP_TYPE_IFINDEX: - stream_putl(s, nexthop->ifindex); - break; - default: - /* do nothing */ - break; - } - return 1; -} - -int cmd2type[] = { - [ZEBRA_NEXTHOP_REGISTER] = RNH_NEXTHOP_TYPE, - [ZEBRA_NEXTHOP_UNREGISTER] = RNH_NEXTHOP_TYPE, - [ZEBRA_IMPORT_ROUTE_REGISTER] = RNH_IMPORT_CHECK_TYPE, - [ZEBRA_IMPORT_ROUTE_UNREGISTER] = RNH_IMPORT_CHECK_TYPE, -}; - -/* Nexthop register */ -static void zserv_rnh_register(ZAPI_HANDLER_ARGS) -{ - struct rnh *rnh; - struct stream *s; - struct prefix p; - u_short l = 0; - u_char flags = 0; - uint16_t type = cmd2type[hdr->command]; - - if (IS_ZEBRA_DEBUG_NHT) - zlog_debug( - "rnh_register msg from client %s: length=%d, type=%s\n", - zebra_route_string(client->proto), hdr->length, - (type == RNH_NEXTHOP_TYPE) ? "nexthop" : "route"); - - s = client->ibuf; - - client->nh_reg_time = monotime(NULL); - - while (l < hdr->length) { - STREAM_GETC(s, flags); - STREAM_GETW(s, p.family); - STREAM_GETC(s, p.prefixlen); - l += 4; - if (p.family == AF_INET) { - if (p.prefixlen > IPV4_MAX_BITLEN) { - zlog_warn( - "%s: Specified prefix length %d is too large for a v4 address", - __PRETTY_FUNCTION__, p.prefixlen); - return; - } - STREAM_GET(&p.u.prefix4.s_addr, s, IPV4_MAX_BYTELEN); - l += IPV4_MAX_BYTELEN; - } else if (p.family == AF_INET6) { - if (p.prefixlen > IPV6_MAX_BITLEN) { - zlog_warn( - "%s: Specified prefix length %d is to large for a v6 address", - __PRETTY_FUNCTION__, p.prefixlen); - return; - } - STREAM_GET(&p.u.prefix6, s, IPV6_MAX_BYTELEN); - l += IPV6_MAX_BYTELEN; - } else { - zlog_err( - "rnh_register: Received unknown family type %d\n", - p.family); - return; - } - rnh = zebra_add_rnh(&p, zvrf_id(zvrf), type); - if (type == RNH_NEXTHOP_TYPE) { - if (flags - && !CHECK_FLAG(rnh->flags, ZEBRA_NHT_CONNECTED)) - SET_FLAG(rnh->flags, ZEBRA_NHT_CONNECTED); - else if (!flags - && CHECK_FLAG(rnh->flags, ZEBRA_NHT_CONNECTED)) - UNSET_FLAG(rnh->flags, ZEBRA_NHT_CONNECTED); - } else if (type == RNH_IMPORT_CHECK_TYPE) { - if (flags - && !CHECK_FLAG(rnh->flags, ZEBRA_NHT_EXACT_MATCH)) - SET_FLAG(rnh->flags, ZEBRA_NHT_EXACT_MATCH); - else if (!flags && CHECK_FLAG(rnh->flags, - ZEBRA_NHT_EXACT_MATCH)) - UNSET_FLAG(rnh->flags, ZEBRA_NHT_EXACT_MATCH); - } - - zebra_add_rnh_client(rnh, client, type, zvrf_id(zvrf)); - /* Anything not AF_INET/INET6 has been filtered out above */ - zebra_evaluate_rnh(zvrf_id(zvrf), p.family, 1, type, &p); - } - -stream_failure: - return; -} - -/* Nexthop register */ -static void zserv_rnh_unregister(ZAPI_HANDLER_ARGS) -{ - struct rnh *rnh; - struct stream *s; - struct prefix p; - u_short l = 0; - uint16_t type = cmd2type[hdr->command]; - - if (IS_ZEBRA_DEBUG_NHT) - zlog_debug("rnh_unregister msg from client %s: length=%d\n", - zebra_route_string(client->proto), hdr->length); - - s = client->ibuf; - - while (l < hdr->length) { - uint8_t flags; - - STREAM_GETC(s, flags); - if (flags != 0) - goto stream_failure; - - STREAM_GETW(s, p.family); - STREAM_GETC(s, p.prefixlen); - l += 4; - if (p.family == AF_INET) { - if (p.prefixlen > IPV4_MAX_BITLEN) { - zlog_warn( - "%s: Specified prefix length %d is to large for a v4 address", - __PRETTY_FUNCTION__, p.prefixlen); - return; - } - STREAM_GET(&p.u.prefix4.s_addr, s, IPV4_MAX_BYTELEN); - l += IPV4_MAX_BYTELEN; - } else if (p.family == AF_INET6) { - if (p.prefixlen > IPV6_MAX_BITLEN) { - zlog_warn( - "%s: Specified prefix length %d is to large for a v6 address", - __PRETTY_FUNCTION__, p.prefixlen); - return; - } - STREAM_GET(&p.u.prefix6, s, IPV6_MAX_BYTELEN); - l += IPV6_MAX_BYTELEN; - } else { - zlog_err( - "rnh_register: Received unknown family type %d\n", - p.family); - return; - } - rnh = zebra_lookup_rnh(&p, zvrf_id(zvrf), type); - if (rnh) { - client->nh_dereg_time = monotime(NULL); - zebra_remove_rnh_client(rnh, client, type); - } - } -stream_failure: - return; -} - -#define ZEBRA_MIN_FEC_LENGTH 5 - -/* FEC register */ -static void zserv_fec_register(ZAPI_HANDLER_ARGS) -{ - struct stream *s; - u_short l = 0; - struct prefix p; - u_int16_t flags; - u_int32_t label_index = MPLS_INVALID_LABEL_INDEX; - - s = client->ibuf; - zvrf = vrf_info_lookup(VRF_DEFAULT); - if (!zvrf) - return; - - /* - * The minimum amount of data that can be sent for one fec - * registration - */ - if (hdr->length < ZEBRA_MIN_FEC_LENGTH) { - zlog_err( - "fec_register: Received a fec register of length %d, it is of insufficient size to properly decode", - hdr->length); - return; - } - - while (l < hdr->length) { - STREAM_GETW(s, flags); - memset(&p, 0, sizeof(p)); - STREAM_GETW(s, p.family); - if (p.family != AF_INET && p.family != AF_INET6) { - zlog_err( - "fec_register: Received unknown family type %d\n", - p.family); - return; - } - STREAM_GETC(s, p.prefixlen); - if ((p.family == AF_INET && p.prefixlen > IPV4_MAX_BITLEN) - || (p.family == AF_INET6 - && p.prefixlen > IPV6_MAX_BITLEN)) { - zlog_warn( - "%s: Specified prefix length: %d is to long for %d", - __PRETTY_FUNCTION__, p.prefixlen, p.family); - return; - } - l += 5; - STREAM_GET(&p.u.prefix, s, PSIZE(p.prefixlen)); - l += PSIZE(p.prefixlen); - if (flags & ZEBRA_FEC_REGISTER_LABEL_INDEX) { - STREAM_GETL(s, label_index); - l += 4; - } else - label_index = MPLS_INVALID_LABEL_INDEX; - zebra_mpls_fec_register(zvrf, &p, label_index, client); - } - -stream_failure: - return; -} - -/* FEC unregister */ -static void zserv_fec_unregister(ZAPI_HANDLER_ARGS) -{ - struct stream *s; - u_short l = 0; - struct prefix p; - uint16_t flags; - - s = client->ibuf; - zvrf = vrf_info_lookup(VRF_DEFAULT); - if (!zvrf) - return; - - /* - * The minimum amount of data that can be sent for one - * fec unregistration - */ - if (hdr->length < ZEBRA_MIN_FEC_LENGTH) { - zlog_err( - "fec_unregister: Received a fec unregister of length %d, it is of insufficient size to properly decode", - hdr->length); - return; - } - - while (l < hdr->length) { - STREAM_GETW(s, flags); - if (flags != 0) - goto stream_failure; - - memset(&p, 0, sizeof(p)); - STREAM_GETW(s, p.family); - if (p.family != AF_INET && p.family != AF_INET6) { - zlog_err( - "fec_unregister: Received unknown family type %d\n", - p.family); - return; - } - STREAM_GETC(s, p.prefixlen); - if ((p.family == AF_INET && p.prefixlen > IPV4_MAX_BITLEN) - || (p.family == AF_INET6 - && p.prefixlen > IPV6_MAX_BITLEN)) { - zlog_warn( - "%s: Received prefix length %d which is greater than %d can support", - __PRETTY_FUNCTION__, p.prefixlen, p.family); - return; - } - l += 5; - STREAM_GET(&p.u.prefix, s, PSIZE(p.prefixlen)); - l += PSIZE(p.prefixlen); - zebra_mpls_fec_unregister(zvrf, &p, client); - } - -stream_failure: - return; + return zebra_server_send_message(client, s); } /* - Modified version of zsend_ipv4_nexthop_lookup(): - Query unicast rib if nexthop is not found on mrib. - Returns both route metric and protocol distance. -*/ + * Modified version of zsend_ipv4_nexthop_lookup(): Query unicast rib if + * nexthop is not found on mrib. Returns both route metric and protocol + * distance. + */ static int zsend_ipv4_nexthop_lookup_mrib(struct zserv *client, struct in_addr addr, struct route_entry *re, @@ -966,7 +616,7 @@ static int zsend_ipv4_nexthop_lookup_mrib(struct zserv *client, struct nexthop *nexthop; /* Get output stream. */ - s = client->obuf; + s = stream_new(ZEBRA_MAX_PACKET_SIZ); stream_reset(s); /* Fill in result. */ @@ -997,7 +647,7 @@ static int zsend_ipv4_nexthop_lookup_mrib(struct zserv *client, stream_putw_at(s, 0, stream_get_endp(s)); - return zebra_server_send_message(client); + return zebra_server_send_message(client, s); } int zsend_route_notify_owner(struct route_entry *re, struct prefix *p, @@ -1028,7 +678,7 @@ int zsend_route_notify_owner(struct route_entry *re, struct prefix *p, re->table, note); } - s = client->obuf; + s = stream_new(ZEBRA_MAX_PACKET_SIZ); stream_reset(s); zclient_create_header(s, ZEBRA_ROUTE_NOTIFY_OWNER, re->vrf_id); @@ -1045,7 +695,7 @@ int zsend_route_notify_owner(struct route_entry *re, struct prefix *p, stream_putw_at(s, 0, stream_get_endp(s)); - return zebra_server_send_message(client); + return zebra_server_send_message(client, s); } void zsend_rule_notify_owner(struct zebra_pbr_rule *rule, @@ -1068,7 +718,7 @@ void zsend_rule_notify_owner(struct zebra_pbr_rule *rule, if (!client) return; - s = client->obuf; + s = stream_new(ZEBRA_MAX_PACKET_SIZ); stream_reset(s); zclient_create_header(s, ZEBRA_RULE_NOTIFY_OWNER, VRF_DEFAULT); @@ -1083,22 +733,20 @@ void zsend_rule_notify_owner(struct zebra_pbr_rule *rule, stream_putw_at(s, 0, stream_get_endp(s)); - zebra_server_send_message(client); + zebra_server_send_message(client, s); } /* Router-id is updated. Send ZEBRA_ROUTER_ID_ADD to client. */ int zsend_router_id_update(struct zserv *client, struct prefix *p, vrf_id_t vrf_id) { - struct stream *s; int blen; /* Check this client need interface information. */ if (!vrf_bitmap_check(client->ridinfo, vrf_id)) return 0; - s = client->obuf; - stream_reset(s); + struct stream *s = stream_new(ZEBRA_MAX_PACKET_SIZ); /* Message type. */ zclient_create_header(s, ZEBRA_ROUTER_ID_UPDATE, vrf_id); @@ -1112,7 +760,7 @@ int zsend_router_id_update(struct zserv *client, struct prefix *p, /* Write packet size. */ stream_putw_at(s, 0, stream_get_endp(s)); - return zebra_server_send_message(client); + return zebra_server_send_message(client, s); } /* @@ -1120,10 +768,7 @@ int zsend_router_id_update(struct zserv *client, struct prefix *p, */ int zsend_pw_update(struct zserv *client, struct zebra_pw *pw) { - struct stream *s; - - s = client->obuf; - stream_reset(s); + struct stream *s = stream_new(ZEBRA_MAX_PACKET_SIZ); zclient_create_header(s, ZEBRA_PW_STATUS_UPDATE, pw->vrf_id); stream_write(s, pw->ifname, IF_NAMESIZE); @@ -1133,13 +778,325 @@ int zsend_pw_update(struct zserv *client, struct zebra_pw *pw) /* Put length at the first point of the stream. */ stream_putw_at(s, 0, stream_get_endp(s)); - return zebra_server_send_message(client); + return zebra_server_send_message(client, s); } -/* Register zebra server interface information. Send current all - interface and address information. */ -static void zread_interface_add(ZAPI_HANDLER_ARGS) +/* Send response to a get label chunk request to client */ +static int zsend_assign_label_chunk_response(struct zserv *client, + vrf_id_t vrf_id, + struct label_manager_chunk *lmc) +{ + int ret; + struct stream *s = stream_new(ZEBRA_MAX_PACKET_SIZ); + zclient_create_header(s, ZEBRA_GET_LABEL_CHUNK, vrf_id); + + if (lmc) { + /* keep */ + stream_putc(s, lmc->keep); + /* start and end labels */ + stream_putl(s, lmc->start); + stream_putl(s, lmc->end); + } + + /* Write packet size. */ + stream_putw_at(s, 0, stream_get_endp(s)); + + ret = writen(client->sock, s->data, stream_get_endp(s)); + stream_free(s); + return ret; +} + +/* Send response to a label manager connect request to client */ +static int zsend_label_manager_connect_response(struct zserv *client, + vrf_id_t vrf_id, u_short result) +{ + int ret; + struct stream *s = stream_new(ZEBRA_MAX_PACKET_SIZ); + + zclient_create_header(s, ZEBRA_LABEL_MANAGER_CONNECT, vrf_id); + + /* result */ + stream_putc(s, result); + + /* Write packet size. */ + stream_putw_at(s, 0, stream_get_endp(s)); + + ret = writen(client->sock, s->data, stream_get_endp(s)); + stream_free(s); + + return ret; +} + +/* Inbound message handling ------------------------------------------------ */ + +int cmd2type[] = { + [ZEBRA_NEXTHOP_REGISTER] = RNH_NEXTHOP_TYPE, + [ZEBRA_NEXTHOP_UNREGISTER] = RNH_NEXTHOP_TYPE, + [ZEBRA_IMPORT_ROUTE_REGISTER] = RNH_IMPORT_CHECK_TYPE, + [ZEBRA_IMPORT_ROUTE_UNREGISTER] = RNH_IMPORT_CHECK_TYPE, +}; + +/* Nexthop register */ +static void zread_rnh_register(ZAPI_HANDLER_ARGS) +{ + struct rnh *rnh; + struct stream *s; + struct prefix p; + u_short l = 0; + u_char flags = 0; + uint16_t type = cmd2type[hdr->command]; + + if (IS_ZEBRA_DEBUG_NHT) + zlog_debug( + "rnh_register msg from client %s: hdr->length=%d, type=%s\n", + zebra_route_string(client->proto), hdr->length, + (type == RNH_NEXTHOP_TYPE) ? "nexthop" : "route"); + + s = msg; + + client->nh_reg_time = monotime(NULL); + + while (l < hdr->length) { + STREAM_GETC(s, flags); + STREAM_GETW(s, p.family); + STREAM_GETC(s, p.prefixlen); + l += 4; + if (p.family == AF_INET) { + if (p.prefixlen > IPV4_MAX_BITLEN) { + zlog_warn( + "%s: Specified prefix hdr->length %d is too large for a v4 address", + __PRETTY_FUNCTION__, p.prefixlen); + return; + } + STREAM_GET(&p.u.prefix4.s_addr, s, IPV4_MAX_BYTELEN); + l += IPV4_MAX_BYTELEN; + } else if (p.family == AF_INET6) { + if (p.prefixlen > IPV6_MAX_BITLEN) { + zlog_warn( + "%s: Specified prefix hdr->length %d is to large for a v6 address", + __PRETTY_FUNCTION__, p.prefixlen); + return; + } + STREAM_GET(&p.u.prefix6, s, IPV6_MAX_BYTELEN); + l += IPV6_MAX_BYTELEN; + } else { + zlog_err( + "rnh_register: Received unknown family type %d\n", + p.family); + return; + } + rnh = zebra_add_rnh(&p, zvrf_id(zvrf), type); + if (type == RNH_NEXTHOP_TYPE) { + if (flags + && !CHECK_FLAG(rnh->flags, ZEBRA_NHT_CONNECTED)) + SET_FLAG(rnh->flags, ZEBRA_NHT_CONNECTED); + else if (!flags + && CHECK_FLAG(rnh->flags, ZEBRA_NHT_CONNECTED)) + UNSET_FLAG(rnh->flags, ZEBRA_NHT_CONNECTED); + } else if (type == RNH_IMPORT_CHECK_TYPE) { + if (flags + && !CHECK_FLAG(rnh->flags, ZEBRA_NHT_EXACT_MATCH)) + SET_FLAG(rnh->flags, ZEBRA_NHT_EXACT_MATCH); + else if (!flags + && CHECK_FLAG(rnh->flags, + ZEBRA_NHT_EXACT_MATCH)) + UNSET_FLAG(rnh->flags, ZEBRA_NHT_EXACT_MATCH); + } + + zebra_add_rnh_client(rnh, client, type, zvrf_id(zvrf)); + /* Anything not AF_INET/INET6 has been filtered out above */ + zebra_evaluate_rnh(zvrf_id(zvrf), p.family, 1, type, &p); + } + +stream_failure: + return; +} + +/* Nexthop register */ +static void zread_rnh_unregister(ZAPI_HANDLER_ARGS) +{ + struct rnh *rnh; + struct stream *s; + struct prefix p; + u_short l = 0; + uint16_t type = cmd2type[hdr->command]; + + if (IS_ZEBRA_DEBUG_NHT) + zlog_debug( + "rnh_unregister msg from client %s: hdr->length=%d\n", + zebra_route_string(client->proto), hdr->length); + + s = msg; + + while (l < hdr->length) { + uint8_t flags; + + STREAM_GETC(s, flags); + if (flags != 0) + goto stream_failure; + + STREAM_GETW(s, p.family); + STREAM_GETC(s, p.prefixlen); + l += 4; + if (p.family == AF_INET) { + if (p.prefixlen > IPV4_MAX_BITLEN) { + zlog_warn( + "%s: Specified prefix hdr->length %d is to large for a v4 address", + __PRETTY_FUNCTION__, p.prefixlen); + return; + } + STREAM_GET(&p.u.prefix4.s_addr, s, IPV4_MAX_BYTELEN); + l += IPV4_MAX_BYTELEN; + } else if (p.family == AF_INET6) { + if (p.prefixlen > IPV6_MAX_BITLEN) { + zlog_warn( + "%s: Specified prefix hdr->length %d is to large for a v6 address", + __PRETTY_FUNCTION__, p.prefixlen); + return; + } + STREAM_GET(&p.u.prefix6, s, IPV6_MAX_BYTELEN); + l += IPV6_MAX_BYTELEN; + } else { + zlog_err( + "rnh_register: Received unknown family type %d\n", + p.family); + return; + } + rnh = zebra_lookup_rnh(&p, zvrf_id(zvrf), type); + if (rnh) { + client->nh_dereg_time = monotime(NULL); + zebra_remove_rnh_client(rnh, client, type); + } + } +stream_failure: + return; +} + +#define ZEBRA_MIN_FEC_LENGTH 5 + +/* FEC register */ +static void zread_fec_register(ZAPI_HANDLER_ARGS) +{ + struct stream *s; + u_short l = 0; + struct prefix p; + uint16_t flags; + uint32_t label_index = MPLS_INVALID_LABEL_INDEX; + + s = msg; + zvrf = vrf_info_lookup(VRF_DEFAULT); + if (!zvrf) + return; // unexpected + + /* + * The minimum amount of data that can be sent for one fec + * registration + */ + if (hdr->length < ZEBRA_MIN_FEC_LENGTH) { + zlog_err( + "fec_register: Received a fec register of hdr->length %d, it is of insufficient size to properly decode", + hdr->length); + return; + } + + while (l < hdr->length) { + STREAM_GETW(s, flags); + memset(&p, 0, sizeof(p)); + STREAM_GETW(s, p.family); + if (p.family != AF_INET && p.family != AF_INET6) { + zlog_err( + "fec_register: Received unknown family type %d\n", + p.family); + return; + } + STREAM_GETC(s, p.prefixlen); + if ((p.family == AF_INET && p.prefixlen > IPV4_MAX_BITLEN) + || (p.family == AF_INET6 + && p.prefixlen > IPV6_MAX_BITLEN)) { + zlog_warn( + "%s: Specified prefix hdr->length: %d is to long for %d", + __PRETTY_FUNCTION__, p.prefixlen, p.family); + return; + } + l += 5; + STREAM_GET(&p.u.prefix, s, PSIZE(p.prefixlen)); + l += PSIZE(p.prefixlen); + if (flags & ZEBRA_FEC_REGISTER_LABEL_INDEX) { + STREAM_GETL(s, label_index); + l += 4; + } else + label_index = MPLS_INVALID_LABEL_INDEX; + zebra_mpls_fec_register(zvrf, &p, label_index, client); + } + +stream_failure: + return; +} + +/* FEC unregister */ +static void zread_fec_unregister(ZAPI_HANDLER_ARGS) +{ + struct stream *s; + u_short l = 0; + struct prefix p; + uint16_t flags; + + s = msg; + zvrf = vrf_info_lookup(VRF_DEFAULT); + if (!zvrf) + return; // unexpected + + /* + * The minimum amount of data that can be sent for one + * fec unregistration + */ + if (hdr->length < ZEBRA_MIN_FEC_LENGTH) { + zlog_err( + "fec_unregister: Received a fec unregister of hdr->length %d, it is of insufficient size to properly decode", + hdr->length); + return; + } + + while (l < hdr->length) { + STREAM_GETW(s, flags); + if (flags != 0) + goto stream_failure; + + memset(&p, 0, sizeof(p)); + STREAM_GETW(s, p.family); + if (p.family != AF_INET && p.family != AF_INET6) { + zlog_err( + "fec_unregister: Received unknown family type %d\n", + p.family); + return; + } + STREAM_GETC(s, p.prefixlen); + if ((p.family == AF_INET && p.prefixlen > IPV4_MAX_BITLEN) + || (p.family == AF_INET6 + && p.prefixlen > IPV6_MAX_BITLEN)) { + zlog_warn( + "%s: Received prefix hdr->length %d which is greater than %d can support", + __PRETTY_FUNCTION__, p.prefixlen, p.family); + return; + } + l += 5; + STREAM_GET(&p.u.prefix, s, PSIZE(p.prefixlen)); + l += PSIZE(p.prefixlen); + zebra_mpls_fec_unregister(zvrf, &p, client); + } + +stream_failure: + return; +} + + + +/* + * Register zebra server interface information. + * Send current all interface and address information. + */ +static void zread_interface_add(ZAPI_HANDLER_ARGS) { struct vrf *vrf; struct interface *ifp; @@ -1153,14 +1110,10 @@ static void zread_interface_add(ZAPI_HANDLER_ARGS) if (!CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE)) continue; - if (zsend_interface_add(client, ifp) < 0) - return; - - if (zsend_interface_addresses(client, ifp) < 0) - return; + zsend_interface_add(client, ifp); + zsend_interface_addresses(client, ifp); } } - return; } /* Unregister zebra server interface information. */ @@ -1193,9 +1146,8 @@ static void zread_route_add(ZAPI_HANDLER_ARGS) int i, ret; vrf_id_t vrf_id = 0; - s = client->ibuf; - if (zapi_route_decode(s, &api) < 0) - return; + s = msg; + zapi_route_decode(s, &api); /* Allocate new route. */ vrf_id = zvrf_id(zvrf); @@ -1342,7 +1294,7 @@ static void zread_route_del(ZAPI_HANDLER_ARGS) afi_t afi; struct prefix_ipv6 *src_p = NULL; - s = client->ibuf; + s = msg; if (zapi_route_decode(s, &api) < 0) return; @@ -1368,8 +1320,6 @@ static void zread_route_del(ZAPI_HANDLER_ARGS) client->v6_route_del_cnt++; break; } - - return; } /* This function support multiple nexthop. */ @@ -1396,7 +1346,7 @@ static void zread_ipv4_add(ZAPI_HANDLER_ARGS) enum blackhole_type bh_type = BLACKHOLE_NULL; /* Get input stream. */ - s = client->ibuf; + s = msg; /* Allocate new re. */ re = XCALLOC(MTYPE_RE, sizeof(struct route_entry)); @@ -1527,7 +1477,6 @@ static void zread_ipv4_add(ZAPI_HANDLER_ARGS) stream_failure: nexthops_free(re->ng.nexthop); XFREE(MTYPE_RE, re); - return; } /* Zebra server IPv4 prefix delete function. */ @@ -1538,7 +1487,7 @@ static void zread_ipv4_delete(ZAPI_HANDLER_ARGS) struct prefix p; u_int32_t table_id; - s = client->ibuf; + s = msg; /* Type, flags, message. */ STREAM_GETC(s, api.type); @@ -1574,10 +1523,9 @@ static void zread_ipv4_nexthop_lookup_mrib(ZAPI_HANDLER_ARGS) struct in_addr addr; struct route_entry *re; - STREAM_GET(&addr.s_addr, client->ibuf, IPV4_MAX_BYTELEN); + STREAM_GET(&addr.s_addr, msg, IPV4_MAX_BYTELEN); re = rib_match_ipv4_multicast(zvrf_id(zvrf), addr, NULL); zsend_ipv4_nexthop_lookup_mrib(client, addr, re, zvrf); - return; stream_failure: return; @@ -1605,7 +1553,7 @@ static void zread_ipv4_route_ipv6_nexthop_add(ZAPI_HANDLER_ARGS) enum blackhole_type bh_type = BLACKHOLE_NULL; /* Get input stream. */ - s = client->ibuf; + s = msg; memset(&nhop_addr, 0, sizeof(struct in6_addr)); @@ -1618,7 +1566,6 @@ static void zread_ipv4_route_ipv6_nexthop_add(ZAPI_HANDLER_ARGS) zlog_warn("%s: Specified route type: %d is not a legal value\n", __PRETTY_FUNCTION__, re->type); XFREE(MTYPE_RE, re); - return; } STREAM_GETW(s, re->instance); @@ -1754,7 +1701,6 @@ static void zread_ipv4_route_ipv6_nexthop_add(ZAPI_HANDLER_ARGS) stream_failure: nexthops_free(re->ng.nexthop); XFREE(MTYPE_RE, re); - return; } static void zread_ipv6_add(ZAPI_HANDLER_ARGS) @@ -1780,7 +1726,7 @@ static void zread_ipv6_add(ZAPI_HANDLER_ARGS) enum blackhole_type bh_type = BLACKHOLE_NULL; /* Get input stream. */ - s = client->ibuf; + s = msg; memset(&nhop_addr, 0, sizeof(struct in6_addr)); @@ -1947,8 +1893,6 @@ static void zread_ipv6_add(ZAPI_HANDLER_ARGS) stream_failure: nexthops_free(re->ng.nexthop); XFREE(MTYPE_RE, re); - - return; } /* Zebra server IPv6 prefix delete function. */ @@ -1959,7 +1903,7 @@ static void zread_ipv6_delete(ZAPI_HANDLER_ARGS) struct prefix p; struct prefix_ipv6 src_p, *src_pp; - s = client->ibuf; + s = msg; /* Type, flags, message. */ STREAM_GETC(s, api.type); @@ -2020,9 +1964,9 @@ static void zread_hello(ZAPI_HANDLER_ARGS) u_short instance; u_char notify; - STREAM_GETC(client->ibuf, proto); - STREAM_GETW(client->ibuf, instance); - STREAM_GETC(client->ibuf, notify); + STREAM_GETC(msg, proto); + STREAM_GETW(msg, instance); + STREAM_GETC(msg, notify); if (notify) client->notify_owner = true; @@ -2068,7 +2012,7 @@ static void zread_mpls_labels(ZAPI_HANDLER_ARGS) u_int8_t distance; /* Get input stream. */ - s = client->ibuf; + s = msg; /* Get data. */ STREAM_GETC(s, type); @@ -2139,27 +2083,9 @@ static void zread_mpls_labels(ZAPI_HANDLER_ARGS) stream_failure: return; } -/* Send response to a label manager connect request to client */ -static int zsend_label_manager_connect_response(struct zserv *client, - vrf_id_t vrf_id, u_short result) -{ - struct stream *s; - s = client->obuf; - stream_reset(s); - - zclient_create_header(s, ZEBRA_LABEL_MANAGER_CONNECT, vrf_id); - - /* result */ - stream_putc(s, result); - - /* Write packet size. */ - stream_putw_at(s, 0, stream_get_endp(s)); - - return writen(client->sock, s->data, stream_get_endp(s)); -} - -static void zread_label_manager_connect(struct zserv *client, vrf_id_t vrf_id) +static void zread_label_manager_connect(struct zserv *client, + struct stream *msg, vrf_id_t vrf_id) { struct stream *s; /* type of protocol (lib/zebra.h) */ @@ -2167,7 +2093,7 @@ static void zread_label_manager_connect(struct zserv *client, vrf_id_t vrf_id) u_short instance; /* Get input stream. */ - s = client->ibuf; + s = msg; /* Get data. */ STREAM_GETC(s, proto); @@ -2200,33 +2126,9 @@ static void zread_label_manager_connect(struct zserv *client, vrf_id_t vrf_id) stream_failure: return; } -/* Send response to a get label chunk request to client */ -static int zsend_assign_label_chunk_response(struct zserv *client, - vrf_id_t vrf_id, - struct label_manager_chunk *lmc) -{ - struct stream *s; - s = client->obuf; - stream_reset(s); - - zclient_create_header(s, ZEBRA_GET_LABEL_CHUNK, vrf_id); - - if (lmc) { - /* keep */ - stream_putc(s, lmc->keep); - /* start and end labels */ - stream_putl(s, lmc->start); - stream_putl(s, lmc->end); - } - - /* Write packet size. */ - stream_putw_at(s, 0, stream_get_endp(s)); - - return writen(client->sock, s->data, stream_get_endp(s)); -} - -static void zread_get_label_chunk(struct zserv *client, vrf_id_t vrf_id) +static void zread_get_label_chunk(struct zserv *client, struct stream *msg, + vrf_id_t vrf_id) { struct stream *s; u_char keep; @@ -2234,7 +2136,7 @@ static void zread_get_label_chunk(struct zserv *client, vrf_id_t vrf_id) struct label_manager_chunk *lmc; /* Get input stream. */ - s = client->ibuf; + s = msg; /* Get data. */ STREAM_GETC(s, keep); @@ -2254,13 +2156,13 @@ stream_failure: return; } -static void zread_release_label_chunk(struct zserv *client) +static void zread_release_label_chunk(struct zserv *client, struct stream *msg) { struct stream *s; uint32_t start, end; /* Get input stream. */ - s = client->ibuf; + s = msg; /* Get data. */ STREAM_GETL(s, start); @@ -2284,7 +2186,7 @@ static void zread_label_manager_request(ZAPI_HANDLER_ARGS) /* this is a label manager */ else { if (hdr->command == ZEBRA_LABEL_MANAGER_CONNECT) - zread_label_manager_connect(client, zvrf_id(zvrf)); + zread_label_manager_connect(client, msg, zvrf_id(zvrf)); else { /* Sanity: don't allow 'unidentified' requests */ if (!client->proto) { @@ -2293,9 +2195,10 @@ static void zread_label_manager_request(ZAPI_HANDLER_ARGS) return; } if (hdr->command == ZEBRA_GET_LABEL_CHUNK) - zread_get_label_chunk(client, zvrf_id(zvrf)); + zread_get_label_chunk(client, msg, + zvrf_id(zvrf)); else if (hdr->command == ZEBRA_RELEASE_LABEL_CHUNK) - zread_release_label_chunk(client); + zread_release_label_chunk(client, msg); } } } @@ -2316,7 +2219,7 @@ static void zread_pseudowire(ZAPI_HANDLER_ARGS) struct zebra_pw *pw; /* Get input stream. */ - s = client->ibuf; + s = msg; /* Get data. */ STREAM_GET(ifname, s, IF_NAMESIZE); @@ -2413,116 +2316,11 @@ static void zebra_client_close_cleanup_rnh(struct zserv *client) } } -/* free zebra client information. */ -static void zebra_client_free(struct zserv *client) -{ - /* Send client de-registration to BFD */ - zebra_ptm_bfd_client_deregister(client->proto); - - /* Cleanup any registered nexthops - across all VRFs. */ - zebra_client_close_cleanup_rnh(client); - - /* Release Label Manager chunks */ - release_daemon_chunks(client->proto, client->instance); - - /* Cleanup any FECs registered by this client. */ - zebra_mpls_cleanup_fecs_for_client(vrf_info_lookup(VRF_DEFAULT), - client); - - /* Remove pseudowires associated with this client */ - zebra_pw_client_close(client); - - /* Close file descriptor. */ - if (client->sock) { - unsigned long nroutes; - - close(client->sock); - nroutes = rib_score_proto(client->proto, client->instance); - zlog_notice( - "client %d disconnected. %lu %s routes removed from the rib", - client->sock, nroutes, - zebra_route_string(client->proto)); - client->sock = -1; - } - - /* Free stream buffers. */ - if (client->ibuf) - stream_free(client->ibuf); - if (client->obuf) - stream_free(client->obuf); - if (client->wb) - buffer_free(client->wb); - - /* Release threads. */ - if (client->t_read) - thread_cancel(client->t_read); - if (client->t_write) - thread_cancel(client->t_write); - if (client->t_suicide) - thread_cancel(client->t_suicide); - - /* Free bitmaps. */ - for (afi_t afi = AFI_IP; afi < AFI_MAX; afi++) - for (int i = 0; i < ZEBRA_ROUTE_MAX; i++) - vrf_bitmap_free(client->redist[afi][i]); - - vrf_bitmap_free(client->redist_default); - vrf_bitmap_free(client->ifinfo); - vrf_bitmap_free(client->ridinfo); - - XFREE(MTYPE_TMP, client); -} - -static void zebra_client_close(struct zserv *client) -{ - listnode_delete(zebrad.client_list, client); - zebra_client_free(client); -} - -/* Make new client. */ -static void zebra_client_create(int sock) -{ - struct zserv *client; - int i; - afi_t afi; - - client = XCALLOC(MTYPE_TMP, sizeof(struct zserv)); - - /* Make client input/output buffer. */ - client->sock = sock; - client->ibuf = stream_new(ZEBRA_MAX_PACKET_SIZ); - client->obuf = stream_new(ZEBRA_MAX_PACKET_SIZ); - client->wb = buffer_new(0); - - /* Set table number. */ - client->rtm_table = zebrad.rtm_table_default; - - client->connect_time = monotime(NULL); - /* Initialize flags */ - for (afi = AFI_IP; afi < AFI_MAX; afi++) - for (i = 0; i < ZEBRA_ROUTE_MAX; i++) - client->redist[afi][i] = vrf_bitmap_init(); - client->redist_default = vrf_bitmap_init(); - client->ifinfo = vrf_bitmap_init(); - client->ridinfo = vrf_bitmap_init(); - - /* by default, it's not a synchronous client */ - client->is_synchronous = 0; - - /* Add this client to linked list. */ - listnode_add(zebrad.client_list, client); - - /* Make new read thread. */ - zebra_event(ZEBRA_READ, sock, client); - - zebra_vrf_update_all(client); -} - static void zread_interface_set_master(ZAPI_HANDLER_ARGS) { struct interface *master; struct interface *slave; - struct stream *s = client->ibuf; + struct stream *s = msg; int ifindex; vrf_id_t vrf_id; @@ -2553,7 +2351,7 @@ static void zread_vrf_label(ZAPI_HANDLER_ARGS) struct zebra_vrf *def_zvrf; enum lsp_types_t ltype; - s = client->ibuf; + s = msg; STREAM_GETL(s, nlabel); STREAM_GETC(s, afi); if (nlabel == zvrf->label[afi]) { @@ -2619,7 +2417,7 @@ static inline void zread_rule(ZAPI_HANDLER_ARGS) uint32_t total, i; ifindex_t ifindex; - s = client->ibuf; + s = msg; STREAM_GETL(s, total); for (i = 0; i < total; i++) { @@ -2670,23 +2468,6 @@ stream_failure: return; } -/* - * Reads header from zmsg stream. - * - * Note this advances the stream getp by the size of the header. - */ -static bool zserv_read_header(struct stream *msg, struct zmsghdr *hdr) -{ - STREAM_GETW(msg, hdr->length); - STREAM_GETC(msg, hdr->marker); - STREAM_GETC(msg, hdr->version); - STREAM_GETL(msg, hdr->vrf_id); - STREAM_GETW(msg, hdr->command); - return true; -stream_failure: - return false; -} - void (*zserv_handlers[])(ZAPI_HANDLER_ARGS) = { [ZEBRA_ROUTER_ID_ADD] = zread_router_id_add, [ZEBRA_ROUTER_ID_DELETE] = zread_router_id_delete, @@ -2705,10 +2486,10 @@ void (*zserv_handlers[])(ZAPI_HANDLER_ARGS) = { [ZEBRA_REDISTRIBUTE_DEFAULT_DELETE] = zebra_redistribute_default_delete, [ZEBRA_IPV4_NEXTHOP_LOOKUP_MRIB] = zread_ipv4_nexthop_lookup_mrib, [ZEBRA_HELLO] = zread_hello, - [ZEBRA_NEXTHOP_REGISTER] = zserv_rnh_register, - [ZEBRA_NEXTHOP_UNREGISTER] = zserv_rnh_unregister, - [ZEBRA_IMPORT_ROUTE_REGISTER] = zserv_rnh_register, - [ZEBRA_IMPORT_ROUTE_UNREGISTER] = zserv_rnh_unregister, + [ZEBRA_NEXTHOP_REGISTER] = zread_rnh_register, + [ZEBRA_NEXTHOP_UNREGISTER] = zread_rnh_unregister, + [ZEBRA_IMPORT_ROUTE_REGISTER] = zread_rnh_register, + [ZEBRA_IMPORT_ROUTE_UNREGISTER] = zread_rnh_unregister, [ZEBRA_BFD_DEST_UPDATE] = zebra_ptm_bfd_dst_register, [ZEBRA_BFD_DEST_REGISTER] = zebra_ptm_bfd_dst_register, [ZEBRA_BFD_DEST_DEREGISTER] = zebra_ptm_bfd_dst_deregister, @@ -2728,8 +2509,8 @@ void (*zserv_handlers[])(ZAPI_HANDLER_ARGS) = { [ZEBRA_LABEL_MANAGER_CONNECT] = zread_label_manager_request, [ZEBRA_GET_LABEL_CHUNK] = zread_label_manager_request, [ZEBRA_RELEASE_LABEL_CHUNK] = zread_label_manager_request, - [ZEBRA_FEC_REGISTER] = zserv_fec_register, - [ZEBRA_FEC_UNREGISTER] = zserv_fec_unregister, + [ZEBRA_FEC_REGISTER] = zread_fec_register, + [ZEBRA_FEC_UNREGISTER] = zread_fec_unregister, [ZEBRA_ADVERTISE_DEFAULT_GW] = zebra_vxlan_advertise_gw_macip, [ZEBRA_ADVERTISE_SUBNET] = zebra_vxlan_advertise_subnet, [ZEBRA_ADVERTISE_ALL_VNI] = zebra_vxlan_advertise_all_vni, @@ -2746,19 +2527,255 @@ void (*zserv_handlers[])(ZAPI_HANDLER_ARGS) = { [ZEBRA_RULE_DELETE] = zread_rule, }; -static inline void zserv_handle_commands(struct zserv *client, uint16_t command, - uint16_t length, +static inline void zserv_handle_commands(struct zserv *client, + struct zmsghdr *hdr, + struct stream *msg, struct zebra_vrf *zvrf) { - struct zmsghdr hdr; - - stream_set_getp(client->ibuf, 0); - zserv_read_header(client->ibuf, &hdr); - if (hdr.command > sizeof(zserv_handlers) - || zserv_handlers[hdr.command] == NULL) - zlog_info("Zebra received unknown command %d", hdr.command); + if (hdr->command > sizeof(zserv_handlers) + || zserv_handlers[hdr->command] == NULL) + zlog_info("Zebra received unknown command %d", hdr->command); else - zserv_handlers[hdr.command](client, &hdr, zvrf); + zserv_handlers[hdr->command](client, hdr, msg, zvrf); + + stream_free(msg); +} + +/* Lifecycle ---------------------------------------------------------------- */ + +/* free zebra client information. */ +static void zebra_client_free(struct zserv *client) +{ + /* Send client de-registration to BFD */ + zebra_ptm_bfd_client_deregister(client->proto); + + /* Cleanup any registered nexthops - across all VRFs. */ + zebra_client_close_cleanup_rnh(client); + + /* Release Label Manager chunks */ + release_daemon_chunks(client->proto, client->instance); + + /* Cleanup any FECs registered by this client. */ + zebra_mpls_cleanup_fecs_for_client(vrf_info_lookup(VRF_DEFAULT), + client); + + /* Remove pseudowires associated with this client */ + zebra_pw_client_close(client); + + /* Close file descriptor. */ + if (client->sock) { + unsigned long nroutes; + + close(client->sock); + nroutes = rib_score_proto(client->proto, client->instance); + zlog_notice( + "client %d disconnected. %lu %s routes removed from the rib", + client->sock, nroutes, + zebra_route_string(client->proto)); + client->sock = -1; + } + + /* Free stream buffers. */ + if (client->ibuf_work) + stream_free(client->ibuf_work); + if (client->obuf_work) + stream_free(client->obuf_work); + if (client->ibuf_fifo) + stream_fifo_free(client->ibuf_fifo); + if (client->obuf_fifo) + stream_fifo_free(client->obuf_fifo); + if (client->wb) + buffer_free(client->wb); + + /* Release threads. */ + if (client->t_read) + thread_cancel(client->t_read); + if (client->t_write) + thread_cancel(client->t_write); + if (client->t_suicide) + thread_cancel(client->t_suicide); + + /* Free bitmaps. */ + for (afi_t afi = AFI_IP; afi < AFI_MAX; afi++) + for (int i = 0; i < ZEBRA_ROUTE_MAX; i++) + vrf_bitmap_free(client->redist[afi][i]); + + vrf_bitmap_free(client->redist_default); + vrf_bitmap_free(client->ifinfo); + vrf_bitmap_free(client->ridinfo); + + XFREE(MTYPE_TMP, client); +} + +/* + * Called from client thread to terminate itself. + */ +static void zebra_client_close(struct zserv *client) +{ + listnode_delete(zebrad.client_list, client); + zebra_client_free(client); +} + +/* Make new client. */ +static void zebra_client_create(int sock) +{ + struct zserv *client; + int i; + afi_t afi; + + client = XCALLOC(MTYPE_TMP, sizeof(struct zserv)); + + /* Make client input/output buffer. */ + client->sock = sock; + client->ibuf_fifo = stream_fifo_new(); + client->obuf_fifo = stream_fifo_new(); + client->ibuf_work = stream_new(ZEBRA_MAX_PACKET_SIZ); + client->obuf_work = stream_new(ZEBRA_MAX_PACKET_SIZ); + client->wb = buffer_new(0); + + /* Set table number. */ + client->rtm_table = zebrad.rtm_table_default; + + client->connect_time = monotime(NULL); + /* Initialize flags */ + for (afi = AFI_IP; afi < AFI_MAX; afi++) + for (i = 0; i < ZEBRA_ROUTE_MAX; i++) + client->redist[afi][i] = vrf_bitmap_init(); + client->redist_default = vrf_bitmap_init(); + client->ifinfo = vrf_bitmap_init(); + client->ridinfo = vrf_bitmap_init(); + + /* by default, it's not a synchronous client */ + client->is_synchronous = 0; + + /* Add this client to linked list. */ + listnode_add(zebrad.client_list, client); + + zebra_vrf_update_all(client); + + /* start read loop */ + zebra_event(client, ZEBRA_READ); +} + +static int zserv_delayed_close(struct thread *thread) +{ + struct zserv *client = THREAD_ARG(thread); + + client->t_suicide = NULL; + zebra_client_close(client); + return 0; +} + +/* + * Log zapi message to zlog. + * + * errmsg (optional) + * Debugging message + * + * msg + * The message + * + * hdr (optional) + * The message header + */ +static void zserv_log_message(const char *errmsg, struct stream *msg, + struct zmsghdr *hdr) +{ + zlog_debug("Rx'd ZAPI message"); + if (errmsg) + zlog_debug("%s", errmsg); + if (hdr) { + zlog_debug(" Length: %d", hdr->length); + zlog_debug("Command: %s", zserv_command_string(hdr->command)); + zlog_debug(" VRF: %u", hdr->vrf_id); + } + zlog_hexdump(msg->data, STREAM_READABLE(msg)); +} + +static int zserv_flush_data(struct thread *thread) +{ + struct zserv *client = THREAD_ARG(thread); + + client->t_write = NULL; + if (client->t_suicide) { + zebra_client_close(client); + return -1; + } + switch (buffer_flush_available(client->wb, client->sock)) { + case BUFFER_ERROR: + zlog_warn( + "%s: buffer_flush_available failed on zserv client fd %d, closing", + __func__, client->sock); + zebra_client_close(client); + client = NULL; + break; + case BUFFER_PENDING: + client->t_write = NULL; + thread_add_write(zebrad.master, zserv_flush_data, client, + client->sock, &client->t_write); + break; + case BUFFER_EMPTY: + break; + } + + if (client) + client->last_write_time = monotime(NULL); + return 0; +} + +/* + * Write a single packet. + */ +static int zserv_write(struct thread *thread) +{ + struct zserv *client = THREAD_ARG(thread); + struct stream *msg; + int writerv; + + if (client->t_suicide) + return -1; + + if (client->is_synchronous) + return 0; + + msg = stream_fifo_pop(client->obuf_fifo); + stream_set_getp(msg, 0); + client->last_write_cmd = stream_getw_from(msg, 6); + + writerv = buffer_write(client->wb, client->sock, STREAM_DATA(msg), + stream_get_endp(msg)); + + stream_free(msg); + + switch (writerv) { + case BUFFER_ERROR: + zlog_warn( + "%s: buffer_write failed to zserv client fd %d, closing", + __func__, client->sock); + /* + * Schedule a delayed close since many of the functions that + * call this one do not check the return code. They do not + * allow for the possibility that an I/O error may have caused + * the client to be deleted. + */ + client->t_suicide = NULL; + thread_add_event(zebrad.master, zserv_delayed_close, client, 0, + &client->t_suicide); + return -1; + case BUFFER_EMPTY: + THREAD_OFF(client->t_write); + break; + case BUFFER_PENDING: + thread_add_write(zebrad.master, zserv_flush_data, client, + client->sock, &client->t_write); + break; + } + + if (client->obuf_fifo->count) + zebra_event(client, ZEBRA_WRITE); + + client->last_write_time = monotime(NULL); + return 0; } #if defined(HANDLE_ZAPI_FUZZING) @@ -2781,26 +2798,66 @@ static void zserv_write_incoming(struct stream *orig, uint16_t command) } #endif +static int zserv_process_messages(struct thread *thread) +{ + struct zserv *client = THREAD_ARG(thread); + struct zebra_vrf *zvrf; + struct zmsghdr hdr; + struct stream *msg; + bool hdrvalid; + + do { + msg = stream_fifo_pop(client->ibuf_fifo); + + /* break if out of messages */ + if (!msg) + continue; + + /* read & check header */ + hdrvalid = zapi_parse_header(msg, &hdr); + if (!hdrvalid && IS_ZEBRA_DEBUG_PACKET && IS_ZEBRA_DEBUG_RECV) { + const char *emsg = "Message has corrupt header"; + zserv_log_message(emsg, msg, NULL); + } + if (!hdrvalid) + continue; + + /* lookup vrf */ + zvrf = zebra_vrf_lookup_by_id(hdr.vrf_id); + if (!zvrf && IS_ZEBRA_DEBUG_PACKET && IS_ZEBRA_DEBUG_RECV) { + const char *emsg = "Message specifies unknown VRF"; + zserv_log_message(emsg, msg, &hdr); + } + if (!zvrf) + continue; + + /* process commands */ + zserv_handle_commands(client, &hdr, msg, zvrf); + + } while (msg); + + return 0; +} + /* Handler of zebra service request. */ -static int zebra_client_read(struct thread *thread) +static int zserv_read(struct thread *thread) { int sock; struct zserv *client; size_t already; - uint16_t length, command; - uint8_t marker, version; - vrf_id_t vrf_id; - struct zebra_vrf *zvrf; #if defined(HANDLE_ZAPI_FUZZING) int packets = 1; #else int packets = zebrad.packets_to_process; #endif + struct zmsghdr hdr; + ssize_t nb; + bool hdrvalid; + char errmsg[256]; /* Get thread data. Reset reading thread because I'm running. */ sock = THREAD_FD(thread); client = THREAD_ARG(thread); - client->t_read = NULL; if (client->t_suicide) { zebra_client_close(client); @@ -2808,88 +2865,84 @@ static int zebra_client_read(struct thread *thread) } while (packets) { + already = stream_get_endp(client->ibuf_work); + /* Read length and command (if we don't have it already). */ - if ((already = stream_get_endp(client->ibuf)) - < ZEBRA_HEADER_SIZE) { - ssize_t nbyte; - if (((nbyte = stream_read_try(client->ibuf, sock, - ZEBRA_HEADER_SIZE - - already)) - == 0) - || (nbyte == -1)) { - if (IS_ZEBRA_DEBUG_EVENT) - zlog_debug( - "connection closed socket [%d]", - sock); - zebra_client_close(client); - return -1; - } - if (nbyte != (ssize_t)(ZEBRA_HEADER_SIZE - already)) { + if (already < ZEBRA_HEADER_SIZE) { + nb = stream_read_try(client->ibuf_work, sock, + ZEBRA_HEADER_SIZE - already); + if ((nb == 0 || nb == -1) && IS_ZEBRA_DEBUG_EVENT) + zlog_debug("connection closed socket [%d]", + sock); + if ((nb == 0 || nb == -1)) + goto zread_fail; + if (nb != (ssize_t)(ZEBRA_HEADER_SIZE - already)) { /* Try again later. */ - zebra_event(ZEBRA_READ, sock, client); - return 0; + break; } already = ZEBRA_HEADER_SIZE; } /* Reset to read from the beginning of the incoming packet. */ - stream_set_getp(client->ibuf, 0); + stream_set_getp(client->ibuf_work, 0); /* Fetch header values */ - STREAM_GETW(client->ibuf, length); - STREAM_GETC(client->ibuf, marker); - STREAM_GETC(client->ibuf, version); - STREAM_GETL(client->ibuf, vrf_id); - STREAM_GETW(client->ibuf, command); + hdrvalid = zapi_parse_header(client->ibuf_work, &hdr); - if (marker != ZEBRA_HEADER_MARKER || version != ZSERV_VERSION) { - zlog_err( - "%s: socket %d version mismatch, marker %d, version %d", - __func__, sock, marker, version); - zebra_client_close(client); - return -1; + if (!hdrvalid) { + snprintf(errmsg, sizeof(errmsg), + "%s: Message has corrupt header", __func__); + zserv_log_message(errmsg, client->ibuf_work, NULL); + goto zread_fail; } - if (length < ZEBRA_HEADER_SIZE) { - zlog_warn( - "%s: socket %d message length %u is less than header size %d", - __func__, sock, length, ZEBRA_HEADER_SIZE); - zebra_client_close(client); - return -1; + + /* Validate header */ + if (hdr.marker != ZEBRA_HEADER_MARKER + || hdr.version != ZSERV_VERSION) { + snprintf( + errmsg, sizeof(errmsg), + "Message has corrupt header\n%s: socket %d version mismatch, marker %d, version %d", + __func__, sock, hdr.marker, hdr.version); + zserv_log_message(errmsg, client->ibuf_work, &hdr); + goto zread_fail; } - if (length > STREAM_SIZE(client->ibuf)) { - zlog_warn( - "%s: socket %d message length %u exceeds buffer size %lu", - __func__, sock, length, - (u_long)STREAM_SIZE(client->ibuf)); - zebra_client_close(client); - return -1; + if (hdr.length < ZEBRA_HEADER_SIZE) { + snprintf( + errmsg, sizeof(errmsg), + "Message has corrupt header\n%s: socket %d message length %u is less than header size %d", + __func__, sock, hdr.length, ZEBRA_HEADER_SIZE); + zserv_log_message(errmsg, client->ibuf_work, &hdr); + goto zread_fail; + } + if (hdr.length > STREAM_SIZE(client->ibuf_work)) { + snprintf( + errmsg, sizeof(errmsg), + "Message has corrupt header\n%s: socket %d message length %u exceeds buffer size %lu", + __func__, sock, hdr.length, + (unsigned long)STREAM_SIZE(client->ibuf_work)); + goto zread_fail; } /* Read rest of data. */ - if (already < length) { - ssize_t nbyte; - if (((nbyte = stream_read_try(client->ibuf, sock, - length - already)) - == 0) - || (nbyte == -1)) { - if (IS_ZEBRA_DEBUG_EVENT) - zlog_debug( - "connection closed [%d] when reading zebra data", - sock); - zebra_client_close(client); - return -1; - } - if (nbyte != (ssize_t)(length - already)) { + if (already < hdr.length) { + nb = stream_read_try(client->ibuf_work, sock, + hdr.length - already); + if ((nb == 0 || nb == -1) && IS_ZEBRA_DEBUG_EVENT) + zlog_debug( + "connection closed [%d] when reading zebra data", + sock); + if ((nb == 0 || nb == -1)) + goto zread_fail; + if (nb != (ssize_t)(hdr.length - already)) { /* Try again later. */ - zebra_event(ZEBRA_READ, sock, client); - return 0; + break; } } #if defined(HANDLE_ZAPI_FUZZING) - zserv_write_incoming(client->ibuf, command); + zserv_write_incoming(client->ibuf_work, command); #endif - length -= ZEBRA_HEADER_SIZE; + hdr.length -= ZEBRA_HEADER_SIZE; /* Debug packet information. */ if (IS_ZEBRA_DEBUG_EVENT) @@ -2897,41 +2950,54 @@ static int zebra_client_read(struct thread *thread) sock); if (IS_ZEBRA_DEBUG_PACKET && IS_ZEBRA_DEBUG_RECV) - zlog_debug("zebra message received [%s] %d in VRF %u", - zserv_command_string(command), length, - vrf_id); + zserv_log_message(NULL, client->ibuf_work, &hdr); client->last_read_time = monotime(NULL); - client->last_read_cmd = command; + client->last_read_cmd = hdr.command; - zvrf = zebra_vrf_lookup_by_id(vrf_id); - if (!zvrf) { - if (IS_ZEBRA_DEBUG_PACKET && IS_ZEBRA_DEBUG_RECV) - zlog_debug("zebra received unknown VRF[%u]", - vrf_id); - goto zclient_read_out; - } + stream_set_getp(client->ibuf_work, 0); + struct stream *msg = stream_dup(client->ibuf_work); - zserv_handle_commands(client, command, length, zvrf); + stream_fifo_push(client->ibuf_fifo, msg); - if (client->t_suicide) { - /* No need to wait for thread callback, just kill - * immediately. - */ - zebra_client_close(client); - return -1; - } - packets -= 1; - stream_reset(client->ibuf); + if (client->t_suicide) + goto zread_fail; + + --packets; + stream_reset(client->ibuf_work); } -stream_failure: -zclient_read_out: - stream_reset(client->ibuf); - zebra_event(ZEBRA_READ, sock, client); + if (IS_ZEBRA_DEBUG_PACKET) + zlog_debug("Read %d packets", + zebrad.packets_to_process - packets); + + /* Schedule job to process those packets */ + thread_add_event(zebrad.master, &zserv_process_messages, client, 0, + NULL); + + /* Reschedule ourselves */ + zebra_event(client, ZEBRA_READ); + return 0; + +zread_fail: + zebra_client_close(client); + return -1; } +static void zebra_event(struct zserv *client, enum event event) +{ + switch (event) { + case ZEBRA_READ: + thread_add_read(zebrad.master, zserv_read, client, client->sock, + &client->t_read); + break; + case ZEBRA_WRITE: + thread_add_write(zebrad.master, zserv_write, client, + client->sock, &client->t_write); + break; + } +} /* Accept code of zebra server socket. */ static int zebra_accept(struct thread *thread) @@ -2944,7 +3010,7 @@ static int zebra_accept(struct thread *thread) accept_sock = THREAD_FD(thread); /* Reregister myself. */ - zebra_event(ZEBRA_SERV, accept_sock, NULL); + thread_add_read(zebrad.master, zebra_accept, NULL, accept_sock, NULL); len = sizeof(struct sockaddr_in); client_sock = accept(accept_sock, (struct sockaddr *)&client, &len); @@ -3031,26 +3097,7 @@ void zebra_zserv_socket_init(char *path) umask(old_mask); - zebra_event(ZEBRA_SERV, sock, NULL); -} - - -static void zebra_event(enum event event, int sock, struct zserv *client) -{ - switch (event) { - case ZEBRA_SERV: - thread_add_read(zebrad.master, zebra_accept, client, sock, - NULL); - break; - case ZEBRA_READ: - client->t_read = NULL; - thread_add_read(zebrad.master, zebra_client_read, client, sock, - &client->t_read); - break; - case ZEBRA_WRITE: - /**/ - break; - } + thread_add_read(zebrad.master, zebra_accept, NULL, sock, NULL); } #define ZEBRA_TIME_BUF 32 diff --git a/zebra/zserv.h b/zebra/zserv.h index 74ff31bcf9..a055a28c01 100644 --- a/zebra/zserv.h +++ b/zebra/zserv.h @@ -47,8 +47,12 @@ struct zserv { int sock; /* Input/output buffer to the client. */ - struct stream *ibuf; - struct stream *obuf; + struct stream_fifo *ibuf_fifo; + struct stream_fifo *obuf_fifo; + + /* Private I/O buffers */ + struct stream *ibuf_work; + struct stream *obuf_work; /* Buffer of data waiting to be written to client. */ struct buffer *wb; @@ -129,7 +133,7 @@ struct zserv { int last_write_cmd; }; -/* ZAPI protocol message header */ +/* ZAPI protocol structs */ struct zmsghdr { uint16_t length; uint8_t marker; @@ -139,7 +143,8 @@ struct zmsghdr { }; #define ZAPI_HANDLER_ARGS \ - struct zserv *client, struct zmsghdr *hdr, struct zebra_vrf *zvrf + struct zserv *client, struct zmsghdr *hdr, struct stream *msg, \ + struct zebra_vrf *zvrf /* Zebra instance */ struct zebra_t { @@ -197,7 +202,7 @@ extern void zsend_rule_notify_owner(struct zebra_pbr_rule *rule, extern void zserv_nexthop_num_warn(const char *, const struct prefix *, const unsigned int); -extern int zebra_server_send_message(struct zserv *client); +extern int zebra_server_send_message(struct zserv *client, struct stream *msg); extern struct zserv *zebra_find_client(u_char proto, u_short instance); From 124ead27dbd7e61e79a334533adc702fdf172ddb Mon Sep 17 00:00:00 2001 From: Quentin Young Date: Wed, 7 Mar 2018 11:23:58 -0500 Subject: [PATCH 20/25] lib, zebra: use existing zapi header struct Nobody uses it, but it's got the same definition. Move the parser function into zclient.c and use it. Signed-off-by: Quentin Young --- lib/zclient.c | 12 +++++++++ lib/zclient.h | 66 ++++++++++++++++++++++++++++++++++++++------- zebra/zebra_vxlan.c | 2 +- zebra/zserv.h | 9 ------- 4 files changed, 70 insertions(+), 19 deletions(-) diff --git a/lib/zclient.c b/lib/zclient.c index fa3a5f6691..20aaaca161 100644 --- a/lib/zclient.c +++ b/lib/zclient.c @@ -322,6 +322,18 @@ stream_failure: return 0; } +bool zapi_parse_header(struct stream *zmsg, struct zmsghdr *hdr) +{ + STREAM_GETW(zmsg, hdr->length); + STREAM_GETC(zmsg, hdr->marker); + STREAM_GETC(zmsg, hdr->version); + STREAM_GETC(zmsg, hdr->vrf_id); + STREAM_GETW(zmsg, hdr->command); + return true; +stream_failure: + return false; +} + /* Send simple Zebra message. */ static int zebra_message_send(struct zclient *zclient, int command, vrf_id_t vrf_id) diff --git a/lib/zclient.h b/lib/zclient.h index 1aa94b641c..c8574946d0 100644 --- a/lib/zclient.h +++ b/lib/zclient.h @@ -237,14 +237,14 @@ struct zclient { */ #define ZAPI_MESSAGE_TABLEID 0x80 -/* Zserv protocol message header */ -struct zserv_header { - uint16_t length; - uint8_t marker; /* corresponds to command field in old zserv - * always set to 255 in new zserv. - */ - uint8_t version; #define ZSERV_VERSION 5 +/* Zserv protocol message header */ +struct zmsghdr { + uint16_t length; + /* corresponds to command field in old zserv + * always set to 255 in new zserv. */ + uint8_t marker; + uint8_t version; vrf_id_t vrf_id; uint16_t command; }; @@ -449,9 +449,58 @@ extern int zclient_send_message(struct zclient *); /* create header for command, length to be filled in by user later */ extern void zclient_create_header(struct stream *, uint16_t, vrf_id_t); +/* + * Read sizeof(struct zmsghdr) bytes from the provided socket and parse the + * received data into the specified fields. If this is successful, read the + * rest of the packet into the provided stream. + * + * s + * The stream to read into + * + * sock + * The socket to read from + * + * size + * Parsed message size will be placed in the pointed-at integer + * + * marker + * Parsed marker will be placed in the pointed-at byte + * + * version + * Parsed version will be placed in the pointed-at byte + * + * vrf_id + * Parsed VRF ID will be placed in the pointed-at vrf_id_t + * + * cmd + * Parsed command number will be placed in the pointed-at integer + * + * Returns: + * -1 if: + * - insufficient data for header was read + * - a version mismatch was detected + * - a marker mismatch was detected + * - header size field specified more data than could be read + */ extern int zclient_read_header(struct stream *s, int sock, u_int16_t *size, u_char *marker, u_char *version, vrf_id_t *vrf_id, u_int16_t *cmd); +/* + * Parse header from ZAPI message stream into struct zmsghdr. + * This function assumes the stream getp points at the first byte of the header. + * If the function is successful then the stream getp will point to the byte + * immediately after the last byte of the header. + * + * zmsg + * The stream containing the header + * + * hdr + * The header struct to parse into. + * + * Returns: + * true if parsing succeeded, false otherwise + */ +extern bool zapi_parse_header(struct stream *zmsg, struct zmsghdr *hdr); extern void zclient_interface_set_master(struct zclient *client, struct interface *master, @@ -469,8 +518,7 @@ extern void zebra_interface_if_set_value(struct stream *, struct interface *); extern void zebra_router_id_update_read(struct stream *s, struct prefix *rid); #if CONFDATE > 20180823 -CPP_NOTICE( - "zapi_ipv4_route, zapi_ipv6_route, zapi_ipv4_route_ipv6_nexthop as well as the zapi_ipv4 and zapi_ipv6 data structures should be removed now"); +CPP_NOTICE("zapi_ipv4_route, zapi_ipv6_route, zapi_ipv4_route_ipv6_nexthop as well as the zapi_ipv4 and zapi_ipv6 data structures should be removed now"); #endif extern int zapi_ipv4_route(u_char, struct zclient *, struct prefix_ipv4 *, diff --git a/zebra/zebra_vxlan.c b/zebra/zebra_vxlan.c index a8d1848723..256fa9e4b7 100644 --- a/zebra/zebra_vxlan.c +++ b/zebra/zebra_vxlan.c @@ -6612,7 +6612,7 @@ void zebra_vxlan_advertise_gw_macip(ZAPI_HANDLER_ARGS) zvni = zvni_lookup(vni); if (!zvni) - return 0; + return; if (IS_ZEBRA_DEBUG_VXLAN) zlog_debug( diff --git a/zebra/zserv.h b/zebra/zserv.h index a055a28c01..62707510c2 100644 --- a/zebra/zserv.h +++ b/zebra/zserv.h @@ -133,15 +133,6 @@ struct zserv { int last_write_cmd; }; -/* ZAPI protocol structs */ -struct zmsghdr { - uint16_t length; - uint8_t marker; - uint8_t version; - uint32_t vrf_id; - uint16_t command; -}; - #define ZAPI_HANDLER_ARGS \ struct zserv *client, struct zmsghdr *hdr, struct stream *msg, \ struct zebra_vrf *zvrf From 5530922ef7408fe8275a75675094c7c453186a2b Mon Sep 17 00:00:00 2001 From: Quentin Young Date: Wed, 7 Mar 2018 12:30:51 -0500 Subject: [PATCH 21/25] lib: zclient.h style fixes Signed-off-by: Quentin Young --- lib/zclient.h | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/lib/zclient.h b/lib/zclient.h index c8574946d0..dd9c8973fa 100644 --- a/lib/zclient.h +++ b/lib/zclient.h @@ -241,8 +241,7 @@ struct zclient { /* Zserv protocol message header */ struct zmsghdr { uint16_t length; - /* corresponds to command field in old zserv - * always set to 255 in new zserv. */ + /* Always set to 255 in new zserv */ uint8_t marker; uint8_t version; vrf_id_t vrf_id; @@ -380,9 +379,11 @@ struct zclient_options { /* Prototypes of zebra client service functions. */ extern struct zclient *zclient_new(struct thread_master *); +/* clang-format off */ #if CONFDATE > 20181101 CPP_NOTICE("zclient_new_notify can take over or zclient_new now"); #endif +/* clang-format on */ extern struct zclient_options zclient_options_default; @@ -517,9 +518,11 @@ 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); +/* clang-format off */ #if CONFDATE > 20180823 CPP_NOTICE("zapi_ipv4_route, zapi_ipv6_route, zapi_ipv4_route_ipv6_nexthop as well as the zapi_ipv4 and zapi_ipv6 data structures should be removed now"); #endif +/* clang-format on */ extern int zapi_ipv4_route(u_char, struct zclient *, struct prefix_ipv4 *, struct zapi_ipv4 *) __attribute__((deprecated)); From 107afcd10b59be3441e2b1f358942ca5e760daa2 Mon Sep 17 00:00:00 2001 From: Quentin Young Date: Fri, 9 Mar 2018 15:59:39 -0500 Subject: [PATCH 22/25] lib, zebra: clean up zapi nits * Get correct data size when parsing VRF ids * Move some vars into smaller scope Signed-off-by: Quentin Young --- lib/zclient.c | 2 +- zebra/zserv.c | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/zclient.c b/lib/zclient.c index 20aaaca161..c720e2519b 100644 --- a/lib/zclient.c +++ b/lib/zclient.c @@ -327,7 +327,7 @@ bool zapi_parse_header(struct stream *zmsg, struct zmsghdr *hdr) STREAM_GETW(zmsg, hdr->length); STREAM_GETC(zmsg, hdr->marker); STREAM_GETC(zmsg, hdr->version); - STREAM_GETC(zmsg, hdr->vrf_id); + STREAM_GETL(zmsg, hdr->vrf_id); STREAM_GETW(zmsg, hdr->command); return true; stream_failure: diff --git a/zebra/zserv.c b/zebra/zserv.c index ac2fe9c0e2..4cdb97be42 100644 --- a/zebra/zserv.c +++ b/zebra/zserv.c @@ -2850,11 +2850,6 @@ static int zserv_read(struct thread *thread) #else int packets = zebrad.packets_to_process; #endif - struct zmsghdr hdr; - ssize_t nb; - bool hdrvalid; - char errmsg[256]; - /* Get thread data. Reset reading thread because I'm running. */ sock = THREAD_FD(thread); client = THREAD_ARG(thread); @@ -2865,6 +2860,11 @@ static int zserv_read(struct thread *thread) } while (packets) { + struct zmsghdr hdr; + ssize_t nb; + bool hdrvalid; + char errmsg[256]; + already = stream_get_endp(client->ibuf_work); /* Read length and command (if we don't have it already). */ From 41903a407407bcdf73dbd471dea3f53d2d056b0b Mon Sep 17 00:00:00 2001 From: Quentin Young Date: Fri, 9 Mar 2018 17:40:16 -0500 Subject: [PATCH 23/25] lib, zebra: slight cleanup after rebase Rebased zapi-cleanup, needs a bit of poking. Signed-off-by: Quentin Young --- lib/zclient.h | 2 +- zebra/zserv.c | 7 +++---- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/lib/zclient.h b/lib/zclient.h index dd9c8973fa..8033488444 100644 --- a/lib/zclient.h +++ b/lib/zclient.h @@ -237,7 +237,7 @@ struct zclient { */ #define ZAPI_MESSAGE_TABLEID 0x80 -#define ZSERV_VERSION 5 +#define ZSERV_VERSION 5 /* Zserv protocol message header */ struct zmsghdr { uint16_t length; diff --git a/zebra/zserv.c b/zebra/zserv.c index 4cdb97be42..f53baf65d0 100644 --- a/zebra/zserv.c +++ b/zebra/zserv.c @@ -636,7 +636,7 @@ static int zsend_ipv4_nexthop_lookup_mrib(struct zserv *client, * chain of nexthops. */ for (nexthop = re->ng.nexthop; nexthop; nexthop = nexthop->next) if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE)) - num += zsend_write_nexthop(s, nexthop); + num += zserv_encode_nexthop(s, nexthop); stream_putc_at(s, nump, num); /* store nexthop_num */ } else { @@ -706,8 +706,8 @@ void zsend_rule_notify_owner(struct zebra_pbr_rule *rule, struct stream *s; if (IS_ZEBRA_DEBUG_PACKET) { - zlog_debug("%s: Notifying %u", - __PRETTY_FUNCTION__, rule->unique); + zlog_debug("%s: Notifying %u", __PRETTY_FUNCTION__, + rule->unique); } for (ALL_LIST_ELEMENTS_RO(zebrad.client_list, node, client)) { @@ -1091,7 +1091,6 @@ stream_failure: } - /* * Register zebra server interface information. * Send current all interface and address information. From e049c5fcce862e994fc1b79baf8671c0aa25894e Mon Sep 17 00:00:00 2001 From: Quentin Young Date: Mon, 12 Mar 2018 14:01:47 -0400 Subject: [PATCH 24/25] lib: fixup zlog_hexdump * Allocate correct amount of memory * Use snprintf() instead of sprintf() Signed-off-by: Quentin Young --- lib/log.c | 41 +++++++++++++++++++++++++---------------- 1 file changed, 25 insertions(+), 16 deletions(-) diff --git a/lib/log.c b/lib/log.c index 9e33ef9102..2d856cc777 100644 --- a/lib/log.c +++ b/lib/log.c @@ -1092,41 +1092,50 @@ void zlog_hexdump(const void *mem, unsigned int len) unsigned long i = 0; unsigned int j = 0; unsigned int columns = 8; - char buf[(len * 4) + ((len / 4) * 20) + 30]; + /* 19 bytes for 0xADDRESS: */ + /* 24 bytes for data; 2 chars plus a space per data byte */ + /* 1 byte for space */ + /* 8 bytes for ASCII representation */ + /* 1 byte for a newline */ + /* ===================== */ + /* 53 bytes per 8 bytes of data */ + /* 1 byte for null term */ + size_t bs = ((len / 8) + 1) * 53 + 1; + char buf[bs]; char *s = buf; + memset(buf, 0, sizeof(buf)); + for (i = 0; i < len + ((len % columns) ? (columns - len % columns) : 0); i++) { /* print offset */ if (i % columns == 0) - s += sprintf(s, "0x%016lx: ", (unsigned long)mem + i); + s += snprintf(s, bs - (s - buf), + "0x%016lx: ", (unsigned long)mem + i); /* print hex data */ if (i < len) - s += sprintf(s, "%02x ", 0xFF & ((const char *)mem)[i]); + s += snprintf(s, bs - (s - buf), "%02x ", + 0xFF & ((const char *)mem)[i]); /* end of block, just aligning for ASCII dump */ else - s += sprintf(s, " "); + s += snprintf(s, bs - (s - buf), " "); /* print ASCII dump */ if (i % columns == (columns - 1)) { for (j = i - (columns - 1); j <= i; j++) { - if (j >= len) /* end of block, not really - printing */ - s += sprintf(s, " "); - - else if (isprint((int)((const char *)mem) - [j])) /* printable char - */ - s += sprintf( - s, "%c", + /* end of block not really printing */ + if (j >= len) + s += snprintf(s, bs - (s - buf), " "); + else if (isprint((int)((const char *)mem)[j])) + s += snprintf( + s, bs - (s - buf), "%c", 0xFF & ((const char *)mem)[j]); - else /* other char */ - s += sprintf(s, "."); + s += snprintf(s, bs - (s - buf), "."); } - s += sprintf(s, "\n"); + s += snprintf(s, bs - (s - buf), "\n"); } } zlog_debug("\n%s", buf); From abccc77544f973ad896d31f356ee6fc6df3e2614 Mon Sep 17 00:00:00 2001 From: Quentin Young Date: Mon, 12 Mar 2018 14:04:56 -0400 Subject: [PATCH 25/25] tests: add unit test for zlog Just tests zlog_hexdump right now Signed-off-by: Quentin Young --- lib/log.c | 18 +++++++------ tests/Makefile.am | 6 ++++- tests/lib/test_zlog.c | 61 ++++++++++++++++++++++++++++++++++++++++++ tests/lib/test_zlog.py | 4 +++ 4 files changed, 80 insertions(+), 9 deletions(-) create mode 100644 tests/lib/test_zlog.c create mode 100644 tests/lib/test_zlog.py diff --git a/lib/log.c b/lib/log.c index 2d856cc777..74e7be7c7d 100644 --- a/lib/log.c +++ b/lib/log.c @@ -1092,14 +1092,16 @@ void zlog_hexdump(const void *mem, unsigned int len) unsigned long i = 0; unsigned int j = 0; unsigned int columns = 8; - /* 19 bytes for 0xADDRESS: */ - /* 24 bytes for data; 2 chars plus a space per data byte */ - /* 1 byte for space */ - /* 8 bytes for ASCII representation */ - /* 1 byte for a newline */ - /* ===================== */ - /* 53 bytes per 8 bytes of data */ - /* 1 byte for null term */ + /* + * 19 bytes for 0xADDRESS: + * 24 bytes for data; 2 chars plus a space per data byte + * 1 byte for space + * 8 bytes for ASCII representation + * 1 byte for a newline + * ===================== + * 53 bytes per 8 bytes of data + * 1 byte for null term + */ size_t bs = ((len / 8) + 1) * 53 + 1; char buf[bs]; char *s = buf; diff --git a/tests/Makefile.am b/tests/Makefile.am index f4ab2a126a..0c9a5684da 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -73,6 +73,7 @@ check_PROGRAMS = \ lib/test_timer_correctness \ lib/test_timer_performance \ lib/test_ttable \ + lib/test_zlog \ lib/cli/test_cli \ lib/cli/test_commands \ $(TESTS_BGPD) \ @@ -115,9 +116,9 @@ lib_test_heavy_SOURCES = lib/test_heavy.c helpers/c/main.c lib_test_memory_SOURCES = lib/test_memory.c lib_test_nexthop_iter_SOURCES = lib/test_nexthop_iter.c helpers/c/prng.c lib_test_privs_SOURCES = lib/test_privs.c +lib_test_ringbuf_SOURCES = lib/test_ringbuf.c lib_test_srcdest_table_SOURCES = lib/test_srcdest_table.c \ helpers/c/prng.c -lib_test_ringbuf_SOURCES = lib/test_ringbuf.c lib_test_segv_SOURCES = lib/test_segv.c lib_test_sig_SOURCES = lib/test_sig.c lib_test_stream_SOURCES = lib/test_stream.c @@ -127,6 +128,7 @@ lib_test_timer_correctness_SOURCES = lib/test_timer_correctness.c \ lib_test_timer_performance_SOURCES = lib/test_timer_performance.c \ helpers/c/prng.c lib_test_ttable_SOURCES = lib/test_ttable.c +lib_test_zlog_SOURCES = lib/test_zlog.c lib_test_zmq_SOURCES = lib/test_zmq.c lib_test_zmq_CFLAGS = $(AM_CFLAGS) $(ZEROMQ_CFLAGS) lib_cli_test_cli_SOURCES = lib/cli/test_cli.c lib/cli/common_cli.c @@ -167,6 +169,7 @@ lib_test_table_LDADD = $(ALL_TESTS_LDADD) -lm lib_test_timer_correctness_LDADD = $(ALL_TESTS_LDADD) lib_test_timer_performance_LDADD = $(ALL_TESTS_LDADD) lib_test_ttable_LDADD = $(ALL_TESTS_LDADD) +lib_test_zlog_LDADD = $(ALL_TESTS_LDADD) lib_test_zmq_LDADD = ../lib/libfrrzmq.la $(ALL_TESTS_LDADD) $(ZEROMQ_LIBS) lib_cli_test_cli_LDADD = $(ALL_TESTS_LDADD) lib_cli_test_commands_LDADD = $(ALL_TESTS_LDADD) @@ -207,6 +210,7 @@ EXTRA_DIST = \ lib/test_timer_correctness.py \ lib/test_ttable.py \ lib/test_ttable.refout \ + lib/test_zlog.py \ ospf6d/test_lsdb.py \ ospf6d/test_lsdb.in \ ospf6d/test_lsdb.refout \ diff --git a/tests/lib/test_zlog.c b/tests/lib/test_zlog.c new file mode 100644 index 0000000000..790e65cfe9 --- /dev/null +++ b/tests/lib/test_zlog.c @@ -0,0 +1,61 @@ +/* + * Zlog tests. + * Copyright (C) 2018 Cumulus Networks, Inc. + * Quentin Young + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * 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 + */ +#include +#include +#include "log.h" + +/* maximum amount of data to hexdump */ +#define MAXDATA 16384 + +/* + * Test hexdump functionality. + * + * At the moment, not crashing is considered success. + */ +static bool test_zlog_hexdump(void) +{ + unsigned int nl = 1; + + do { + long d[nl]; + + for (unsigned int i = 0; i < nl; i++) + d[i] = random(); + zlog_hexdump(d, nl * sizeof(long)); + } while (++nl * sizeof(long) <= MAXDATA); + + return true; +} + +bool (*tests[])(void) = { + test_zlog_hexdump, +}; + +int main(int argc, char **argv) +{ + openzlog("testzlog", "NONE", 0, LOG_CONS | LOG_NDELAY | LOG_PID, + LOG_ERR); + zlog_set_file("test_zlog.log", LOG_DEBUG); + + for (unsigned int i = 0; i < array_size(tests); i++) + if (!tests[i]()) + return 1; + return 0; +} diff --git a/tests/lib/test_zlog.py b/tests/lib/test_zlog.py new file mode 100644 index 0000000000..2ca2585886 --- /dev/null +++ b/tests/lib/test_zlog.py @@ -0,0 +1,4 @@ +import frrtest + +class TestZlog(frrtest.TestMultiOut): + program = './test_zlog'