Merge pull request #233 from donaldsharp/ecmp1

bgpd, zebra: Allow setting ecmp from daemon cli
This commit is contained in:
Renato Westphal 2017-03-03 12:42:52 -03:00 committed by GitHub
commit 83456d1438
13 changed files with 66 additions and 34 deletions

View File

@ -75,6 +75,7 @@ static const struct option longopts[] =
{ "vty_socket", required_argument, NULL, OPTION_VTYSOCK }, { "vty_socket", required_argument, NULL, OPTION_VTYSOCK },
{ "retain", no_argument, NULL, 'r'}, { "retain", no_argument, NULL, 'r'},
{ "no_kernel", no_argument, NULL, 'n'}, { "no_kernel", no_argument, NULL, 'n'},
{ "ecmp", required_argument, NULL, 'e'},
{ "user", required_argument, NULL, 'u'}, { "user", required_argument, NULL, 'u'},
{ "group", required_argument, NULL, 'g'}, { "group", required_argument, NULL, 'g'},
{ "skip_runas", no_argument, NULL, 'S'}, { "skip_runas", no_argument, NULL, 'S'},
@ -176,6 +177,7 @@ redistribution between different routing protocols.\n\n\
--vty_socket Override vty socket path\n\ --vty_socket Override vty socket path\n\
-r, --retain When program terminates, retain added route by bgpd.\n\ -r, --retain When program terminates, retain added route by bgpd.\n\
-n, --no_kernel Do not install route to kernel.\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\ -u, --user User to run as\n\
-g, --group Group to run as\n\ -g, --group Group to run as\n\
-S, --skip_runas Skip user and group run as\n\ -S, --skip_runas Skip user and group run as\n\
@ -468,6 +470,14 @@ main (int argc, char **argv)
case 'A': case 'A':
vty_addr = optarg; vty_addr = optarg;
break; 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': case 'P':
/* Deal with atoi() returning 0 on failure, and bgpd not /* Deal with atoi() returning 0 on failure, and bgpd not
listening on bgp port... */ listening on bgp port... */

View File

@ -84,11 +84,11 @@ bgp_maximum_paths_unset (struct bgp *bgp, afi_t afi, safi_t safi,
switch (peertype) switch (peertype)
{ {
case BGP_PEER_IBGP: 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; bgp->maxpaths[afi][safi].ibgp_flags = 0;
break; break;
case BGP_PEER_EBGP: case BGP_PEER_EBGP:
bgp->maxpaths[afi][safi].maxpaths_ebgp = MULTIPATH_NUM; bgp->maxpaths[afi][safi].maxpaths_ebgp = multipath_num;
break; break;
default: default:
return -1; 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]; char path_buf[PATH_ADDPATH_STR_BUFFER];
mpath_changed = 0; mpath_changed = 0;
maxpaths = MULTIPATH_NUM; maxpaths = multipath_num;
mpath_count = 0; mpath_count = 0;
cur_mpath = NULL; cur_mpath = NULL;
old_mpath_count = 0; old_mpath_count = 0;

View File

@ -1144,6 +1144,13 @@ bgp_maxpaths_config_vty (struct vty *vty, int peer_type, const char *mpaths,
if (set) if (set)
{ {
maxpaths = strtol(mpaths, NULL, 10); 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); ret = bgp_maximum_paths_set (bgp, afi, safi, peer_type, maxpaths, options);
} }
else else

View File

@ -69,7 +69,7 @@ struct stream *bgp_ifindices_buf = NULL;
Number of supported next-hops are finite, use of arrays should be ok. */ Number of supported next-hops are finite, use of arrays should be ok. */
struct attr attr_cp[MULTIPATH_NUM]; struct attr attr_cp[MULTIPATH_NUM];
struct attr_extra attr_extra_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 */ /* Once per address-family initialization of the attribute array */
#define BGP_INFO_ATTR_BUF_INIT()\ #define BGP_INFO_ATTR_BUF_INIT()\
@ -82,7 +82,7 @@ do {\
#define BGP_INFO_ATTR_BUF_COPY(info_src, info_dst)\ #define BGP_INFO_ATTR_BUF_COPY(info_src, info_dst)\
do { \ do { \
*info_dst = *info_src; \ *info_dst = *info_src; \
assert(attr_index != MULTIPATH_NUM);\ assert(attr_index != multipath_num);\
attr_cp[attr_index].extra = &attr_extra_cp[attr_index]; \ attr_cp[attr_index].extra = &attr_extra_cp[attr_index]; \
bgp_attr_dup (&attr_cp[attr_index], info_src->attr); \ bgp_attr_dup (&attr_cp[attr_index], info_src->attr); \
bgp_attr_deep_dup (&attr_cp[attr_index], info_src->attr); \ bgp_attr_deep_dup (&attr_cp[attr_index], info_src->attr); \

View File

@ -93,6 +93,8 @@ struct bgp_master *bm;
/* BGP community-list. */ /* BGP community-list. */
struct community_list_handler *bgp_clist; struct community_list_handler *bgp_clist;
unsigned int multipath_num = MULTIPATH_NUM;
static void bgp_if_init (struct bgp *bgp); static void bgp_if_init (struct bgp *bgp);
static void bgp_if_finish (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); bgp->rib[afi][safi] = bgp_table_init (afi, safi);
/* Enable maximum-paths */ /* 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_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_IBGP, multipath_num, 0);
} }
bgp->v_update_delay = BGP_UPDATE_DELAY_DEF; bgp->v_update_delay = BGP_UPDATE_DELAY_DEF;

View File

@ -1161,6 +1161,7 @@ typedef enum
} bgp_policy_type_e; } bgp_policy_type_e;
extern struct bgp_master *bm; extern struct bgp_master *bm;
extern unsigned int multipath_num;
/* Prototypes. */ /* Prototypes. */
extern void bgp_terminate (void); extern void bgp_terminate (void);

View File

@ -96,6 +96,7 @@ struct option longopts[] =
{ "vty_addr", required_argument, NULL, 'A'}, { "vty_addr", required_argument, NULL, 'A'},
{ "vty_port", required_argument, NULL, 'P'}, { "vty_port", required_argument, NULL, 'P'},
{ "vty_socket", required_argument, NULL, OPTION_VTYSOCK }, { "vty_socket", required_argument, NULL, OPTION_VTYSOCK },
{ "ecmp", required_argument, NULL, 'e'},
{ "retain", no_argument, NULL, 'r'}, { "retain", no_argument, NULL, 'r'},
{ "dryrun", no_argument, NULL, 'C'}, { "dryrun", no_argument, NULL, 'C'},
#ifdef HAVE_NETLINK #ifdef HAVE_NETLINK
@ -135,6 +136,8 @@ char config_default[] = SYSCONFDIR DEFAULT_CONFIG_FILE;
/* Process ID saved for use by init system */ /* Process ID saved for use by init system */
const char *pid_file = PATH_ZEBRA_PID; const char *pid_file = PATH_ZEBRA_PID;
unsigned int multipath_num = MULTIPATH_NUM;
/* Help information display. */ /* Help information display. */
static void static void
usage (char *progname, int status) usage (char *progname, int status)
@ -328,6 +331,14 @@ main (int argc, char **argv)
case 'A': case 'A':
vty_addr = optarg; vty_addr = optarg;
break; 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': case 'i':
pid_file = optarg; pid_file = optarg;
break; break;

View File

@ -1108,7 +1108,7 @@ netlink_route_multipath (int cmd, struct prefix *p, struct prefix *src_p,
struct sockaddr_nl snl; struct sockaddr_nl snl;
struct nexthop *nexthop = NULL, *tnexthop; struct nexthop *nexthop = NULL, *tnexthop;
int recursing; int recursing;
int nexthop_num; unsigned int nexthop_num;
int discard; int discard;
int family = PREFIX_FAMILY(p); int family = PREFIX_FAMILY(p);
const char *routedesc; const char *routedesc;
@ -1224,7 +1224,7 @@ netlink_route_multipath (int cmd, struct prefix *p, struct prefix *src_p,
} }
/* Singlepath case. */ /* Singlepath case. */
if (nexthop_num == 1 || MULTIPATH_NUM == 1) if (nexthop_num == 1 || multipath_num == 1)
{ {
nexthop_num = 0; nexthop_num = 0;
for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing)) for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing))
@ -1300,7 +1300,7 @@ netlink_route_multipath (int cmd, struct prefix *p, struct prefix *src_p,
nexthop_num = 0; nexthop_num = 0;
for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing)) for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing))
{ {
if (nexthop_num >= MULTIPATH_NUM) if (nexthop_num >= multipath_num)
break; break;
if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE)) if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
@ -1457,7 +1457,7 @@ netlink_mpls_multipath (int cmd, zebra_lsp_t *lsp)
mpls_lse_t lse; mpls_lse_t lse;
zebra_nhlfe_t *nhlfe; zebra_nhlfe_t *nhlfe;
struct nexthop *nexthop = NULL; struct nexthop *nexthop = NULL;
int nexthop_num; unsigned int nexthop_num;
const char *routedesc; const char *routedesc;
struct zebra_ns *zns = zebra_ns_lookup (NS_DEFAULT); struct zebra_ns *zns = zebra_ns_lookup (NS_DEFAULT);
@ -1521,7 +1521,7 @@ netlink_mpls_multipath (int cmd, zebra_lsp_t *lsp)
/* Fill nexthops (paths) based on single-path or multipath. The paths /* Fill nexthops (paths) based on single-path or multipath. The paths
* chosen depend on the operation. * chosen depend on the operation.
*/ */
if (nexthop_num == 1 || MULTIPATH_NUM == 1) if (nexthop_num == 1 || multipath_num == 1)
{ {
routedesc = "single hop"; routedesc = "single hop";
_netlink_mpls_debug(cmd, lsp->ile.in_label, routedesc); _netlink_mpls_debug(cmd, lsp->ile.in_label, routedesc);
@ -1579,7 +1579,7 @@ netlink_mpls_multipath (int cmd, zebra_lsp_t *lsp)
if (!nexthop) if (!nexthop)
continue; continue;
if (MULTIPATH_NUM != 0 && nexthop_num >= MULTIPATH_NUM) if (nexthop_num >= multipath_num)
break; break;
if ((cmd == RTM_NEWROUTE && if ((cmd == RTM_NEWROUTE &&

View File

@ -137,7 +137,7 @@ typedef struct netlink_route_info_t_
u_char af; u_char af;
struct prefix *prefix; struct prefix *prefix;
uint32_t *metric; uint32_t *metric;
int num_nhs; unsigned int num_nhs;
/* /*
* Nexthop structures * 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)) for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing))
{ {
if (ri->num_nhs >= MULTIPATH_NUM) if (ri->num_nhs >= multipath_num)
break; break;
if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE)) 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 in_buf_len)
{ {
size_t bytelen; size_t bytelen;
int nexthop_num = 0; unsigned int nexthop_num = 0;
size_t buf_offset; size_t buf_offset;
netlink_nh_info_t *nhi; netlink_nh_info_t *nhi;
@ -447,7 +447,7 @@ static void
zfpm_log_route_info (netlink_route_info_t *ri, const char *label) zfpm_log_route_info (netlink_route_info_t *ri, const char *label)
{ {
netlink_nh_info_t *nhi; netlink_nh_info_t *nhi;
int i; unsigned int i;
zfpm_debug ("%s : %s %s/%d, Proto: %s, Metric: %u", label, zfpm_debug ("%s : %s %s/%d, Proto: %s, Metric: %u", label,
nl_msg_type_to_str (ri->nlmsg_type), nl_msg_type_to_str (ri->nlmsg_type),

View File

@ -149,7 +149,7 @@ create_add_route_message (qpb_allocator_t *allocator, rib_dest_t *dest,
struct nexthop *nexthop, *tnexthop; struct nexthop *nexthop, *tnexthop;
int recursing; int recursing;
uint num_nhs, u; uint num_nhs, u;
struct nexthop *nexthops[MAX (MULTIPATH_NUM, 64)]; struct nexthop *nexthops[MULTIPATH_NUM];
msg = QPB_ALLOC(allocator, typeof(*msg)); msg = QPB_ALLOC(allocator, typeof(*msg));
if (!msg) { if (!msg) {
@ -198,7 +198,7 @@ create_add_route_message (qpb_allocator_t *allocator, rib_dest_t *dest,
num_nhs = 0; num_nhs = 0;
for (ALL_NEXTHOPS_RO (rib->nexthop, nexthop, tnexthop, recursing)) for (ALL_NEXTHOPS_RO (rib->nexthop, nexthop, tnexthop, recursing))
{ {
if (MULTIPATH_NUM != 0 && num_nhs >= MULTIPATH_NUM) if (num_nhs >= multipath_num)
break; break;
if (num_nhs >= ZEBRA_NUM_OF(nexthops)) if (num_nhs >= ZEBRA_NUM_OF(nexthops))

View File

@ -138,7 +138,7 @@ kernel_lsp_cmd (int action, zebra_lsp_t *lsp)
if (!nexthop) if (!nexthop)
continue; continue;
if (MULTIPATH_NUM != 0 && nexthop_num >= MULTIPATH_NUM) if (nexthop_num >= multipath_num)
break; break;
/* XXX */ /* XXX */

View File

@ -1050,12 +1050,12 @@ zread_interface_delete (struct zserv *client, u_short length, struct zebra_vrf *
void void
zserv_nexthop_num_warn (const char *caller, const struct prefix *p, const unsigned int nexthop_num) 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]; char buff[PREFIX2STR_BUFFER];
prefix2str(p, buff, sizeof (buff)); prefix2str(p, buff, sizeof (buff));
zlog_warn("%s: Prefix %s has %d nexthops, but we can only use the first %d", 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 static int
zread_ipv4_route_ipv6_nexthop_add (struct zserv *client, u_short length, struct zebra_vrf *zvrf) 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 stream *s;
struct in6_addr nexthop; struct in6_addr nexthop;
struct rib *rib; 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. */ * next-hop-addr/next-hop-ifindices. */
if (CHECK_FLAG (message, ZAPI_MESSAGE_NEXTHOP)) if (CHECK_FLAG (message, ZAPI_MESSAGE_NEXTHOP))
{ {
int nh_count = 0; unsigned int nh_count = 0;
int if_count = 0; unsigned int if_count = 0;
int max_nh_if = 0; unsigned int max_nh_if = 0;
nexthop_num = stream_getc (s); nexthop_num = stream_getc (s);
zserv_nexthop_num_warn(__func__, (const struct prefix *)&p, nexthop_num); 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: case NEXTHOP_TYPE_IPV6:
stream_get (&nexthop, s, 16); stream_get (&nexthop, s, 16);
if (nh_count < MULTIPATH_NUM) { if (nh_count < multipath_num) {
nexthops[nh_count++] = nexthop; nexthops[nh_count++] = nexthop;
} }
break; break;
case NEXTHOP_TYPE_IFINDEX: case NEXTHOP_TYPE_IFINDEX:
if (if_count < MULTIPATH_NUM) { if (if_count < multipath_num) {
ifindices[if_count++] = stream_getl (s); ifindices[if_count++] = stream_getl (s);
} }
break; break;
@ -1401,7 +1401,7 @@ zread_ipv4_route_ipv6_nexthop_add (struct zserv *client, u_short length, struct
static int static int
zread_ipv6_add (struct zserv *client, u_short length, struct zebra_vrf *zvrf) zread_ipv6_add (struct zserv *client, u_short length, struct zebra_vrf *zvrf)
{ {
int i; unsigned int i;
struct stream *s; struct stream *s;
struct in6_addr nexthop; struct in6_addr nexthop;
struct rib *rib; 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. */ * next-hop-addr/next-hop-ifindices. */
if (CHECK_FLAG (message, ZAPI_MESSAGE_NEXTHOP)) if (CHECK_FLAG (message, ZAPI_MESSAGE_NEXTHOP))
{ {
int nh_count = 0; unsigned int nh_count = 0;
int if_count = 0; unsigned int if_count = 0;
int max_nh_if = 0; unsigned int max_nh_if = 0;
nexthop_num = stream_getc (s); nexthop_num = stream_getc (s);
zserv_nexthop_num_warn(__func__, (const struct prefix *)&p, nexthop_num); 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: case NEXTHOP_TYPE_IPV6:
stream_get (&nexthop, s, 16); stream_get (&nexthop, s, 16);
if (nh_count < MULTIPATH_NUM) { if (nh_count < multipath_num) {
nexthops[nh_count++] = nexthop; nexthops[nh_count++] = nexthop;
} }
break; break;
case NEXTHOP_TYPE_IFINDEX: case NEXTHOP_TYPE_IFINDEX:
if (if_count < MULTIPATH_NUM) { if (if_count < multipath_num) {
ifindices[if_count++] = stream_getl (s); ifindices[if_count++] = stream_getl (s);
} }
break; break;

View File

@ -135,6 +135,7 @@ struct zebra_t
struct work_queue *lsp_process_q; struct work_queue *lsp_process_q;
}; };
extern struct zebra_t zebrad; extern struct zebra_t zebrad;
extern unsigned int multipath_num;
/* Prototypes. */ /* Prototypes. */
extern void zebra_init (void); extern void zebra_init (void);