diff --git a/babeld/kernel.c b/babeld/kernel.c index 26860f3bae..105a7d0518 100644 --- a/babeld/kernel.c +++ b/babeld/kernel.c @@ -144,15 +144,15 @@ kernel_route_v4(int add, const unsigned char *gate, int ifindex, unsigned int metric) { struct zapi_route api; /* quagga's communication system */ + struct zapi_nexthop *api_nh; /* next router to go - no ECMP */ struct prefix quagga_prefix; /* quagga's prefix */ struct in_addr babel_prefix_addr; /* babeld's prefix addr */ - struct nexthop nexthop; /* next router to go */ - struct nexthop *nexthop_pointer = &nexthop; /* it's an array! */ + + api_nh = &api.nexthops[0]; /* convert to be understandable by quagga */ /* convert given addresses */ uchar_to_inaddr(&babel_prefix_addr, pref); - uchar_to_inaddr(&nexthop.gate.ipv4, gate); /* make prefix structure */ memset (&quagga_prefix, 0, sizeof(quagga_prefix)); @@ -168,6 +168,7 @@ kernel_route_v4(int add, api.instance = 0; api.safi = SAFI_UNICAST; api.vrf_id = VRF_DEFAULT; + api.prefix = quagga_prefix; SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP); if(metric >= KERNEL_INFINITY) { @@ -175,13 +176,13 @@ kernel_route_v4(int add, api.nexthop_num = 0; } else { api.nexthop_num = 1; - api.nexthop = &nexthop_pointer; - nexthop.ifindex = ifindex; - if (IPV4_ADDR_SAME (&nexthop.gate.ipv4, &quagga_prefix.u.prefix4) && + api_nh->ifindex = ifindex; + uchar_to_inaddr(&api_nh->gate.ipv4, gate); + if (IPV4_ADDR_SAME (&api_nh->gate.ipv4, &quagga_prefix.u.prefix4) && quagga_prefix.prefixlen == 32) { - nexthop.type = NEXTHOP_TYPE_IFINDEX; + api_nh->type = NEXTHOP_TYPE_IFINDEX; } else { - nexthop.type = NEXTHOP_TYPE_IPV4_IFINDEX; + api_nh->type = NEXTHOP_TYPE_IPV4_IFINDEX; } SET_FLAG(api.message, ZAPI_MESSAGE_METRIC); api.metric = metric; @@ -191,7 +192,7 @@ kernel_route_v4(int add, add ? "adding" : "removing" ); return zapi_route (add ? ZEBRA_IPV4_ROUTE_ADD : ZEBRA_IPV4_ROUTE_DELETE, - zclient, &quagga_prefix, NULL, &api); + zclient, &api); } static int @@ -199,15 +200,15 @@ kernel_route_v6(int add, const unsigned char *pref, unsigned short plen, const unsigned char *gate, int ifindex, unsigned int metric) { struct zapi_route api; /* quagga's communication system */ + struct zapi_nexthop *api_nh; /* next router to go - no ECMP */ struct prefix quagga_prefix; /* quagga's prefix */ struct in6_addr babel_prefix_addr; /* babeld's prefix addr */ - struct nexthop nexthop; /* next router to go */ - struct nexthop *nexthop_pointer = &nexthop; + + api_nh = &api.nexthops[0]; /* convert to be understandable by quagga */ /* convert given addresses */ uchar_to_in6addr(&babel_prefix_addr, pref); - uchar_to_in6addr(&nexthop.gate.ipv6, gate); /* make prefix structure */ memset (&quagga_prefix, 0, sizeof(quagga_prefix)); @@ -223,6 +224,7 @@ kernel_route_v6(int add, const unsigned char *pref, unsigned short plen, api.instance = 0; api.safi = SAFI_UNICAST; api.vrf_id = VRF_DEFAULT; + api.prefix = quagga_prefix; if(metric >= KERNEL_INFINITY) { api.flags = ZEBRA_FLAG_REJECT; @@ -230,10 +232,10 @@ kernel_route_v6(int add, const unsigned char *pref, unsigned short plen, } else { SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP); api.nexthop_num = 1; - api.nexthop = &nexthop_pointer; - nexthop.ifindex = ifindex; + api_nh->ifindex = ifindex; + uchar_to_in6addr(&api_nh->gate.ipv6, gate); /* difference to IPv4: always leave the linklocal as nexthop */ - nexthop.type = NEXTHOP_TYPE_IPV6_IFINDEX; + api_nh->type = NEXTHOP_TYPE_IPV6_IFINDEX; SET_FLAG(api.message, ZAPI_MESSAGE_METRIC); api.metric = metric; } @@ -242,7 +244,7 @@ kernel_route_v6(int add, const unsigned char *pref, unsigned short plen, add ? "adding" : "removing" ); return zapi_route (add ? ZEBRA_IPV6_ROUTE_ADD : ZEBRA_IPV6_ROUTE_DELETE, - zclient, &quagga_prefix, NULL, &api); + zclient, &api); } int diff --git a/lib/zclient.c b/lib/zclient.c index f8bbdd85c9..53e8569b77 100644 --- a/lib/zclient.c +++ b/lib/zclient.c @@ -892,16 +892,12 @@ int zapi_ipv6_route(u_char cmd, struct zclient *zclient, struct prefix_ipv6 *p, return zclient_send_message(zclient); } -int zapi_route(u_char cmd, struct zclient *zclient, struct prefix *p, - struct prefix_ipv6 *src_p, struct zapi_route *api) +int zapi_route(u_char cmd, struct zclient *zclient, struct zapi_route *api) { int i; int psize; struct stream *s; - - /* either we have !SRCPFX && src_p == NULL, or SRCPFX && src_p != NULL - */ - assert(!(api->message & ZAPI_MESSAGE_SRCPFX) == !src_p); + struct zapi_nexthop *api_nh; /* Reset stream. */ s = zclient->obuf; @@ -917,69 +913,63 @@ int zapi_route(u_char cmd, struct zclient *zclient, struct prefix *p, stream_putw(s, api->safi); /* Put prefix information. */ - psize = PSIZE(p->prefixlen); - stream_putc(s, p->prefixlen); - stream_write(s, (u_char *)&p->u.prefix, psize); + psize = PSIZE(api->prefix.prefixlen); + stream_putc(s, api->prefix.prefixlen); + stream_write(s, (u_char *)&api->prefix.u.prefix, psize); if (CHECK_FLAG(api->message, ZAPI_MESSAGE_SRCPFX)) { - psize = PSIZE(src_p->prefixlen); - stream_putc(s, src_p->prefixlen); - stream_write(s, (u_char *)&src_p->prefix, psize); + psize = PSIZE(api->src_prefix.prefixlen); + stream_putc(s, api->src_prefix.prefixlen); + stream_write(s, (u_char *)&api->src_prefix.prefix, psize); } /* Nexthop, ifindex, distance and metric information. */ if (CHECK_FLAG(api->message, ZAPI_MESSAGE_NEXTHOP)) { + /* limit the number of nexthops if necessary */ + if (api->nexthop_num > MULTIPATH_NUM) { + char buf[PREFIX2STR_BUFFER]; + + prefix2str(&api->prefix, buf, sizeof(buf)); + zlog_warn( + "%s: prefix %s: encoding %u nexthops out of %u", + __func__, buf, MULTIPATH_NUM, api->nexthop_num); + api->nexthop_num = MULTIPATH_NUM; + } + stream_putc(s, api->nexthop_num); for (i = 0; i < api->nexthop_num; i++) { - stream_putc(s, api->nexthop[i]->type); - switch (api->nexthop[i]->type) { + api_nh = &api->nexthops[i]; + + stream_putc(s, api_nh->type); + switch (api_nh->type) { case NEXTHOP_TYPE_BLACKHOLE: break; case NEXTHOP_TYPE_IPV4: - stream_put_in_addr(s, - &api->nexthop[i]->gate.ipv4); - - /* For labeled-unicast, each nexthop is followed - * by label. */ - if (CHECK_FLAG(api->message, - ZAPI_MESSAGE_LABEL)) - stream_putl( - s, - api->nexthop[i] - ->nh_label->label[0]); + stream_put_in_addr(s, &api_nh->gate.ipv4); break; case NEXTHOP_TYPE_IPV4_IFINDEX: - stream_put_in_addr(s, - &api->nexthop[i]->gate.ipv4); - stream_putl(s, api->nexthop[i]->ifindex); + stream_put_in_addr(s, &api_nh->gate.ipv4); + stream_putl(s, api_nh->ifindex); break; case NEXTHOP_TYPE_IFINDEX: - stream_putl(s, api->nexthop[i]->ifindex); + stream_putl(s, api_nh->ifindex); break; case NEXTHOP_TYPE_IPV6: - stream_write( - s, - (u_char *)&api->nexthop[i]->gate.ipv6, - 16); - - /* For labeled-unicast, each nexthop is followed - * by label. */ - if (CHECK_FLAG(api->message, - ZAPI_MESSAGE_LABEL)) - stream_putl( - s, - api->nexthop[i] - ->nh_label->label[0]); + stream_write(s, (u_char *)&api_nh->gate.ipv6, + 16); break; case NEXTHOP_TYPE_IPV6_IFINDEX: - stream_write( - s, - (u_char *)&api->nexthop[i]->gate.ipv6, - 16); - stream_putl(s, api->nexthop[i]->ifindex); + stream_write(s, (u_char *)&api_nh->gate.ipv6, + 16); + stream_putl(s, api_nh->ifindex); break; } + + /* For labeled-unicast, each nexthop is followed + * by label. */ + if (CHECK_FLAG(api->message, ZAPI_MESSAGE_LABEL)) + stream_putl(s, api_nh->label); } } diff --git a/lib/zclient.h b/lib/zclient.h index ddd9655443..92aeabb07f 100644 --- a/lib/zclient.h +++ b/lib/zclient.h @@ -224,6 +224,13 @@ struct zserv_header { uint16_t command; }; +struct zapi_nexthop { + enum nexthop_types_t type; + ifindex_t ifindex; + union g_addr gate; + mpls_label_t label; +}; + struct zapi_route { u_char type; u_short instance; @@ -234,8 +241,11 @@ struct zapi_route { safi_t safi; + struct prefix prefix; + struct prefix_ipv6 src_prefix; + u_char nexthop_num; - struct nexthop **nexthop; + struct zapi_nexthop nexthops[MULTIPATH_NUM]; u_char distance; @@ -416,7 +426,7 @@ extern int zapi_ipv6_route(u_char cmd, struct zclient *zclient, extern int zapi_ipv4_route_ipv6_nexthop(u_char, struct zclient *, struct prefix_ipv4 *, struct zapi_ipv6 *); -extern int zapi_route(u_char cmd, struct zclient *zclient, struct prefix *p, - struct prefix_ipv6 *src_p, struct zapi_route *api); +extern int zapi_route(u_char cmd, struct zclient *zclient, + struct zapi_route *api); #endif /* _ZEBRA_ZCLIENT_H */