From 37fe77317cecd662eafaeab67aad02fed949b388 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Thu, 3 Nov 2016 19:59:19 -0400 Subject: [PATCH] bgpd, zebra: Allow setting ecmp from daemon cli When starting up bgp and zebra now, you can specify -e or --ecmp and that number will be used as the maximum ecmp that can be used. The = 1 and <= MULTIPATH_NUM that Quagga is compiled with. Signed-off-by: Donald Sharp --- bgpd/bgp_main.c | 10 ++++++++++ bgpd/bgp_mpath.c | 6 +++--- bgpd/bgp_vty.c | 7 +++++++ bgpd/bgp_zebra.c | 4 ++-- bgpd/bgpd.c | 6 ++++-- bgpd/bgpd.h | 1 + zebra/main.c | 11 +++++++++++ zebra/rt_netlink.c | 12 ++++++------ zebra/zebra_fpm_netlink.c | 8 ++++---- zebra/zebra_fpm_protobuf.c | 4 ++-- zebra/zebra_mpls_openbsd.c | 2 +- zebra/zserv.c | 28 ++++++++++++++-------------- zebra/zserv.h | 1 + 13 files changed, 66 insertions(+), 34 deletions(-) diff --git a/bgpd/bgp_main.c b/bgpd/bgp_main.c index 9607d381d..fbbcda591 100644 --- a/bgpd/bgp_main.c +++ b/bgpd/bgp_main.c @@ -75,6 +75,7 @@ static const struct option longopts[] = { "vty_socket", required_argument, NULL, OPTION_VTYSOCK }, { "retain", no_argument, NULL, 'r'}, { "no_kernel", no_argument, NULL, 'n'}, + { "ecmp", required_argument, NULL, 'e'}, { "user", required_argument, NULL, 'u'}, { "group", required_argument, NULL, 'g'}, { "skip_runas", no_argument, NULL, 'S'}, @@ -176,6 +177,7 @@ redistribution between different routing protocols.\n\n\ --vty_socket Override vty socket path\n\ -r, --retain When program terminates, retain added route by bgpd.\n\ -n, --no_kernel Do not install route to kernel.\n\ +-e, --ecmp Specify ECMP to use.\n\ -u, --user User to run as\n\ -g, --group Group to run as\n\ -S, --skip_runas Skip user and group run as\n\ @@ -468,6 +470,14 @@ main (int argc, char **argv) case 'A': vty_addr = optarg; break; + case 'e': + multipath_num = atoi (optarg); + if (multipath_num > MULTIPATH_NUM || multipath_num <= 0) + { + zlog_err ("Multipath Number specified must be less than %d and greater than 0", MULTIPATH_NUM); + return 1; + } + break; case 'P': /* Deal with atoi() returning 0 on failure, and bgpd not listening on bgp port... */ diff --git a/bgpd/bgp_mpath.c b/bgpd/bgp_mpath.c index f564ff169..a95c4a008 100644 --- a/bgpd/bgp_mpath.c +++ b/bgpd/bgp_mpath.c @@ -84,11 +84,11 @@ bgp_maximum_paths_unset (struct bgp *bgp, afi_t afi, safi_t safi, switch (peertype) { case BGP_PEER_IBGP: - bgp->maxpaths[afi][safi].maxpaths_ibgp = MULTIPATH_NUM; + bgp->maxpaths[afi][safi].maxpaths_ibgp = multipath_num; bgp->maxpaths[afi][safi].ibgp_flags = 0; break; case BGP_PEER_EBGP: - bgp->maxpaths[afi][safi].maxpaths_ebgp = MULTIPATH_NUM; + bgp->maxpaths[afi][safi].maxpaths_ebgp = multipath_num; break; default: return -1; @@ -436,7 +436,7 @@ bgp_info_mpath_update (struct bgp_node *rn, struct bgp_info *new_best, char path_buf[PATH_ADDPATH_STR_BUFFER]; mpath_changed = 0; - maxpaths = MULTIPATH_NUM; + maxpaths = multipath_num; mpath_count = 0; cur_mpath = NULL; old_mpath_count = 0; diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index aa8c3145f..07f2d5945 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -1144,6 +1144,13 @@ bgp_maxpaths_config_vty (struct vty *vty, int peer_type, const char *mpaths, if (set) { maxpaths = strtol(mpaths, NULL, 10); + if (maxpaths > multipath_num) + { + vty_out (vty, + "%% Maxpaths Specified: %d is > than multipath num specified on bgp command line %d", + maxpaths, multipath_num); + return CMD_WARNING; + } ret = bgp_maximum_paths_set (bgp, afi, safi, peer_type, maxpaths, options); } else diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c index 822f459c2..2a513dda2 100644 --- a/bgpd/bgp_zebra.c +++ b/bgpd/bgp_zebra.c @@ -69,7 +69,7 @@ struct stream *bgp_ifindices_buf = NULL; Number of supported next-hops are finite, use of arrays should be ok. */ struct attr attr_cp[MULTIPATH_NUM]; struct attr_extra attr_extra_cp[MULTIPATH_NUM]; -int attr_index = 0; +unsigned int attr_index = 0; /* Once per address-family initialization of the attribute array */ #define BGP_INFO_ATTR_BUF_INIT()\ @@ -82,7 +82,7 @@ do {\ #define BGP_INFO_ATTR_BUF_COPY(info_src, info_dst)\ do { \ *info_dst = *info_src; \ - assert(attr_index != MULTIPATH_NUM);\ + assert(attr_index != multipath_num);\ attr_cp[attr_index].extra = &attr_extra_cp[attr_index]; \ bgp_attr_dup (&attr_cp[attr_index], info_src->attr); \ bgp_attr_deep_dup (&attr_cp[attr_index], info_src->attr); \ diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c index 3512167b0..9b779e5d3 100644 --- a/bgpd/bgpd.c +++ b/bgpd/bgpd.c @@ -93,6 +93,8 @@ struct bgp_master *bm; /* BGP community-list. */ struct community_list_handler *bgp_clist; +unsigned int multipath_num = MULTIPATH_NUM; + static void bgp_if_init (struct bgp *bgp); static void bgp_if_finish (struct bgp *bgp); @@ -2918,8 +2920,8 @@ bgp_create (as_t *as, const char *name, enum bgp_instance_type inst_type) bgp->rib[afi][safi] = bgp_table_init (afi, safi); /* Enable maximum-paths */ - bgp_maximum_paths_set (bgp, afi, safi, BGP_PEER_EBGP, MULTIPATH_NUM, 0); - bgp_maximum_paths_set (bgp, afi, safi, BGP_PEER_IBGP, MULTIPATH_NUM, 0); + bgp_maximum_paths_set (bgp, afi, safi, BGP_PEER_EBGP, multipath_num, 0); + bgp_maximum_paths_set (bgp, afi, safi, BGP_PEER_IBGP, multipath_num, 0); } bgp->v_update_delay = BGP_UPDATE_DELAY_DEF; diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h index 09c64aa33..f0f2ed87b 100644 --- a/bgpd/bgpd.h +++ b/bgpd/bgpd.h @@ -1161,6 +1161,7 @@ typedef enum } bgp_policy_type_e; extern struct bgp_master *bm; +extern unsigned int multipath_num; /* Prototypes. */ extern void bgp_terminate (void); diff --git a/zebra/main.c b/zebra/main.c index 79c9ea702..b72ce84cd 100644 --- a/zebra/main.c +++ b/zebra/main.c @@ -96,6 +96,7 @@ struct option longopts[] = { "vty_addr", required_argument, NULL, 'A'}, { "vty_port", required_argument, NULL, 'P'}, { "vty_socket", required_argument, NULL, OPTION_VTYSOCK }, + { "ecmp", required_argument, NULL, 'e'}, { "retain", no_argument, NULL, 'r'}, { "dryrun", no_argument, NULL, 'C'}, #ifdef HAVE_NETLINK @@ -135,6 +136,8 @@ char config_default[] = SYSCONFDIR DEFAULT_CONFIG_FILE; /* Process ID saved for use by init system */ const char *pid_file = PATH_ZEBRA_PID; +unsigned int multipath_num = MULTIPATH_NUM; + /* Help information display. */ static void usage (char *progname, int status) @@ -328,6 +331,14 @@ main (int argc, char **argv) case 'A': vty_addr = optarg; break; + case 'e': + multipath_num = atoi (optarg); + if (multipath_num > MULTIPATH_NUM || multipath_num <= 0) + { + zlog_err ("Multipath Number specified must be less than %d and greater than 0", MULTIPATH_NUM); + return 1; + } + break; case 'i': pid_file = optarg; break; diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c index d88dc05b2..c2bfa7065 100644 --- a/zebra/rt_netlink.c +++ b/zebra/rt_netlink.c @@ -1257,7 +1257,7 @@ netlink_route_multipath (int cmd, struct prefix *p, struct prefix *src_p, struct sockaddr_nl snl; struct nexthop *nexthop = NULL, *tnexthop; int recursing; - int nexthop_num; + unsigned int nexthop_num; int discard; int family = PREFIX_FAMILY(p); const char *routedesc; @@ -1373,7 +1373,7 @@ netlink_route_multipath (int cmd, struct prefix *p, struct prefix *src_p, } /* Singlepath case. */ - if (nexthop_num == 1 || MULTIPATH_NUM == 1) + if (nexthop_num == 1 || multipath_num == 1) { nexthop_num = 0; for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing)) @@ -1449,7 +1449,7 @@ netlink_route_multipath (int cmd, struct prefix *p, struct prefix *src_p, nexthop_num = 0; for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing)) { - if (nexthop_num >= MULTIPATH_NUM) + if (nexthop_num >= multipath_num) break; if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE)) @@ -1606,7 +1606,7 @@ netlink_mpls_multipath (int cmd, zebra_lsp_t *lsp) mpls_lse_t lse; zebra_nhlfe_t *nhlfe; struct nexthop *nexthop = NULL; - int nexthop_num; + unsigned int nexthop_num; const char *routedesc; struct zebra_ns *zns = zebra_ns_lookup (NS_DEFAULT); @@ -1670,7 +1670,7 @@ netlink_mpls_multipath (int cmd, zebra_lsp_t *lsp) /* Fill nexthops (paths) based on single-path or multipath. The paths * chosen depend on the operation. */ - if (nexthop_num == 1 || MULTIPATH_NUM == 1) + if (nexthop_num == 1 || multipath_num == 1) { routedesc = "single hop"; _netlink_mpls_debug(cmd, lsp->ile.in_label, routedesc); @@ -1728,7 +1728,7 @@ netlink_mpls_multipath (int cmd, zebra_lsp_t *lsp) if (!nexthop) continue; - if (MULTIPATH_NUM != 0 && nexthop_num >= MULTIPATH_NUM) + if (nexthop_num >= multipath_num) break; if ((cmd == RTM_NEWROUTE && diff --git a/zebra/zebra_fpm_netlink.c b/zebra/zebra_fpm_netlink.c index 9fffc9e61..92ab5df2c 100644 --- a/zebra/zebra_fpm_netlink.c +++ b/zebra/zebra_fpm_netlink.c @@ -137,7 +137,7 @@ typedef struct netlink_route_info_t_ u_char af; struct prefix *prefix; uint32_t *metric; - int num_nhs; + unsigned int num_nhs; /* * Nexthop structures @@ -289,7 +289,7 @@ netlink_route_info_fill (netlink_route_info_t *ri, int cmd, for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing)) { - if (ri->num_nhs >= MULTIPATH_NUM) + if (ri->num_nhs >= multipath_num) break; if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE)) @@ -325,7 +325,7 @@ netlink_route_info_encode (netlink_route_info_t *ri, char *in_buf, size_t in_buf_len) { size_t bytelen; - int nexthop_num = 0; + unsigned int nexthop_num = 0; size_t buf_offset; netlink_nh_info_t *nhi; @@ -447,7 +447,7 @@ static void zfpm_log_route_info (netlink_route_info_t *ri, const char *label) { netlink_nh_info_t *nhi; - int i; + unsigned int i; zfpm_debug ("%s : %s %s/%d, Proto: %s, Metric: %u", label, nl_msg_type_to_str (ri->nlmsg_type), diff --git a/zebra/zebra_fpm_protobuf.c b/zebra/zebra_fpm_protobuf.c index 702c355f1..fba57c68f 100644 --- a/zebra/zebra_fpm_protobuf.c +++ b/zebra/zebra_fpm_protobuf.c @@ -149,7 +149,7 @@ create_add_route_message (qpb_allocator_t *allocator, rib_dest_t *dest, struct nexthop *nexthop, *tnexthop; int recursing; uint num_nhs, u; - struct nexthop *nexthops[MAX (MULTIPATH_NUM, 64)]; + struct nexthop *nexthops[MULTIPATH_NUM]; msg = QPB_ALLOC(allocator, typeof(*msg)); if (!msg) { @@ -198,7 +198,7 @@ create_add_route_message (qpb_allocator_t *allocator, rib_dest_t *dest, num_nhs = 0; for (ALL_NEXTHOPS_RO (rib->nexthop, nexthop, tnexthop, recursing)) { - if (MULTIPATH_NUM != 0 && num_nhs >= MULTIPATH_NUM) + if (num_nhs >= multipath_num) break; if (num_nhs >= ZEBRA_NUM_OF(nexthops)) diff --git a/zebra/zebra_mpls_openbsd.c b/zebra/zebra_mpls_openbsd.c index 1127f568c..b68b03e0c 100644 --- a/zebra/zebra_mpls_openbsd.c +++ b/zebra/zebra_mpls_openbsd.c @@ -138,7 +138,7 @@ kernel_lsp_cmd (int action, zebra_lsp_t *lsp) if (!nexthop) continue; - if (MULTIPATH_NUM != 0 && nexthop_num >= MULTIPATH_NUM) + if (nexthop_num >= multipath_num) break; /* XXX */ diff --git a/zebra/zserv.c b/zebra/zserv.c index 29515e918..60364410a 100644 --- a/zebra/zserv.c +++ b/zebra/zserv.c @@ -1050,12 +1050,12 @@ zread_interface_delete (struct zserv *client, u_short length, struct zebra_vrf * void zserv_nexthop_num_warn (const char *caller, const struct prefix *p, const unsigned int nexthop_num) { - if (nexthop_num > MULTIPATH_NUM) + if (nexthop_num > multipath_num) { char buff[PREFIX2STR_BUFFER]; prefix2str(p, buff, sizeof (buff)); zlog_warn("%s: Prefix %s has %d nexthops, but we can only use the first %d", - caller, buff, nexthop_num, MULTIPATH_NUM); + caller, buff, nexthop_num, multipath_num); } } @@ -1274,7 +1274,7 @@ zread_ipv4_nexthop_lookup_mrib (struct zserv *client, u_short length, struct zeb static int zread_ipv4_route_ipv6_nexthop_add (struct zserv *client, u_short length, struct zebra_vrf *zvrf) { - int i; + unsigned int i; struct stream *s; struct in6_addr nexthop; struct rib *rib; @@ -1318,9 +1318,9 @@ zread_ipv4_route_ipv6_nexthop_add (struct zserv *client, u_short length, struct * next-hop-addr/next-hop-ifindices. */ if (CHECK_FLAG (message, ZAPI_MESSAGE_NEXTHOP)) { - int nh_count = 0; - int if_count = 0; - int max_nh_if = 0; + unsigned int nh_count = 0; + unsigned int if_count = 0; + unsigned int max_nh_if = 0; nexthop_num = stream_getc (s); zserv_nexthop_num_warn(__func__, (const struct prefix *)&p, nexthop_num); @@ -1332,12 +1332,12 @@ zread_ipv4_route_ipv6_nexthop_add (struct zserv *client, u_short length, struct { case NEXTHOP_TYPE_IPV6: stream_get (&nexthop, s, 16); - if (nh_count < MULTIPATH_NUM) { + if (nh_count < multipath_num) { nexthops[nh_count++] = nexthop; } break; case NEXTHOP_TYPE_IFINDEX: - if (if_count < MULTIPATH_NUM) { + if (if_count < multipath_num) { ifindices[if_count++] = stream_getl (s); } break; @@ -1401,7 +1401,7 @@ zread_ipv4_route_ipv6_nexthop_add (struct zserv *client, u_short length, struct static int zread_ipv6_add (struct zserv *client, u_short length, struct zebra_vrf *zvrf) { - int i; + unsigned int i; struct stream *s; struct in6_addr nexthop; struct rib *rib; @@ -1454,9 +1454,9 @@ zread_ipv6_add (struct zserv *client, u_short length, struct zebra_vrf *zvrf) * next-hop-addr/next-hop-ifindices. */ if (CHECK_FLAG (message, ZAPI_MESSAGE_NEXTHOP)) { - int nh_count = 0; - int if_count = 0; - int max_nh_if = 0; + unsigned int nh_count = 0; + unsigned int if_count = 0; + unsigned int max_nh_if = 0; nexthop_num = stream_getc (s); zserv_nexthop_num_warn(__func__, (const struct prefix *)&p, nexthop_num); @@ -1468,12 +1468,12 @@ zread_ipv6_add (struct zserv *client, u_short length, struct zebra_vrf *zvrf) { case NEXTHOP_TYPE_IPV6: stream_get (&nexthop, s, 16); - if (nh_count < MULTIPATH_NUM) { + if (nh_count < multipath_num) { nexthops[nh_count++] = nexthop; } break; case NEXTHOP_TYPE_IFINDEX: - if (if_count < MULTIPATH_NUM) { + if (if_count < multipath_num) { ifindices[if_count++] = stream_getl (s); } break; diff --git a/zebra/zserv.h b/zebra/zserv.h index a5a997946..21cf1004b 100644 --- a/zebra/zserv.h +++ b/zebra/zserv.h @@ -135,6 +135,7 @@ struct zebra_t struct work_queue *lsp_process_q; }; extern struct zebra_t zebrad; +extern unsigned int multipath_num; /* Prototypes. */ extern void zebra_init (void); -- 2.39.5