Merge branch 'master' of https://github.com/dwalton76/frr into bgpd-draft-ietf-grow-bgp-gshut-10

Conflicts:
	bgpd/bgp_route.c
This commit is contained in:
Daniel Walton 2017-08-28 06:59:38 -07:00
commit 31d5efe2ea
99 changed files with 2771 additions and 4198 deletions

View File

@ -5,7 +5,7 @@ include common.am
AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/lib -I$(top_builddir) -I$(top_builddir)/lib AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/lib -I$(top_builddir) -I$(top_builddir)/lib
AM_CFLAGS = $(WERROR) AM_CFLAGS = $(WERROR)
DEFS = @DEFS@ -DSYSCONFDIR=\"$(sysconfdir)/\" DEFS = @DEFS@ -DSYSCONFDIR=\"$(sysconfdir)/\" -DCONFDATE=$(CONFDATE)
LIBCAP = @LIBCAP@ LIBCAP = @LIBCAP@
EXTRA_DIST = EXTRA_DIST =
@ -25,6 +25,14 @@ pkginclude_HEADERS =
nodist_pkginclude_HEADERS = nodist_pkginclude_HEADERS =
dist_examples_DATA = dist_examples_DATA =
## libtool, the self-made GNU scourge
## ... this should fix relinking
## ... and AUTOMAKE_DUMMY is needed to prevent automake from treating this
## as overriding the normal targets...
$(AUTOMAKE_DUMMY)install-moduleLTLIBRARIES: install-libLTLIBRARIES
$(AUTOMAKE_DUMMY)install-binPROGRAMS: install-libLTLIBRARIES
$(AUTOMAKE_DUMMY)install-sbinPROGRAMS: install-libLTLIBRARIES
include lib/subdir.am include lib/subdir.am
include zebra/subdir.am include zebra/subdir.am
include qpb/subdir.am include qpb/subdir.am

View File

@ -37,7 +37,6 @@ void babelz_zebra_init(void);
/* we must use a pointer because of zclient.c's functions (new, free). */ /* we must use a pointer because of zclient.c's functions (new, free). */
struct zclient *zclient; struct zclient *zclient;
static int zebra_config_write (struct vty *vty);
/* Debug types */ /* Debug types */
static struct { static struct {
@ -55,118 +54,24 @@ static struct {
{0, 0, NULL} {0, 0, NULL}
}; };
/* Zebra node structure. */ /* Zebra route add and delete treatment. */
struct cmd_node zebra_node =
{
ZEBRA_NODE,
"%s(config-router)# ",
1 /* vtysh? yes */
};
/* Zebra route add and delete treatment (ipv6). */
static int static int
babel_zebra_read_ipv6 (int command, struct zclient *zclient, babel_zebra_read_route (int command, struct zclient *zclient,
zebra_size_t length, vrf_id_t vrf) zebra_size_t length, vrf_id_t vrf)
{ {
struct stream *s; struct zapi_route api;
struct zapi_ipv6 api;
unsigned long ifindex = -1;
struct in6_addr nexthop;
struct prefix_ipv6 prefix;
s = zclient->ibuf; if (zapi_route_decode(zclient->ibuf, &api) < 0)
ifindex = 0; return -1;
memset (&nexthop, 0, sizeof (struct in6_addr));
memset (&api, 0, sizeof(struct zapi_ipv6));
memset (&prefix, 0, sizeof (struct prefix_ipv6));
/* Type, flags, message. */ /* we completely ignore srcdest routes for now. */
api.type = stream_getc (s); if (CHECK_FLAG(api.message, ZAPI_MESSAGE_SRCPFX))
api.instance = stream_getw (s); return 0;
api.flags = stream_getl (s);
api.message = stream_getc (s);
/* IPv6 prefix. */ if (command == ZEBRA_REDISTRIBUTE_ROUTE_ADD) {
prefix.family = AF_INET6; babel_route_add(&api);
prefix.prefixlen = stream_getc (s);
stream_get (&prefix.prefix, s, PSIZE (prefix.prefixlen));
/* Nexthop, ifindex, distance, metric. */
if (CHECK_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP)) {
api.nexthop_num = stream_getc (s);
stream_get (&nexthop, s, sizeof(nexthop));
}
if (CHECK_FLAG (api.message, ZAPI_MESSAGE_IFINDEX)) {
api.ifindex_num = stream_getc (s);
ifindex = stream_getl (s);
}
if (CHECK_FLAG (api.message, ZAPI_MESSAGE_DISTANCE))
api.distance = stream_getc (s);
else
api.distance = 0;
if (CHECK_FLAG (api.message, ZAPI_MESSAGE_METRIC))
api.metric = stream_getl (s);
else
api.metric = 0;
if (command == ZEBRA_REDISTRIBUTE_IPV6_ADD)
babel_ipv6_route_add(&api, &prefix, ifindex, &nexthop);
else
babel_ipv6_route_delete(&api, &prefix, ifindex);
return 0;
}
static int
babel_zebra_read_ipv4 (int command, struct zclient *zclient,
zebra_size_t length, vrf_id_t vrf)
{
struct stream *s;
struct zapi_ipv4 api;
unsigned long ifindex = -1;
struct in_addr nexthop;
struct prefix_ipv4 prefix;
s = zclient->ibuf;
ifindex = 0;
memset (&nexthop, 0, sizeof (struct in_addr));
memset (&api, 0, sizeof(struct zapi_ipv4));
memset (&prefix, 0, sizeof (struct prefix_ipv4));
/* Type, flags, message. */
api.type = stream_getc (s);
api.instance = stream_getw (s);
api.flags = stream_getl (s);
api.message = stream_getc (s);
/* IPv6 prefix. */
prefix.family = AF_INET;
prefix.prefixlen = stream_getc (s);
stream_get (&prefix.prefix, s, PSIZE (prefix.prefixlen));
/* Nexthop, ifindex, distance, metric. */
if (CHECK_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP)) {
api.nexthop_num = stream_getc (s);
stream_get (&nexthop, s, sizeof(nexthop));
}
if (CHECK_FLAG (api.message, ZAPI_MESSAGE_IFINDEX)) {
api.ifindex_num = stream_getc (s);
ifindex = stream_getl (s);
}
if (CHECK_FLAG (api.message, ZAPI_MESSAGE_DISTANCE))
api.distance = stream_getc (s);
else
api.distance = 0;
if (CHECK_FLAG (api.message, ZAPI_MESSAGE_METRIC))
api.metric = stream_getl (s);
else
api.metric = 0;
if (command == ZEBRA_REDISTRIBUTE_IPV4_ADD) {
babel_ipv4_route_add(&api, &prefix, ifindex, &nexthop);
} else { } else {
babel_ipv4_route_delete(&api, &prefix, ifindex); babel_route_delete(&api);
} }
return 0; return 0;
@ -342,12 +247,9 @@ void babelz_zebra_init(void)
zclient->interface_down = babel_interface_down; zclient->interface_down = babel_interface_down;
zclient->interface_address_add = babel_interface_address_add; zclient->interface_address_add = babel_interface_address_add;
zclient->interface_address_delete = babel_interface_address_delete; zclient->interface_address_delete = babel_interface_address_delete;
zclient->redistribute_route_ipv4_add = babel_zebra_read_ipv4; zclient->redistribute_route_add = babel_zebra_read_route;
zclient->redistribute_route_ipv4_del = babel_zebra_read_ipv4; zclient->redistribute_route_del = babel_zebra_read_route;
zclient->redistribute_route_ipv6_add = babel_zebra_read_ipv6;
zclient->redistribute_route_ipv6_del = babel_zebra_read_ipv6;
install_node (&zebra_node, zebra_config_write);
install_element(BABEL_NODE, &babel_redistribute_type_cmd); install_element(BABEL_NODE, &babel_redistribute_type_cmd);
install_element(ENABLE_NODE, &debug_babel_cmd); install_element(ENABLE_NODE, &debug_babel_cmd);
install_element(ENABLE_NODE, &no_debug_babel_cmd); install_element(ENABLE_NODE, &no_debug_babel_cmd);
@ -357,23 +259,6 @@ void babelz_zebra_init(void)
install_element(VIEW_NODE, &show_debugging_babel_cmd); install_element(VIEW_NODE, &show_debugging_babel_cmd);
} }
static int
zebra_config_write (struct vty *vty)
{
if (! zclient->enable)
{
vty_out (vty, "no router zebra\n");
return 1;
}
else if (! vrf_bitmap_check (zclient->redist[AFI_IP][ZEBRA_ROUTE_BABEL], VRF_DEFAULT))
{
vty_out (vty, "router zebra\n");
vty_out (vty, " no redistribute babel\n");
return 1;
}
return 0;
}
void void
babel_zebra_close_connexion(void) babel_zebra_close_connexion(void)
{ {

View File

@ -331,8 +331,8 @@ babel_main_loop(struct thread *thread)
/* if there is no timeout, we must wait. */ /* if there is no timeout, we must wait. */
if(timeval_compare(&tv, &babel_now) > 0) { if(timeval_compare(&tv, &babel_now) > 0) {
timeval_minus(&tv, &tv, &babel_now); timeval_minus(&tv, &tv, &babel_now);
debugf(BABEL_DEBUG_TIMEOUT, "babel main loop : timeout: %ld msecs", debugf(BABEL_DEBUG_TIMEOUT, "babel main loop : timeout: %lld msecs",
tv.tv_sec * 1000 + tv.tv_usec / 1000); (long long)tv.tv_sec * 1000 + tv.tv_usec / 1000);
/* it happens often to have less than 1 ms, it's bad. */ /* it happens often to have less than 1 ms, it's bad. */
timeval_add_msec(&tv, &tv, 300); timeval_add_msec(&tv, &tv, 300);
babel_set_timer(&tv); babel_set_timer(&tv);

View File

@ -51,13 +51,8 @@ THE SOFTWARE.
static int static int
kernel_route_v4(int add, const unsigned char *pref, unsigned short plen, zebra_route(int add, int familt, const unsigned char *pref, unsigned short plen,
const unsigned char *gate, int ifindex, const unsigned char *gate, int ifindex, unsigned int metric);
unsigned int metric);
static int
kernel_route_v6(int add, const unsigned char *pref, unsigned short plen,
const unsigned char *gate, int ifindex,
unsigned int metric);
int int
kernel_interface_operational(struct interface *interface) kernel_interface_operational(struct interface *interface)
@ -84,7 +79,7 @@ kernel_route(int operation, const unsigned char *pref, unsigned short plen,
unsigned int newmetric) unsigned int newmetric)
{ {
int rc; int rc;
int ipv4; int family;
/* Check that the protocol family is consistent. */ /* Check that the protocol family is consistent. */
if(plen >= 96 && v4mapped(pref)) { if(plen >= 96 && v4mapped(pref)) {
@ -92,46 +87,37 @@ kernel_route(int operation, const unsigned char *pref, unsigned short plen,
errno = EINVAL; errno = EINVAL;
return -1; return -1;
} }
ipv4 = 1; family = AF_INET;
} else { } else {
if(v4mapped(gate)) { if(v4mapped(gate)) {
errno = EINVAL; errno = EINVAL;
return -1; return -1;
} }
ipv4 = 0; family = AF_INET6;
} }
switch (operation) { switch (operation) {
case ROUTE_ADD: case ROUTE_ADD:
return ipv4 ? return zebra_route(1, family, pref, plen, gate, ifindex, metric);
kernel_route_v4(1, pref, plen, gate, ifindex, metric):
kernel_route_v6(1, pref, plen, gate, ifindex, metric);
break; break;
case ROUTE_FLUSH: case ROUTE_FLUSH:
return ipv4 ? return zebra_route(0, family, pref, plen, gate, ifindex, metric);
kernel_route_v4(0, pref, plen, gate, ifindex, metric):
kernel_route_v6(0, pref, plen, gate, ifindex, metric);
break; break;
case ROUTE_MODIFY: case ROUTE_MODIFY:
if(newmetric == metric && memcmp(newgate, gate, 16) == 0 && if(newmetric == metric && memcmp(newgate, gate, 16) == 0 &&
newifindex == ifindex) newifindex == ifindex)
return 0; return 0;
debugf(BABEL_DEBUG_ROUTE, "Modify route: delete old; add new."); debugf(BABEL_DEBUG_ROUTE, "Modify route: delete old; add new.");
rc = ipv4 ? rc = zebra_route(0, family, pref, plen, gate, ifindex, metric);
kernel_route_v4(0, pref, plen, gate, ifindex, metric):
kernel_route_v6(0, pref, plen, gate, ifindex, metric);
if (rc < 0) if (rc < 0)
return -1; return -1;
rc = ipv4 ? rc = zebra_route(1, family, pref, plen, newgate, newifindex,
kernel_route_v4(1, pref, plen, newgate, newifindex, newmetric): newmetric);
kernel_route_v6(1, pref, plen, newgate, newifindex, newmetric);
return rc; return rc;
break; break;
default: default:
zlog_err("this should never appens (false value - kernel_route)"); zlog_err("this should never happen (false value - kernel_route)");
assert(0); assert(0);
exit(1); exit(1);
break; break;
@ -139,110 +125,81 @@ kernel_route(int operation, const unsigned char *pref, unsigned short plen,
} }
static int static int
kernel_route_v4(int add, zebra_route(int add, int family, const unsigned char *pref, unsigned short plen,
const unsigned char *pref, unsigned short plen, const unsigned char *gate, int ifindex, unsigned int metric)
const unsigned char *gate, int ifindex, unsigned int metric)
{ {
struct zapi_route api; /* quagga's communication system */ struct zapi_route api; /* quagga's communication system */
struct prefix quagga_prefix; /* quagga's prefix */ struct prefix quagga_prefix; /* quagga's prefix */
struct in_addr babel_prefix_addr; /* babeld's prefix addr */ union g_addr babel_prefix_addr; /* babeld's prefix addr */
struct nexthop nexthop; /* next router to go */ struct zapi_nexthop *api_nh; /* next router to go - no ECMP */
struct nexthop *nexthop_pointer = &nexthop; /* it's an array! */
api_nh = &api.nexthops[0];
/* convert to be understandable by quagga */ /* convert to be understandable by quagga */
/* convert given addresses */ /* convert given addresses */
uchar_to_inaddr(&babel_prefix_addr, pref); switch (family) {
uchar_to_inaddr(&nexthop.gate.ipv4, gate); case AF_INET:
uchar_to_inaddr(&babel_prefix_addr.ipv4, pref);
break;
case AF_INET6:
uchar_to_in6addr(&babel_prefix_addr.ipv6, pref);
break;
}
/* make prefix structure */ /* make prefix structure */
memset (&quagga_prefix, 0, sizeof(quagga_prefix)); memset (&quagga_prefix, 0, sizeof(quagga_prefix));
quagga_prefix.family = AF_INET; quagga_prefix.family = family;
IPV4_ADDR_COPY (&quagga_prefix.u.prefix4, &babel_prefix_addr); switch (family) {
quagga_prefix.prefixlen = plen - 96; /* our plen is for v4mapped's addr */ case AF_INET:
IPV4_ADDR_COPY (&quagga_prefix.u.prefix4, &babel_prefix_addr.ipv4);
/* our plen is for v4mapped's addr */
quagga_prefix.prefixlen = plen - 96;
break;
case AF_INET6:
IPV6_ADDR_COPY (&quagga_prefix.u.prefix6, &babel_prefix_addr.ipv6);
quagga_prefix.prefixlen = plen;
break;
}
apply_mask(&quagga_prefix); apply_mask(&quagga_prefix);
memset(&api, 0, sizeof(api)); memset(&api, 0, sizeof(api));
api.type = ZEBRA_ROUTE_BABEL; api.type = ZEBRA_ROUTE_BABEL;
api.flags = 0;
api.message = 0;
api.instance = 0;
api.safi = SAFI_UNICAST; api.safi = SAFI_UNICAST;
api.vrf_id = VRF_DEFAULT; api.vrf_id = VRF_DEFAULT;
api.prefix = quagga_prefix;
SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
if(metric >= KERNEL_INFINITY) { if(metric >= KERNEL_INFINITY) {
api.flags = ZEBRA_FLAG_REJECT; api.flags = ZEBRA_FLAG_REJECT;
api.nexthop_num = 0;
} else { } else {
SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
api.nexthop_num = 1; api.nexthop_num = 1;
api.nexthop = &nexthop_pointer; api_nh->ifindex = ifindex;
nexthop.ifindex = ifindex;
if (IPV4_ADDR_SAME (&nexthop.gate.ipv4, &quagga_prefix.u.prefix4) && switch (family) {
quagga_prefix.prefixlen == 32) { case AF_INET:
nexthop.type = NEXTHOP_TYPE_IFINDEX; uchar_to_inaddr(&api_nh->gate.ipv4, gate);
} else { if (IPV4_ADDR_SAME (&api_nh->gate.ipv4, &quagga_prefix.u.prefix4) &&
nexthop.type = NEXTHOP_TYPE_IPV4_IFINDEX; quagga_prefix.prefixlen == 32) {
api_nh->type = NEXTHOP_TYPE_IFINDEX;
} else {
api_nh->type = NEXTHOP_TYPE_IPV4_IFINDEX;
}
break;
case AF_INET6:
uchar_to_in6addr(&api_nh->gate.ipv6, gate);
/* difference to IPv4: always leave the linklocal as nexthop */
api_nh->type = NEXTHOP_TYPE_IPV6_IFINDEX;
break;
} }
SET_FLAG(api.message, ZAPI_MESSAGE_METRIC); SET_FLAG(api.message, ZAPI_MESSAGE_METRIC);
api.metric = metric; api.metric = metric;
} }
debugf(BABEL_DEBUG_ROUTE, "%s route (ipv4) to zebra", debugf(BABEL_DEBUG_ROUTE, "%s route (%s) to zebra",
add ? "adding" : "removing" ); add ? "adding" : "removing",
return zapi_route (add ? ZEBRA_IPV4_ROUTE_ADD : (family == AF_INET) ? "ipv4" : "ipv6");
ZEBRA_IPV4_ROUTE_DELETE, return zclient_route_send (add ? ZEBRA_ROUTE_ADD : ZEBRA_ROUTE_DELETE,
zclient, &quagga_prefix, NULL, &api); zclient, &api);
}
static int
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 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;
/* 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));
quagga_prefix.family = AF_INET6;
IPV6_ADDR_COPY (&quagga_prefix.u.prefix6, &babel_prefix_addr);
quagga_prefix.prefixlen = plen;
apply_mask(&quagga_prefix);
memset(&api, 0, sizeof(api));
api.type = ZEBRA_ROUTE_BABEL;
api.flags = 0;
api.message = 0;
api.instance = 0;
api.safi = SAFI_UNICAST;
api.vrf_id = VRF_DEFAULT;
if(metric >= KERNEL_INFINITY) {
api.flags = ZEBRA_FLAG_REJECT;
api.nexthop_num = 0;
} else {
SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
api.nexthop_num = 1;
api.nexthop = &nexthop_pointer;
nexthop.ifindex = ifindex;
/* difference to IPv4: always leave the linklocal as nexthop */
nexthop.type = NEXTHOP_TYPE_IPV6_IFINDEX;
SET_FLAG(api.message, ZAPI_MESSAGE_METRIC);
api.metric = metric;
}
debugf(BABEL_DEBUG_ROUTE, "%s route (ipv6) to zebra",
add ? "adding" : "removing" );
return zapi_route (add ? ZEBRA_IPV6_ROUTE_ADD :
ZEBRA_IPV6_ROUTE_DELETE,
zclient, &quagga_prefix, NULL, &api);
} }
int int

View File

@ -391,7 +391,7 @@ parse_packet(const unsigned char *from, struct interface *ifp,
} else if(type == MESSAGE_HELLO) { } else if(type == MESSAGE_HELLO) {
unsigned short seqno, interval; unsigned short seqno, interval;
int changed; int changed;
unsigned int timestamp; unsigned int timestamp = 0;
DO_NTOHS(seqno, message + 4); DO_NTOHS(seqno, message + 4);
DO_NTOHS(interval, message + 6); DO_NTOHS(interval, message + 6);
debugf(BABEL_DEBUG_COMMON,"Received hello %d (%d) from %s on %s.", debugf(BABEL_DEBUG_COMMON,"Received hello %d (%d) from %s on %s.",

View File

@ -43,63 +43,54 @@ static int numxroutes = 0, maxxroutes = 0;
/* Add redistributed route to Babel table. */ /* Add redistributed route to Babel table. */
int int
babel_ipv4_route_add (struct zapi_ipv4 *api, struct prefix_ipv4 *prefix, babel_route_add (struct zapi_route *api)
unsigned int ifindex, struct in_addr *nexthop)
{ {
unsigned char uchar_prefix[16]; unsigned char uchar_prefix[16];
inaddr_to_uchar(uchar_prefix, &prefix->prefix); switch (api->prefix.family) {
debugf(BABEL_DEBUG_ROUTE, "Adding new ipv4 route coming from Zebra."); case AF_INET:
xroute_add_new_route(uchar_prefix, prefix->prefixlen + 96, inaddr_to_uchar(uchar_prefix, &api->prefix.u.prefix4);
api->metric, ifindex, 0, 1); debugf(BABEL_DEBUG_ROUTE, "Adding new ipv4 route coming from Zebra.");
xroute_add_new_route(uchar_prefix, api->prefix.prefixlen + 96,
api->metric, api->nexthops[0].ifindex, 0, 1);
break;
case AF_INET6:
in6addr_to_uchar(uchar_prefix, &api->prefix.u.prefix6);
debugf(BABEL_DEBUG_ROUTE, "Adding new ipv6 route coming from Zebra.");
xroute_add_new_route(uchar_prefix, api->prefix.prefixlen,
api->metric, api->nexthops[0].ifindex, 0, 1);
break;
}
return 0; return 0;
} }
/* Remove redistributed route from Babel table. */ /* Remove redistributed route from Babel table. */
int int
babel_ipv4_route_delete (struct zapi_ipv4 *api, struct prefix_ipv4 *prefix, babel_route_delete (struct zapi_route *api)
unsigned int ifindex)
{ {
unsigned char uchar_prefix[16]; unsigned char uchar_prefix[16];
struct xroute *xroute = NULL; struct xroute *xroute = NULL;
inaddr_to_uchar(uchar_prefix, &prefix->prefix); switch (api->prefix.family) {
xroute = find_xroute(uchar_prefix, prefix->prefixlen + 96); case AF_INET:
if (xroute != NULL) { inaddr_to_uchar(uchar_prefix, &api->prefix.u.prefix4);
debugf(BABEL_DEBUG_ROUTE, "Removing ipv4 route (from zebra)."); xroute = find_xroute(uchar_prefix, api->prefix.prefixlen + 96);
flush_xroute(xroute); if (xroute != NULL) {
debugf(BABEL_DEBUG_ROUTE, "Removing ipv4 route (from zebra).");
flush_xroute(xroute);
}
break;
case AF_INET6:
in6addr_to_uchar(uchar_prefix, &api->prefix.u.prefix6);
xroute = find_xroute(uchar_prefix, api->prefix.prefixlen);
if (xroute != NULL) {
debugf(BABEL_DEBUG_ROUTE, "Removing ipv6 route (from zebra).");
flush_xroute(xroute);
}
break;
} }
return 0;
}
/* Add redistributed route to Babel table. */
int
babel_ipv6_route_add (struct zapi_ipv6 *api, struct prefix_ipv6 *prefix,
unsigned int ifindex, struct in6_addr *nexthop)
{
unsigned char uchar_prefix[16];
in6addr_to_uchar(uchar_prefix, &prefix->prefix);
debugf(BABEL_DEBUG_ROUTE, "Adding new route coming from Zebra.");
xroute_add_new_route(uchar_prefix, prefix->prefixlen, api->metric, ifindex,
0, 1);
return 0;
}
/* Remove redistributed route from Babel table. */
int
babel_ipv6_route_delete (struct zapi_ipv6 *api, struct prefix_ipv6 *prefix,
unsigned int ifindex)
{
unsigned char uchar_prefix[16];
struct xroute *xroute = NULL;
in6addr_to_uchar(uchar_prefix, &prefix->prefix);
xroute = find_xroute(uchar_prefix, prefix->prefixlen);
if (xroute != NULL) {
debugf(BABEL_DEBUG_ROUTE, "Removing route (from zebra).");
flush_xroute(xroute);
}
return 0; return 0;
} }

View File

@ -36,14 +36,8 @@ struct xroute_stream;
struct xroute *find_xroute(const unsigned char *prefix, unsigned char plen); struct xroute *find_xroute(const unsigned char *prefix, unsigned char plen);
void flush_xroute(struct xroute *xroute); void flush_xroute(struct xroute *xroute);
int babel_ipv4_route_add (struct zapi_ipv4 *api, struct prefix_ipv4 *prefix, int babel_route_add (struct zapi_route *api);
unsigned int ifindex, struct in_addr *nexthop); int babel_route_delete (struct zapi_route *api);
int babel_ipv4_route_delete (struct zapi_ipv4 *api, struct prefix_ipv4 *prefix,
unsigned int ifindex);
int babel_ipv6_route_add (struct zapi_ipv6 *api, struct prefix_ipv6 *prefix,
unsigned int ifindex, struct in6_addr *nexthop);
int babel_ipv6_route_delete (struct zapi_ipv6 *api, struct prefix_ipv6 *prefix,
unsigned int ifindex);
int xroutes_estimate(void); int xroutes_estimate(void);
struct xroute_stream *xroute_stream(void); struct xroute_stream *xroute_stream(void);
struct xroute *xroute_stream_next(struct xroute_stream *stream); struct xroute *xroute_stream_next(struct xroute_stream *stream);

View File

@ -72,7 +72,7 @@ struct bgp_attr_encap_subtlv {
unsigned long refcnt; unsigned long refcnt;
uint16_t type; uint16_t type;
uint16_t length; uint16_t length;
uint8_t value[1]; /* will be extended */ uint8_t value[0]; /* will be extended */
}; };
#if ENABLE_BGP_VNC #if ENABLE_BGP_VNC

View File

@ -219,9 +219,6 @@ static __attribute__((__noreturn__)) void bgp_exit(int status)
memset(bm, 0, sizeof(*bm)); memset(bm, 0, sizeof(*bm));
frr_fini(); frr_fini();
if (bgp_debug_count())
log_memstats_stderr("bgpd");
exit(status); exit(status);
} }

View File

@ -20,6 +20,7 @@
*/ */
#include <zebra.h> #include <zebra.h>
#include <math.h>
#include "prefix.h" #include "prefix.h"
#include "linklist.h" #include "linklist.h"
@ -2087,7 +2088,7 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_node *rn,
* to do this upon changes to best path except of the label index * to do this upon changes to best path except of the label index
* changes. * changes.
*/ */
if (safi == SAFI_UNICAST) { if (bgp->allocate_mpls_labels[afi][safi]) {
if (new_select) { if (new_select) {
if (!old_select if (!old_select
|| bgp_label_index_differs(new_select, old_select) || bgp_label_index_differs(new_select, old_select)
@ -2108,8 +2109,11 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_node *rn,
} else } else
bgp_register_for_label(rn, new_select); bgp_register_for_label(rn, new_select);
} }
} else if (CHECK_FLAG(rn->flags, BGP_NODE_REGISTERED_FOR_LABEL)) } else if (CHECK_FLAG(rn->flags, BGP_NODE_REGISTERED_FOR_LABEL)) {
bgp_unregister_for_label(rn); bgp_unregister_for_label(rn);
}
} else if (CHECK_FLAG(rn->flags, BGP_NODE_REGISTERED_FOR_LABEL)) {
bgp_unregister_for_label(rn);
} }
/* If best route remains the same and this is not due to user-initiated /* If best route remains the same and this is not due to user-initiated
@ -6153,8 +6157,7 @@ DEFUN (no_ipv6_aggregate_address,
/* Redistribute route treatment. */ /* Redistribute route treatment. */
void bgp_redistribute_add(struct bgp *bgp, struct prefix *p, void bgp_redistribute_add(struct bgp *bgp, struct prefix *p,
const struct in_addr *nexthop, const union g_addr *nexthop, unsigned int ifindex,
const struct in6_addr *nexthop6, unsigned int ifindex,
u_int32_t metric, u_char type, u_short instance, u_int32_t metric, u_char type, u_short instance,
route_tag_t tag) route_tag_t tag)
{ {
@ -6170,14 +6173,17 @@ void bgp_redistribute_add(struct bgp *bgp, struct prefix *p,
/* Make default attribute. */ /* Make default attribute. */
bgp_attr_default_set(&attr, BGP_ORIGIN_INCOMPLETE); bgp_attr_default_set(&attr, BGP_ORIGIN_INCOMPLETE);
if (nexthop) if (nexthop) {
attr.nexthop = *nexthop; switch (p->family) {
attr.nh_ifindex = ifindex; case AF_INET:
attr.nexthop = nexthop->ipv4;
if (nexthop6) { break;
attr.mp_nexthop_global = *nexthop6; case AF_INET6:
attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL; attr.mp_nexthop_global = nexthop->ipv6;
attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
}
} }
attr.nh_ifindex = ifindex;
attr.med = metric; attr.med = metric;
attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC); attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
@ -8087,7 +8093,8 @@ static int bgp_show_community_list(struct vty *vty, struct bgp *bgp,
static int bgp_show_prefix_longer(struct vty *vty, struct bgp *bgp, static int bgp_show_prefix_longer(struct vty *vty, struct bgp *bgp,
const char *prefix, afi_t afi, safi_t safi, const char *prefix, afi_t afi, safi_t safi,
enum bgp_show_type type); enum bgp_show_type type);
static int bgp_show_regexp(struct vty *vty, const char *regstr, afi_t afi, static int bgp_show_regexp(struct vty *vty, struct bgp *bgp,
const char *regstr, afi_t afi,
safi_t safi, enum bgp_show_type type); safi_t safi, enum bgp_show_type type);
static int bgp_show_community(struct vty *vty, struct bgp *bgp, static int bgp_show_community(struct vty *vty, struct bgp *bgp,
const char *comstr, int exact, afi_t afi, const char *comstr, int exact, afi_t afi,
@ -8905,32 +8912,28 @@ DEFUN (show_ip_bgp_large_community,
static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi, static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
safi_t safi); safi_t safi);
/* BGP route print out function. */
/* BGP route print out function without JSON */
DEFUN (show_ip_bgp, DEFUN (show_ip_bgp,
show_ip_bgp_cmd, show_ip_bgp_cmd,
"show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]]\ "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]]\
[<\ <dampening <parameters>\
cidr-only\ |route-map WORD\
|dampening <flap-statistics|dampened-paths|parameters>\ |prefix-list WORD\
|route-map WORD\ |filter-list WORD\
|prefix-list WORD\ |statistics\
|filter-list WORD\ |community <AA:NN|local-AS|no-advertise|no-export|graceful-shutdown> [exact-match]\
|statistics\ |community-list <(1-500)|WORD> [exact-match]\
|community [<AA:NN|local-AS|no-advertise|no-export|graceful-shutdown> [exact-match]]\ |A.B.C.D/M longer-prefixes\
|community-list <(1-500)|WORD> [exact-match]\ |X:X::X:X/M longer-prefixes\
|A.B.C.D/M longer-prefixes\ >",
|X:X::X:X/M longer-prefixes>\
] [json]",
SHOW_STR SHOW_STR
IP_STR IP_STR
BGP_STR BGP_STR
BGP_INSTANCE_HELP_STR BGP_INSTANCE_HELP_STR
BGP_AFI_HELP_STR BGP_AFI_HELP_STR
BGP_SAFI_WITH_LABEL_HELP_STR BGP_SAFI_WITH_LABEL_HELP_STR
"Display only routes with non-natural netmasks\n"
"Display detailed information about dampening\n" "Display detailed information about dampening\n"
"Display flap statistics of routes\n"
"Display paths suppressed due to dampening\n"
"Display detail of configured dampening parameters\n" "Display detail of configured dampening parameters\n"
"Display routes matching the route-map\n" "Display routes matching the route-map\n"
"A route-map to match on\n" "A route-map to match on\n"
@ -8953,13 +8956,11 @@ DEFUN (show_ip_bgp,
"IPv4 prefix\n" "IPv4 prefix\n"
"Display route and more specific routes\n" "Display route and more specific routes\n"
"IPv6 prefix\n" "IPv6 prefix\n"
"Display route and more specific routes\n" "Display route and more specific routes\n")
JSON_STR)
{ {
afi_t afi = AFI_IP6; afi_t afi = AFI_IP6;
safi_t safi = SAFI_UNICAST; safi_t safi = SAFI_UNICAST;
int exact_match = 0; int exact_match = 0;
enum bgp_show_type sh_type = bgp_show_type_normal;
struct bgp *bgp = NULL; struct bgp *bgp = NULL;
int idx = 0; int idx = 0;
int idx_community_type = 0; int idx_community_type = 0;
@ -8969,23 +8970,8 @@ DEFUN (show_ip_bgp,
if (!idx) if (!idx)
return CMD_WARNING; return CMD_WARNING;
int uj = use_json(argc, argv);
if (uj)
argc--;
if (argv_find(argv, argc, "cidr-only", &idx))
return bgp_show(vty, bgp, afi, safi, bgp_show_type_cidr_only,
NULL, uj);
if (argv_find(argv, argc, "dampening", &idx)) { if (argv_find(argv, argc, "dampening", &idx)) {
if (argv_find(argv, argc, "dampened-paths", &idx)) if (argv_find(argv, argc, "parameters", &idx))
return bgp_show(vty, bgp, afi, safi,
bgp_show_type_dampend_paths, NULL, uj);
else if (argv_find(argv, argc, "flap-statistics", &idx))
return bgp_show(vty, bgp, afi, safi,
bgp_show_type_flap_statistics, NULL,
uj);
else if (argv_find(argv, argc, "parameters", &idx))
return bgp_show_dampening_parameters(vty, afi, safi); return bgp_show_dampening_parameters(vty, afi, safi);
} }
@ -9017,10 +9003,6 @@ DEFUN (show_ip_bgp,
return bgp_show_community(vty, bgp, argv[idx_community_type]->arg, return bgp_show_community(vty, bgp, argv[idx_community_type]->arg,
exact_match, afi, safi); exact_match, afi, safi);
} }
/* show all communities */
else
return bgp_show(vty, bgp, afi, safi,
bgp_show_type_community_all, NULL, uj);
} }
if (argv_find(argv, argc, "community-list", &idx)) { if (argv_find(argv, argc, "community-list", &idx)) {
@ -9037,6 +9019,66 @@ DEFUN (show_ip_bgp,
safi, safi,
bgp_show_type_prefix_longer); bgp_show_type_prefix_longer);
return CMD_WARNING;
}
/* BGP route print out function with JSON */
DEFUN (show_ip_bgp_json,
show_ip_bgp_json_cmd,
"show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]]\
[<\
cidr-only\
|dampening <flap-statistics|dampened-paths>\
|community \
>] [json]",
SHOW_STR
IP_STR
BGP_STR
BGP_INSTANCE_HELP_STR
BGP_AFI_HELP_STR
BGP_SAFI_WITH_LABEL_HELP_STR
"Display only routes with non-natural netmasks\n"
"Display detailed information about dampening\n"
"Display flap statistics of routes\n"
"Display paths suppressed due to dampening\n"
"Display routes matching the communities\n"
JSON_STR)
{
afi_t afi = AFI_IP6;
safi_t safi = SAFI_UNICAST;
enum bgp_show_type sh_type = bgp_show_type_normal;
struct bgp *bgp = NULL;
int idx = 0;
bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
&bgp);
if (!idx)
return CMD_WARNING;
int uj = use_json(argc, argv);
if (uj)
argc--;
if (argv_find(argv, argc, "cidr-only", &idx))
return bgp_show(vty, bgp, afi, safi, bgp_show_type_cidr_only,
NULL, uj);
if (argv_find(argv, argc, "dampening", &idx)) {
if (argv_find(argv, argc, "dampened-paths", &idx))
return bgp_show(vty, bgp, afi, safi,
bgp_show_type_dampend_paths, NULL, uj);
else if (argv_find(argv, argc, "flap-statistics", &idx))
return bgp_show(vty, bgp, afi, safi,
bgp_show_type_flap_statistics, NULL,
uj);
}
if (argv_find(argv, argc, "community", &idx)) {
/* show all communities */
return bgp_show(vty, bgp, afi, safi,
bgp_show_type_community_all, NULL, uj);
}
if (safi == SAFI_MPLS_VPN) if (safi == SAFI_MPLS_VPN)
return bgp_show_mpls_vpn(vty, afi, NULL, bgp_show_type_normal, return bgp_show_mpls_vpn(vty, afi, NULL, bgp_show_type_normal,
NULL, 0, uj); NULL, 0, uj);
@ -9146,7 +9188,7 @@ DEFUN (show_ip_bgp_regexp,
idx++; idx++;
char *regstr = argv_concat(argv, argc, idx); char *regstr = argv_concat(argv, argc, idx);
int rc = bgp_show_regexp(vty, (const char *)regstr, afi, safi, int rc = bgp_show_regexp(vty, bgp, (const char *)regstr, afi, safi,
bgp_show_type_regexp); bgp_show_type_regexp);
XFREE(MTYPE_TMP, regstr); XFREE(MTYPE_TMP, regstr);
return rc; return rc;
@ -9181,7 +9223,8 @@ DEFUN (show_ip_bgp_instance_all,
return CMD_SUCCESS; return CMD_SUCCESS;
} }
static int bgp_show_regexp(struct vty *vty, const char *regstr, afi_t afi, static int bgp_show_regexp(struct vty *vty, struct bgp *bgp,
const char *regstr, afi_t afi,
safi_t safi, enum bgp_show_type type) safi_t safi, enum bgp_show_type type)
{ {
regex_t *regex; regex_t *regex;
@ -9193,7 +9236,7 @@ static int bgp_show_regexp(struct vty *vty, const char *regstr, afi_t afi,
return CMD_WARNING; return CMD_WARNING;
} }
rc = bgp_show(vty, NULL, afi, safi, type, regex, 0); rc = bgp_show(vty, bgp, afi, safi, type, regex, 0);
bgp_regex_free(regex); bgp_regex_free(regex);
return rc; return rc;
} }
@ -9399,6 +9442,7 @@ static const char *table_stats_strs[] = {
struct bgp_table_stats { struct bgp_table_stats {
struct bgp_table *table; struct bgp_table *table;
unsigned long long counts[BGP_STATS_MAX]; unsigned long long counts[BGP_STATS_MAX];
double total_space;
}; };
#if 0 #if 0
@ -9467,8 +9511,8 @@ static int bgp_table_stats_walker(struct thread *t)
ts->counts[BGP_STATS_UNAGGREGATEABLE]++; ts->counts[BGP_STATS_UNAGGREGATEABLE]++;
/* announced address space */ /* announced address space */
if (space) if (space)
ts->counts[BGP_STATS_SPACE] += ts->total_space += pow(2.0,
1 << (space - rn->p.prefixlen); space - rn->p.prefixlen);
} else if (prn->info) } else if (prn->info)
ts->counts[BGP_STATS_MAX_AGGREGATEABLE]++; ts->counts[BGP_STATS_MAX_AGGREGATEABLE]++;
@ -9578,31 +9622,26 @@ static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
break; break;
case BGP_STATS_SPACE: case BGP_STATS_SPACE:
vty_out(vty, "%-30s: ", table_stats_strs[i]); vty_out(vty, "%-30s: ", table_stats_strs[i]);
vty_out(vty, "%12llu\n", ts.counts[i]); vty_out(vty, "%12g\n", ts.total_space);
if (ts.counts[BGP_STATS_MAXBITLEN] < 9)
break; if (afi == AFI_IP6) {
vty_out(vty, "%30s: ", "%% announced "); vty_out(vty, "%30s: ", "/32 equivalent ");
vty_out(vty, "%12.2f\n", vty_out(vty, "%12g\n",
100 * (float)ts.counts[BGP_STATS_SPACE] ts.total_space * pow(2.0, -128+32));
/ (float)((uint64_t)1UL vty_out(vty, "%30s: ", "/48 equivalent ");
<< ts.counts vty_out(vty, "%12g\n",
[BGP_STATS_MAXBITLEN])); ts.total_space * pow(2.0, -128+48));
vty_out(vty, "%30s: ", "/8 equivalent "); } else {
vty_out(vty, "%12.2f\n", vty_out(vty, "%30s: ", "% announced ");
(float)ts.counts[BGP_STATS_SPACE] vty_out(vty, "%12.2f\n",
/ (float)(1UL ts.total_space * 100. * pow(2.0, -32));
<< (ts.counts vty_out(vty, "%30s: ", "/8 equivalent ");
[BGP_STATS_MAXBITLEN] vty_out(vty, "%12.2f\n",
- 8))); ts.total_space * pow(2.0, -32+8));
if (ts.counts[BGP_STATS_MAXBITLEN] < 25) vty_out(vty, "%30s: ", "/24 equivalent ");
break; vty_out(vty, "%12.2f\n",
vty_out(vty, "%30s: ", "/24 equivalent "); ts.total_space * pow(2.0, -32+24));
vty_out(vty, "%12.2f", }
(float)ts.counts[BGP_STATS_SPACE]
/ (float)(1UL
<< (ts.counts
[BGP_STATS_MAXBITLEN]
- 24)));
break; break;
default: default:
vty_out(vty, "%-30s: ", table_stats_strs[i]); vty_out(vty, "%-30s: ", table_stats_strs[i]);
@ -11332,6 +11371,7 @@ void bgp_route_init(void)
/* IPv4 labeled-unicast configuration. */ /* IPv4 labeled-unicast configuration. */
install_element(VIEW_NODE, &show_ip_bgp_instance_all_cmd); install_element(VIEW_NODE, &show_ip_bgp_instance_all_cmd);
install_element(VIEW_NODE, &show_ip_bgp_cmd); install_element(VIEW_NODE, &show_ip_bgp_cmd);
install_element(VIEW_NODE, &show_ip_bgp_json_cmd);
install_element(VIEW_NODE, &show_ip_bgp_route_cmd); install_element(VIEW_NODE, &show_ip_bgp_route_cmd);
install_element(VIEW_NODE, &show_ip_bgp_regexp_cmd); install_element(VIEW_NODE, &show_ip_bgp_regexp_cmd);

View File

@ -22,6 +22,7 @@
#define _QUAGGA_BGP_ROUTE_H #define _QUAGGA_BGP_ROUTE_H
#include "queue.h" #include "queue.h"
#include "nexthop.h"
#include "bgp_table.h" #include "bgp_table.h"
struct bgp_nexthop_cache; struct bgp_nexthop_cache;
@ -326,8 +327,7 @@ extern int bgp_nlri_parse_ip(struct peer *, struct attr *, struct bgp_nlri *);
extern int bgp_maximum_prefix_overflow(struct peer *, afi_t, safi_t, int); extern int bgp_maximum_prefix_overflow(struct peer *, afi_t, safi_t, int);
extern void bgp_redistribute_add(struct bgp *, struct prefix *, extern void bgp_redistribute_add(struct bgp *, struct prefix *,
const struct in_addr *, const union g_addr *, unsigned int ifindex,
const struct in6_addr *, unsigned int ifindex,
u_int32_t, u_char, u_short, route_tag_t); u_int32_t, u_char, u_short, route_tag_t);
extern void bgp_redistribute_delete(struct bgp *, struct prefix *, u_char, extern void bgp_redistribute_delete(struct bgp *, struct prefix *, u_char,
u_short); u_short);

View File

@ -7081,26 +7081,6 @@ static int bgp_show_summary(struct vty *vty, struct bgp *bgp, int afi, int safi,
return CMD_SUCCESS; return CMD_SUCCESS;
} }
/*
* Return if we have a peer configured to use this afi/safi
*/
static int bgp_show_summary_afi_safi_peer_exists(struct bgp *bgp, int afi,
int safi)
{
struct listnode *node;
struct peer *peer;
for (ALL_LIST_ELEMENTS_RO(bgp->peer, node, peer)) {
if (!CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE))
continue;
if (peer->afc[afi][safi])
return 1;
}
return 0;
}
static void bgp_show_summary_afi_safi(struct vty *vty, struct bgp *bgp, int afi, static void bgp_show_summary_afi_safi(struct vty *vty, struct bgp *bgp, int afi,
int safi, u_char use_json, int safi, u_char use_json,
json_object *json) json_object *json)
@ -7119,8 +7099,7 @@ static void bgp_show_summary_afi_safi(struct vty *vty, struct bgp *bgp, int afi,
if (safi_wildcard) if (safi_wildcard)
safi = 1; /* SAFI_UNICAST */ safi = 1; /* SAFI_UNICAST */
while (safi < SAFI_MAX) { while (safi < SAFI_MAX) {
if (bgp_show_summary_afi_safi_peer_exists(bgp, afi, if (bgp_afi_safi_peer_exists(bgp, afi, safi)) {
safi)) {
json_output = true; json_output = true;
if (is_wildcard) { if (is_wildcard) {
/* /*

View File

@ -58,11 +58,6 @@
/* All information about zebra. */ /* All information about zebra. */
struct zclient *zclient = NULL; struct zclient *zclient = NULL;
/* Growable buffer for nexthops sent to zebra */
struct stream *bgp_nexthop_buf = NULL;
struct stream *bgp_ifindices_buf = NULL;
struct stream *bgp_label_buf = NULL;
/* These array buffers are used in making a copy of the attributes for /* These array buffers are used in making a copy of the attributes for
route-map apply. Arrays are being used here to minimize mallocs and route-map apply. Arrays are being used here to minimize mallocs and
frees for the temporary copy of the attributes. frees for the temporary copy of the attributes.
@ -559,75 +554,36 @@ static int bgp_interface_vrf_update(int command, struct zclient *zclient,
} }
/* Zebra route add and delete treatment. */ /* Zebra route add and delete treatment. */
static int zebra_read_ipv4(int command, struct zclient *zclient, static int zebra_read_route(int command, struct zclient *zclient,
zebra_size_t length, vrf_id_t vrf_id) zebra_size_t length, vrf_id_t vrf_id)
{ {
struct stream *s; struct zapi_route api;
struct zapi_ipv4 api; union g_addr nexthop;
struct in_addr nexthop;
struct prefix_ipv4 p;
unsigned int ifindex; unsigned int ifindex;
int i; int add, i;
struct bgp *bgp; struct bgp *bgp;
bgp = bgp_lookup_by_vrf_id(vrf_id); bgp = bgp_lookup_by_vrf_id(vrf_id);
if (!bgp) if (!bgp)
return 0; return 0;
s = zclient->ibuf; if (zapi_route_decode(zclient->ibuf, &api) < 0)
nexthop.s_addr = 0; return -1;
/* Type, flags, message. */ /* we completely ignore srcdest routes for now. */
api.type = stream_getc(s); if (CHECK_FLAG(api.message, ZAPI_MESSAGE_SRCPFX))
api.instance = stream_getw(s); return 0;
api.flags = stream_getl(s);
api.message = stream_getc(s);
/* IPv4 prefix. */ /* ignore link-local address. */
memset(&p, 0, sizeof(struct prefix_ipv4)); if (api.prefix.family == AF_INET6
p.family = AF_INET; && IN6_IS_ADDR_LINKLOCAL(&api.prefix.u.prefix6))
p.prefixlen = MIN(IPV4_MAX_PREFIXLEN, stream_getc(s)); return 0;
stream_get(&p.prefix, s, PSIZE(p.prefixlen));
/* Nexthop, ifindex, distance, metric. */ nexthop = api.nexthops[0].gate;
if (CHECK_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP)) { ifindex = api.nexthops[0].ifindex;
api.nexthop_num = stream_getc(s);
nexthop.s_addr = stream_get_ipv4(s);
}
if (CHECK_FLAG(api.message, ZAPI_MESSAGE_IFINDEX)) {
api.ifindex_num = stream_getc(s);
ifindex = stream_getl(s); /* ifindex, unused */
} else {
ifindex = 0;
}
if (CHECK_FLAG(api.message, ZAPI_MESSAGE_DISTANCE))
api.distance = stream_getc(s);
if (CHECK_FLAG(api.message, ZAPI_MESSAGE_METRIC))
api.metric = stream_getl(s);
else
api.metric = 0;
if (CHECK_FLAG(api.message, ZAPI_MESSAGE_TAG))
api.tag = stream_getl(s);
else
api.tag = 0;
if (command == ZEBRA_REDISTRIBUTE_IPV4_ADD) {
if (bgp_debug_zebra((struct prefix *)&p)) {
char buf[2][INET_ADDRSTRLEN];
zlog_debug(
"Rx IPv4 route add VRF %u %s[%d] %s/%d nexthop %s metric %u tag %" ROUTE_TAG_PRI,
vrf_id, zebra_route_string(api.type),
api.instance, inet_ntop(AF_INET, &p.prefix,
buf[0], sizeof(buf[0])),
p.prefixlen, inet_ntop(AF_INET, &nexthop,
buf[1], sizeof(buf[1])),
api.metric, api.tag);
}
add = (command == ZEBRA_REDISTRIBUTE_ROUTE_ADD);
if (add) {
/* /*
* The ADD message is actually an UPDATE and there is no * The ADD message is actually an UPDATE and there is no
* explicit DEL * explicit DEL
@ -639,156 +595,30 @@ static int zebra_read_ipv4(int command, struct zclient *zclient,
*/ */
for (i = 0; i < ZEBRA_ROUTE_MAX; i++) { for (i = 0; i < ZEBRA_ROUTE_MAX; i++) {
if (i != api.type) if (i != api.type)
bgp_redistribute_delete(bgp, bgp_redistribute_delete(bgp, &api.prefix, i,
(struct prefix *)&p, i,
api.instance); api.instance);
} }
/* Now perform the add/update. */ /* Now perform the add/update. */
bgp_redistribute_add(bgp, (struct prefix *)&p, &nexthop, NULL, bgp_redistribute_add(bgp, &api.prefix, &nexthop, ifindex,
ifindex, api.metric, api.type, api.metric, api.type, api.instance,
api.instance, api.tag); api.tag);
} else if (command == ZEBRA_REDISTRIBUTE_IPV4_DEL) {
if (bgp_debug_zebra((struct prefix *)&p)) {
char buf[2][INET_ADDRSTRLEN];
zlog_debug(
"Rx IPv4 route delete VRF %u %s[%d] %s/%d "
"nexthop %s metric %u tag %" ROUTE_TAG_PRI,
vrf_id, zebra_route_string(api.type),
api.instance, inet_ntop(AF_INET, &p.prefix,
buf[0], sizeof(buf[0])),
p.prefixlen, inet_ntop(AF_INET, &nexthop,
buf[1], sizeof(buf[1])),
api.metric, api.tag);
}
bgp_redistribute_delete(bgp, (struct prefix *)&p, api.type,
api.instance);
}
return 0;
}
/* Zebra route add and delete treatment. */
static int zebra_read_ipv6(int command, struct zclient *zclient,
zebra_size_t length, vrf_id_t vrf_id)
{
struct stream *s;
struct zapi_ipv6 api;
struct in6_addr nexthop;
struct prefix_ipv6 p, src_p;
unsigned int ifindex;
int i;
struct bgp *bgp;
bgp = bgp_lookup_by_vrf_id(vrf_id);
if (!bgp)
return 0;
s = zclient->ibuf;
memset(&nexthop, 0, sizeof(struct in6_addr));
/* Type, flags, message. */
api.type = stream_getc(s);
api.instance = stream_getw(s);
api.flags = stream_getl(s);
api.message = stream_getc(s);
/* IPv6 prefix. */
memset(&p, 0, sizeof(struct prefix_ipv6));
p.family = AF_INET6;
p.prefixlen = MIN(IPV6_MAX_PREFIXLEN, stream_getc(s));
stream_get(&p.prefix, s, PSIZE(p.prefixlen));
memset(&src_p, 0, sizeof(struct prefix_ipv6));
src_p.family = AF_INET6;
if (CHECK_FLAG(api.message, ZAPI_MESSAGE_SRCPFX)) {
src_p.prefixlen = stream_getc(s);
stream_get(&src_p.prefix, s, PSIZE(src_p.prefixlen));
}
if (src_p.prefixlen)
/* we completely ignore srcdest routes for now. */
return 0;
/* Nexthop, ifindex, distance, metric. */
if (CHECK_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP)) {
api.nexthop_num = stream_getc(s);
stream_get(&nexthop, s, 16);
}
if (CHECK_FLAG(api.message, ZAPI_MESSAGE_IFINDEX)) {
api.ifindex_num = stream_getc(s);
ifindex = stream_getl(s); /* ifindex, unused */
} else { } else {
ifindex = 0; bgp_redistribute_delete(bgp, &api.prefix, api.type,
api.instance);
} }
if (CHECK_FLAG(api.message, ZAPI_MESSAGE_DISTANCE)) if (bgp_debug_zebra(&api.prefix)) {
api.distance = stream_getc(s); char buf[2][PREFIX_STRLEN];
else
api.distance = 0;
if (CHECK_FLAG(api.message, ZAPI_MESSAGE_METRIC)) prefix2str(&api.prefix, buf[0], sizeof(buf[0]));
api.metric = stream_getl(s); inet_ntop(api.prefix.family, &nexthop, buf[1], sizeof(buf[1]));
else zlog_debug(
api.metric = 0; "Rx route %s VRF %u %s[%d] %s "
"nexthop %s metric %u tag %" ROUTE_TAG_PRI,
if (CHECK_FLAG(api.message, ZAPI_MESSAGE_TAG)) (add) ? "add" : "delete", vrf_id,
api.tag = stream_getl(s); zebra_route_string(api.type), api.instance, buf[0],
else buf[1], api.metric, api.tag);
api.tag = 0;
/* Simply ignore link-local address. */
if (IN6_IS_ADDR_LINKLOCAL(&p.prefix))
return 0;
if (command == ZEBRA_REDISTRIBUTE_IPV6_ADD) {
if (bgp_debug_zebra((struct prefix *)&p)) {
char buf[2][INET6_ADDRSTRLEN];
zlog_debug(
"Rx IPv6 route add VRF %u %s[%d] %s/%d nexthop %s metric %u tag %" ROUTE_TAG_PRI,
vrf_id, zebra_route_string(api.type),
api.instance, inet_ntop(AF_INET6, &p.prefix,
buf[0], sizeof(buf[0])),
p.prefixlen, inet_ntop(AF_INET, &nexthop,
buf[1], sizeof(buf[1])),
api.metric, api.tag);
}
/*
* The ADD message is actually an UPDATE and there is no
* explicit DEL
* for a prior redistributed route, if any. So, perform an
* implicit
* DEL processing for the same redistributed route from any
* other
* source type.
*/
for (i = 0; i < ZEBRA_ROUTE_MAX; i++) {
if (i != api.type)
bgp_redistribute_delete(bgp,
(struct prefix *)&p, i,
api.instance);
}
bgp_redistribute_add(bgp, (struct prefix *)&p, NULL, &nexthop,
ifindex, api.metric, api.type,
api.instance, api.tag);
} else if (command == ZEBRA_REDISTRIBUTE_IPV6_DEL) {
if (bgp_debug_zebra((struct prefix *)&p)) {
char buf[2][INET6_ADDRSTRLEN];
zlog_debug(
"Rx IPv6 route delete VRF %u %s[%d] %s/%d "
"nexthop %s metric %u tag %" ROUTE_TAG_PRI,
vrf_id, zebra_route_string(api.type),
api.instance, inet_ntop(AF_INET6, &p.prefix,
buf[0], sizeof(buf[0])),
p.prefixlen, inet_ntop(AF_INET6, &nexthop,
buf[1], sizeof(buf[1])),
api.metric, api.tag);
}
bgp_redistribute_delete(bgp, (struct prefix *)&p, api.type,
api.instance);
} }
return 0; return 0;
@ -1153,7 +983,11 @@ void bgp_zebra_announce(struct bgp_node *rn, struct prefix *p,
struct bgp_info *info, struct bgp *bgp, afi_t afi, struct bgp_info *info, struct bgp *bgp, afi_t afi,
safi_t safi) safi_t safi)
{ {
u_int32_t flags; struct zapi_route api;
struct zapi_nexthop *api_nh;
int nh_family;
int valid_nh_count = 0;
int has_valid_label = 0;
u_char distance; u_char distance;
struct peer *peer; struct peer *peer;
struct bgp_info *mpinfo; struct bgp_info *mpinfo;
@ -1169,18 +1003,17 @@ void bgp_zebra_announce(struct bgp_node *rn, struct prefix *p,
if (!bgp_install_info_to_zebra(bgp)) if (!bgp_install_info_to_zebra(bgp))
return; return;
if ((p->family == AF_INET
&& !vrf_bitmap_check(zclient->redist[AFI_IP][ZEBRA_ROUTE_BGP],
bgp->vrf_id))
|| (p->family == AF_INET6
&& !vrf_bitmap_check(zclient->redist[AFI_IP6][ZEBRA_ROUTE_BGP],
bgp->vrf_id)))
return;
if (bgp->main_zebra_update_hold) if (bgp->main_zebra_update_hold)
return; return;
flags = 0; /* Make Zebra API structure. */
memset(&api, 0, sizeof(api));
api.vrf_id = bgp->vrf_id;
api.type = ZEBRA_ROUTE_BGP;
api.safi = safi;
api.prefix = *p;
SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
peer = info->peer; peer = info->peer;
tag = info->attr->tag; tag = info->attr->tag;
@ -1189,40 +1022,39 @@ void bgp_zebra_announce(struct bgp_node *rn, struct prefix *p,
* in * in
* the RIB */ * the RIB */
if (info->sub_type == BGP_ROUTE_AGGREGATE) if (info->sub_type == BGP_ROUTE_AGGREGATE)
SET_FLAG(flags, ZEBRA_FLAG_BLACKHOLE); SET_FLAG(api.flags, ZEBRA_FLAG_BLACKHOLE);
if (peer->sort == BGP_PEER_IBGP || peer->sort == BGP_PEER_CONFED if (peer->sort == BGP_PEER_IBGP || peer->sort == BGP_PEER_CONFED
|| info->sub_type == BGP_ROUTE_AGGREGATE) { || info->sub_type == BGP_ROUTE_AGGREGATE) {
SET_FLAG(flags, ZEBRA_FLAG_IBGP); SET_FLAG(api.flags, ZEBRA_FLAG_IBGP);
SET_FLAG(flags, ZEBRA_FLAG_INTERNAL); SET_FLAG(api.flags, ZEBRA_FLAG_INTERNAL);
} }
if ((peer->sort == BGP_PEER_EBGP && peer->ttl != 1) if ((peer->sort == BGP_PEER_EBGP && peer->ttl != 1)
|| CHECK_FLAG(peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK) || CHECK_FLAG(peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK)
|| bgp_flag_check(bgp, BGP_FLAG_DISABLE_NH_CONNECTED_CHK)) || bgp_flag_check(bgp, BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
SET_FLAG(flags, ZEBRA_FLAG_INTERNAL); SET_FLAG(api.flags, ZEBRA_FLAG_INTERNAL);
if (p->family == AF_INET && !BGP_ATTR_NEXTHOP_AFI_IP6(info->attr)) { /* Get nexthop address-family */
struct zapi_ipv4 api; if (p->family == AF_INET && !BGP_ATTR_NEXTHOP_AFI_IP6(info->attr))
struct in_addr *nexthop; nh_family = AF_INET;
char buf[2][INET_ADDRSTRLEN]; else if (p->family == AF_INET6
int valid_nh_count = 0; || (p->family == AF_INET
int has_valid_label = 0; && BGP_ATTR_NEXTHOP_AFI_IP6(info->attr)))
nh_family = AF_INET6;
else
return;
/* resize nexthop buffer size if necessary */ if (bgp->table_map[afi][safi].name)
stream_reset(bgp_nexthop_buf); BGP_INFO_ATTR_BUF_INIT();
nexthop = NULL;
stream_reset(bgp_label_buf); /* Metric is currently based on the best-path only */
metric = info->attr->med;
for (mpinfo = info; mpinfo; mpinfo = bgp_info_mpath_next(mpinfo)) {
if (nh_family == AF_INET) {
struct in_addr *nexthop;
if (bgp->table_map[afi][safi].name)
BGP_INFO_ATTR_BUF_INIT();
/* Metric is currently based on the best-path only */
metric = info->attr->med;
for (mpinfo = info; mpinfo;
mpinfo = bgp_info_mpath_next(mpinfo)) {
nexthop = NULL; nexthop = NULL;
if (bgp->table_map[afi][safi].name) { if (bgp->table_map[afi][safi].name) {
@ -1234,8 +1066,6 @@ void bgp_zebra_announce(struct bgp_node *rn, struct prefix *p,
bgp->table_map[afi][safi].map, p, bgp->table_map[afi][safi].map, p,
info_cp)) { info_cp)) {
if (mpinfo == info) { if (mpinfo == info) {
/* Metric is currently based on
* the best-path only */
metric = info_cp->attr->med; metric = info_cp->attr->med;
tag = info_cp->attr->tag; tag = info_cp->attr->tag;
} }
@ -1248,118 +1078,13 @@ void bgp_zebra_announce(struct bgp_node *rn, struct prefix *p,
if (nexthop == NULL) if (nexthop == NULL)
continue; continue;
stream_put(bgp_nexthop_buf, &nexthop, api_nh = &api.nexthops[valid_nh_count];
sizeof(struct in_addr *)); api_nh->gate.ipv4 = *nexthop;
if (mpinfo->extra api_nh->type = NEXTHOP_TYPE_IPV4;
&& bgp_is_valid_label(&mpinfo->extra->label)) {
has_valid_label = 1;
label = label_pton(&mpinfo->extra->label);
stream_put(bgp_label_buf, &label,
sizeof(mpls_label_t));
}
valid_nh_count++;
}
api.vrf_id = bgp->vrf_id;
api.flags = flags;
api.type = ZEBRA_ROUTE_BGP;
api.instance = 0;
api.message = 0;
api.safi = safi;
SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
if (has_valid_label)
SET_FLAG(api.message, ZAPI_MESSAGE_LABEL);
/* Note that this currently only applies to Null0 routes for
* aggregates.
* ZEBRA_FLAG_BLACKHOLE signals zapi_ipv4_route to encode a
* special
* BLACKHOLE nexthop. We want to set api.nexthop_num to zero
* since we
* do not want to also encode the 0.0.0.0 nexthop for the
* aggregate route.
*/
if (CHECK_FLAG(flags, ZEBRA_FLAG_BLACKHOLE))
api.nexthop_num = 0;
else
api.nexthop_num = valid_nh_count;
api.nexthop = (struct in_addr **)STREAM_DATA(bgp_nexthop_buf);
if (has_valid_label) {
api.label_num = valid_nh_count;
api.label = (unsigned int *)STREAM_DATA(bgp_label_buf);
} else { } else {
api.label_num = 0; ifindex_t ifindex;
api.label = NULL; struct in6_addr *nexthop;
}
api.ifindex_num = 0;
SET_FLAG(api.message, ZAPI_MESSAGE_METRIC);
api.metric = metric;
api.tag = 0;
if (tag) {
SET_FLAG(api.message, ZAPI_MESSAGE_TAG);
api.tag = tag;
}
distance = bgp_distance_apply(p, info, afi, safi, bgp);
if (distance) {
SET_FLAG(api.message, ZAPI_MESSAGE_DISTANCE);
api.distance = distance;
}
if (bgp_debug_zebra(p)) {
int i;
char label_buf[20];
zlog_debug(
"Tx IPv4 route %s VRF %u %s/%d metric %u tag %" ROUTE_TAG_PRI
" count %d",
(valid_nh_count ? "add" : "delete"),
bgp->vrf_id, inet_ntop(AF_INET, &p->u.prefix4,
buf[0], sizeof(buf[0])),
p->prefixlen, api.metric, api.tag,
api.nexthop_num);
for (i = 0; i < api.nexthop_num; i++) {
label_buf[0] = '\0';
if (has_valid_label)
sprintf(label_buf, "label %u",
api.label[i]);
zlog_debug(" nhop [%d]: %s %s", i + 1,
inet_ntop(AF_INET, api.nexthop[i],
buf[1], sizeof(buf[1])),
label_buf);
}
}
zapi_ipv4_route(valid_nh_count ? ZEBRA_IPV4_ROUTE_ADD
: ZEBRA_IPV4_ROUTE_DELETE,
zclient, (struct prefix_ipv4 *)p, &api);
}
/* We have to think about a IPv6 link-local address curse. */
if (p->family == AF_INET6
|| (p->family == AF_INET && BGP_ATTR_NEXTHOP_AFI_IP6(info->attr))) {
ifindex_t ifindex;
struct in6_addr *nexthop;
struct zapi_ipv6 api;
int valid_nh_count = 0;
char buf[2][INET6_ADDRSTRLEN];
int has_valid_label = 0;
stream_reset(bgp_nexthop_buf);
stream_reset(bgp_ifindices_buf);
stream_reset(bgp_label_buf);
ifindex = 0;
nexthop = NULL;
if (bgp->table_map[afi][safi].name)
BGP_INFO_ATTR_BUF_INIT();
metric = info->attr->med;
for (mpinfo = info; mpinfo;
mpinfo = bgp_info_mpath_next(mpinfo)) {
ifindex = 0; ifindex = 0;
nexthop = NULL; nexthop = NULL;
@ -1407,147 +1132,72 @@ void bgp_zebra_announce(struct bgp_node *rn, struct prefix *p,
if (ifindex == 0) if (ifindex == 0)
continue; continue;
stream_put(bgp_nexthop_buf, &nexthop, api_nh = &api.nexthops[valid_nh_count];
sizeof(struct in6_addr *)); api_nh->gate.ipv6 = *nexthop;
stream_put(bgp_ifindices_buf, &ifindex, api_nh->ifindex = ifindex;
sizeof(unsigned int)); api_nh->type = NEXTHOP_TYPE_IPV6_IFINDEX;
if (mpinfo->extra
&& bgp_is_valid_label(&mpinfo->extra->label)) {
has_valid_label = 1;
label = label_pton(&mpinfo->extra->label);
stream_put(bgp_label_buf, &label,
sizeof(mpls_label_t));
}
valid_nh_count++;
} }
/* Make Zebra API structure. */ if (mpinfo->extra
api.vrf_id = bgp->vrf_id; && bgp_is_valid_label(&mpinfo->extra->label)) {
api.flags = flags; has_valid_label = 1;
api.type = ZEBRA_ROUTE_BGP; label = label_pton(&mpinfo->extra->label);
api.instance = 0;
api.message = 0;
api.safi = safi;
SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
if (has_valid_label) api_nh->label_num = 1;
SET_FLAG(api.message, ZAPI_MESSAGE_LABEL); api_nh->labels[0] = label;
/* Note that this currently only applies to Null0 routes for
* aggregates.
* ZEBRA_FLAG_BLACKHOLE signals zapi_ipv6_route to encode a
* special
* BLACKHOLE nexthop. We want to set api.nexthop_num to zero
* since we
* do not want to also encode the :: nexthop for the aggregate
* route.
*/
if (CHECK_FLAG(flags, ZEBRA_FLAG_BLACKHOLE))
api.nexthop_num = 0;
else
api.nexthop_num = valid_nh_count;
api.nexthop = (struct in6_addr **)STREAM_DATA(bgp_nexthop_buf);
SET_FLAG(api.message, ZAPI_MESSAGE_IFINDEX);
api.ifindex_num = valid_nh_count;
api.ifindex = (ifindex_t *)STREAM_DATA(bgp_ifindices_buf);
if (has_valid_label) {
api.label_num = valid_nh_count;
api.label = (unsigned int *)STREAM_DATA(bgp_label_buf);
} else {
api.label_num = 0;
api.label = NULL;
} }
SET_FLAG(api.message, ZAPI_MESSAGE_METRIC); valid_nh_count++;
api.metric = metric; }
api.tag = 0;
if (tag) { if (has_valid_label)
SET_FLAG(api.message, ZAPI_MESSAGE_TAG); SET_FLAG(api.message, ZAPI_MESSAGE_LABEL);
api.tag = tag;
}
distance = bgp_distance_apply(p, info, afi, safi, bgp); if (!CHECK_FLAG(api.flags, ZEBRA_FLAG_BLACKHOLE))
if (distance) { api.nexthop_num = valid_nh_count;
SET_FLAG(api.message, ZAPI_MESSAGE_DISTANCE);
api.distance = distance;
}
if (p->family == AF_INET) { SET_FLAG(api.message, ZAPI_MESSAGE_METRIC);
if (bgp_debug_zebra(p)) { api.metric = metric;
int i;
char label_buf[20];
zlog_debug(
"Tx IPv4 route %s VRF %u %s/%d metric %u tag %" ROUTE_TAG_PRI,
valid_nh_count ? "add" : "delete",
bgp->vrf_id,
inet_ntop(AF_INET, &p->u.prefix4,
buf[0], sizeof(buf[0])),
p->prefixlen, api.metric, api.tag);
for (i = 0; i < api.nexthop_num; i++) {
label_buf[0] = '\0';
if (has_valid_label)
sprintf(label_buf, "label %u",
api.label[i]);
zlog_debug(
" nhop [%d]: %s if %s %s",
i + 1,
inet_ntop(AF_INET6,
api.nexthop[i],
buf[1],
sizeof(buf[1])),
ifindex2ifname(api.ifindex[i],
bgp->vrf_id),
label_buf);
}
}
if (valid_nh_count) if (tag) {
zapi_ipv4_route_ipv6_nexthop( SET_FLAG(api.message, ZAPI_MESSAGE_TAG);
ZEBRA_IPV4_ROUTE_IPV6_NEXTHOP_ADD, api.tag = tag;
zclient, (struct prefix_ipv4 *)p, }
(struct zapi_ipv6 *)&api);
else
zapi_ipv4_route(ZEBRA_IPV4_ROUTE_DELETE,
zclient,
(struct prefix_ipv4 *)p,
(struct zapi_ipv4 *)&api);
} else {
if (bgp_debug_zebra(p)) {
int i;
char label_buf[20];
zlog_debug(
"Tx IPv6 route %s VRF %u %s/%d metric %u tag %" ROUTE_TAG_PRI,
valid_nh_count ? "add" : "delete",
bgp->vrf_id,
inet_ntop(AF_INET6, &p->u.prefix6,
buf[0], sizeof(buf[0])),
p->prefixlen, api.metric, api.tag);
for (i = 0; i < api.nexthop_num; i++) {
label_buf[0] = '\0';
if (has_valid_label)
sprintf(label_buf, "label %u",
api.label[i]);
zlog_debug(
" nhop [%d]: %s if %s %s",
i + 1,
inet_ntop(AF_INET6,
api.nexthop[i],
buf[1],
sizeof(buf[1])),
ifindex2ifname(api.ifindex[i],
bgp->vrf_id),
label_buf);
}
}
zapi_ipv6_route( distance = bgp_distance_apply(p, info, afi, safi, bgp);
valid_nh_count ? ZEBRA_IPV6_ROUTE_ADD if (distance) {
: ZEBRA_IPV6_ROUTE_DELETE, SET_FLAG(api.message, ZAPI_MESSAGE_DISTANCE);
zclient, (struct prefix_ipv6 *)p, NULL, &api); api.distance = distance;
}
if (bgp_debug_zebra(p)) {
char prefix_buf[PREFIX_STRLEN];
char nh_buf[INET6_ADDRSTRLEN];
char label_buf[20];
int i;
prefix2str(&api.prefix, prefix_buf, sizeof(prefix_buf));
zlog_debug("Tx route %s VRF %u %s metric %u tag %" ROUTE_TAG_PRI
" count %d",
valid_nh_count ? "add" : "delete", bgp->vrf_id,
prefix_buf, api.metric, api.tag, api.nexthop_num);
for (i = 0; i < api.nexthop_num; i++) {
api_nh = &api.nexthops[i];
inet_ntop(nh_family, &api_nh->gate, nh_buf,
sizeof(nh_buf));
label_buf[0] = '\0';
if (has_valid_label)
sprintf(label_buf, "label %u",
api_nh->labels[0]);
zlog_debug(" nhop [%d]: %s %s", i + 1, nh_buf,
label_buf);
} }
} }
zclient_route_send(valid_nh_count ? ZEBRA_ROUTE_ADD
: ZEBRA_ROUTE_DELETE,
zclient, &api);
} }
/* Announce all routes of a table to zebra */ /* Announce all routes of a table to zebra */
@ -1578,7 +1228,7 @@ void bgp_zebra_announce_table(struct bgp *bgp, afi_t afi, safi_t safi)
void bgp_zebra_withdraw(struct prefix *p, struct bgp_info *info, safi_t safi) void bgp_zebra_withdraw(struct prefix *p, struct bgp_info *info, safi_t safi)
{ {
u_int32_t flags; struct zapi_route api;
struct peer *peer; struct peer *peer;
peer = info->peer; peer = info->peer;
@ -1590,101 +1240,30 @@ void bgp_zebra_withdraw(struct prefix *p, struct bgp_info *info, safi_t safi)
if (!bgp_install_info_to_zebra(peer->bgp)) if (!bgp_install_info_to_zebra(peer->bgp))
return; return;
if ((p->family == AF_INET memset(&api, 0, sizeof(api));
&& !vrf_bitmap_check(zclient->redist[AFI_IP][ZEBRA_ROUTE_BGP], api.vrf_id = peer->bgp->vrf_id;
peer->bgp->vrf_id)) api.type = ZEBRA_ROUTE_BGP;
|| (p->family == AF_INET6 api.safi = safi;
&& !vrf_bitmap_check(zclient->redist[AFI_IP6][ZEBRA_ROUTE_BGP], api.prefix = *p;
peer->bgp->vrf_id)))
return;
flags = 0;
if (peer->sort == BGP_PEER_IBGP) { if (peer->sort == BGP_PEER_IBGP) {
SET_FLAG(flags, ZEBRA_FLAG_INTERNAL); SET_FLAG(api.flags, ZEBRA_FLAG_INTERNAL);
SET_FLAG(flags, ZEBRA_FLAG_IBGP); SET_FLAG(api.flags, ZEBRA_FLAG_IBGP);
} }
if ((peer->sort == BGP_PEER_EBGP && peer->ttl != 1) if ((peer->sort == BGP_PEER_EBGP && peer->ttl != 1)
|| CHECK_FLAG(peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK) || CHECK_FLAG(peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK)
|| bgp_flag_check(peer->bgp, BGP_FLAG_DISABLE_NH_CONNECTED_CHK)) || bgp_flag_check(peer->bgp, BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
SET_FLAG(flags, ZEBRA_FLAG_INTERNAL); SET_FLAG(api.flags, ZEBRA_FLAG_INTERNAL);
if (p->family == AF_INET) { if (bgp_debug_zebra(p)) {
struct zapi_ipv4 api; char buf[PREFIX_STRLEN];
api.vrf_id = peer->bgp->vrf_id; prefix2str(&api.prefix, buf, sizeof(buf));
api.flags = flags; zlog_debug("Tx route delete VRF %u %s", peer->bgp->vrf_id, buf);
api.type = ZEBRA_ROUTE_BGP;
api.instance = 0;
api.message = 0;
api.safi = safi;
SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
api.nexthop_num = 0;
api.nexthop = NULL;
api.label_num = 0;
api.label = NULL;
api.ifindex_num = 0;
SET_FLAG(api.message, ZAPI_MESSAGE_METRIC);
api.metric = info->attr->med;
api.tag = 0;
if (info->attr->tag != 0) {
SET_FLAG(api.message, ZAPI_MESSAGE_TAG);
api.tag = info->attr->tag;
}
if (bgp_debug_zebra(p)) {
char buf[2][INET_ADDRSTRLEN];
zlog_debug(
"Tx IPv4 route delete VRF %u %s/%d metric %u tag %" ROUTE_TAG_PRI,
peer->bgp->vrf_id,
inet_ntop(AF_INET, &p->u.prefix4, buf[0],
sizeof(buf[0])),
p->prefixlen, api.metric, api.tag);
}
zapi_ipv4_route(ZEBRA_IPV4_ROUTE_DELETE, zclient,
(struct prefix_ipv4 *)p, &api);
} }
/* We have to think about a IPv6 link-local address curse. */
if (p->family == AF_INET6) {
struct zapi_ipv6 api;
api.vrf_id = peer->bgp->vrf_id; zclient_route_send(ZEBRA_ROUTE_DELETE, zclient, &api);
api.flags = flags;
api.type = ZEBRA_ROUTE_BGP;
api.instance = 0;
api.message = 0;
api.safi = safi;
SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
api.nexthop_num = 0;
api.nexthop = NULL;
api.ifindex_num = 0;
api.label_num = 0;
SET_FLAG(api.message, ZAPI_MESSAGE_METRIC);
api.metric = info->attr->med;
api.tag = 0;
if (info->attr->tag != 0) {
SET_FLAG(api.message, ZAPI_MESSAGE_TAG);
api.tag = info->attr->tag;
}
if (bgp_debug_zebra(p)) {
char buf[2][INET6_ADDRSTRLEN];
zlog_debug(
"Tx IPv6 route delete VRF %u %s/%d metric %u tag %" ROUTE_TAG_PRI,
peer->bgp->vrf_id,
inet_ntop(AF_INET6, &p->u.prefix6, buf[0],
sizeof(buf[0])),
p->prefixlen, api.metric, api.tag);
}
zapi_ipv6_route(ZEBRA_IPV6_ROUTE_DELETE, zclient,
(struct prefix_ipv6 *)p, NULL, &api);
}
} }
struct bgp_redist *bgp_redist_lookup(struct bgp *bgp, afi_t afi, u_char type, struct bgp_redist *bgp_redist_lookup(struct bgp *bgp, afi_t afi, u_char type,
@ -2198,12 +1777,10 @@ void bgp_zebra_init(struct thread_master *master)
zclient->interface_nbr_address_delete = zclient->interface_nbr_address_delete =
bgp_interface_nbr_address_delete; bgp_interface_nbr_address_delete;
zclient->interface_vrf_update = bgp_interface_vrf_update; zclient->interface_vrf_update = bgp_interface_vrf_update;
zclient->redistribute_route_ipv4_add = zebra_read_ipv4; zclient->redistribute_route_add = zebra_read_route;
zclient->redistribute_route_ipv4_del = zebra_read_ipv4; zclient->redistribute_route_del = zebra_read_route;
zclient->interface_up = bgp_interface_up; zclient->interface_up = bgp_interface_up;
zclient->interface_down = bgp_interface_down; zclient->interface_down = bgp_interface_down;
zclient->redistribute_route_ipv6_add = zebra_read_ipv6;
zclient->redistribute_route_ipv6_del = zebra_read_ipv6;
zclient->nexthop_update = bgp_read_nexthop_update; zclient->nexthop_update = bgp_read_nexthop_update;
zclient->import_check_update = bgp_read_import_check_update; zclient->import_check_update = bgp_read_import_check_update;
zclient->fec_update = bgp_read_fec_update; zclient->fec_update = bgp_read_fec_update;
@ -2211,22 +1788,10 @@ void bgp_zebra_init(struct thread_master *master)
zclient->local_vni_del = bgp_zebra_process_local_vni; zclient->local_vni_del = bgp_zebra_process_local_vni;
zclient->local_macip_add = bgp_zebra_process_local_macip; zclient->local_macip_add = bgp_zebra_process_local_macip;
zclient->local_macip_del = bgp_zebra_process_local_macip; zclient->local_macip_del = bgp_zebra_process_local_macip;
bgp_nexthop_buf = stream_new(multipath_num * sizeof(struct in6_addr));
bgp_ifindices_buf = stream_new(multipath_num * sizeof(unsigned int));
bgp_label_buf = stream_new(multipath_num * sizeof(unsigned int));
} }
void bgp_zebra_destroy(void) void bgp_zebra_destroy(void)
{ {
if (bgp_nexthop_buf)
stream_free(bgp_nexthop_buf);
if (bgp_ifindices_buf)
stream_free(bgp_ifindices_buf);
if (bgp_label_buf)
stream_free(bgp_label_buf);
if (zclient == NULL) if (zclient == NULL)
return; return;
zclient_stop(zclient); zclient_stop(zclient);

View File

@ -1391,6 +1391,32 @@ void bgp_peer_conf_if_to_su_update(struct peer *peer)
hash_get(peer->bgp->peerhash, peer, hash_alloc_intern); hash_get(peer->bgp->peerhash, peer, hash_alloc_intern);
} }
static void bgp_recalculate_afi_safi_bestpaths(struct bgp *bgp, afi_t afi,
safi_t safi)
{
struct bgp_node *rn, *nrn;
for (rn = bgp_table_top(bgp->rib[afi][safi]); rn;
rn = bgp_route_next(rn)) {
if (rn->info != NULL) {
/* Special handling for 2-level routing
* tables. */
if (safi == SAFI_MPLS_VPN
|| safi == SAFI_ENCAP
|| safi == SAFI_EVPN) {
for (nrn = bgp_table_top((
struct bgp_table
*)(rn->info));
nrn;
nrn = bgp_route_next(nrn))
bgp_process(bgp, nrn,
afi, safi);
} else
bgp_process(bgp, rn, afi, safi);
}
}
}
/* Force a bestpath recalculation for all prefixes. This is used /* Force a bestpath recalculation for all prefixes. This is used
* when 'bgp bestpath' commands are entered. * when 'bgp bestpath' commands are entered.
*/ */
@ -1398,29 +1424,10 @@ void bgp_recalculate_all_bestpaths(struct bgp *bgp)
{ {
afi_t afi; afi_t afi;
safi_t safi; safi_t safi;
struct bgp_node *rn, *nrn;
for (afi = AFI_IP; afi < AFI_MAX; afi++) { for (afi = AFI_IP; afi < AFI_MAX; afi++) {
for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) { for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) {
for (rn = bgp_table_top(bgp->rib[afi][safi]); rn; bgp_recalculate_afi_safi_bestpaths(bgp, afi, safi);
rn = bgp_route_next(rn)) {
if (rn->info != NULL) {
/* Special handling for 2-level routing
* tables. */
if (safi == SAFI_MPLS_VPN
|| safi == SAFI_ENCAP
|| safi == SAFI_EVPN) {
for (nrn = bgp_table_top((
struct bgp_table
*)(rn->info));
nrn;
nrn = bgp_route_next(nrn))
bgp_process(bgp, nrn,
afi, safi);
} else
bgp_process(bgp, rn, afi, safi);
}
}
} }
} }
} }
@ -1500,6 +1507,25 @@ struct peer *peer_create_accept(struct bgp *bgp)
return peer; return peer;
} }
/*
* Return true if we have a peer configured to use this afi/safi
*/
int bgp_afi_safi_peer_exists(struct bgp *bgp, afi_t afi, safi_t safi)
{
struct listnode *node;
struct peer *peer;
for (ALL_LIST_ELEMENTS_RO(bgp->peer, node, peer)) {
if (!CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE))
continue;
if (peer->afc[afi][safi])
return 1;
}
return 0;
}
/* Change peer's AS number. */ /* Change peer's AS number. */
void peer_as_change(struct peer *peer, as_t as, int as_specified) void peer_as_change(struct peer *peer, as_t as, int as_specified)
{ {
@ -1714,11 +1740,14 @@ int peer_activate(struct peer *peer, afi_t afi, safi_t safi)
struct peer_group *group; struct peer_group *group;
struct listnode *node, *nnode; struct listnode *node, *nnode;
struct peer *tmp_peer; struct peer *tmp_peer;
struct bgp *bgp;
/* Nothing to do if we've already activated this peer */ /* Nothing to do if we've already activated this peer */
if (peer->afc[afi][safi]) if (peer->afc[afi][safi])
return ret; return ret;
bgp = peer->bgp;
/* This is a peer-group so activate all of the members of the /* This is a peer-group so activate all of the members of the
* peer-group as well */ * peer-group as well */
if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) { if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
@ -1741,6 +1770,17 @@ int peer_activate(struct peer *peer, afi_t afi, safi_t safi)
ret |= non_peergroup_activate_af(peer, afi, safi); ret |= non_peergroup_activate_af(peer, afi, safi);
} }
/* If this is the first peer to be activated for this afi/labeled-unicast
* recalc bestpaths to trigger label allocation */
if (safi == SAFI_LABELED_UNICAST && !bgp->allocate_mpls_labels[afi][SAFI_UNICAST]) {
if (BGP_DEBUG(zebra, ZEBRA))
zlog_info("peer(s) are now active for labeled-unicast, allocate MPLS labels");
bgp->allocate_mpls_labels[afi][SAFI_UNICAST] = 1;
bgp_recalculate_afi_safi_bestpaths(bgp, afi, SAFI_UNICAST);
}
return ret; return ret;
} }
@ -1798,6 +1838,7 @@ int peer_deactivate(struct peer *peer, afi_t afi, safi_t safi)
struct peer_group *group; struct peer_group *group;
struct peer *tmp_peer; struct peer *tmp_peer;
struct listnode *node, *nnode; struct listnode *node, *nnode;
struct bgp *bgp;
/* Nothing to do if we've already de-activated this peer */ /* Nothing to do if we've already de-activated this peer */
if (!peer->afc[afi][safi]) if (!peer->afc[afi][safi])
@ -1821,6 +1862,20 @@ int peer_deactivate(struct peer *peer, afi_t afi, safi_t safi)
ret |= non_peergroup_deactivate_af(peer, afi, safi); ret |= non_peergroup_deactivate_af(peer, afi, safi);
} }
bgp = peer->bgp;
/* If this is the last peer to be deactivated for this afi/labeled-unicast
* recalc bestpaths to trigger label deallocation */
if (safi == SAFI_LABELED_UNICAST &&
bgp->allocate_mpls_labels[afi][SAFI_UNICAST] &&
!bgp_afi_safi_peer_exists(bgp, afi, safi)) {
if (BGP_DEBUG(zebra, ZEBRA))
zlog_info("peer(s) are no longer active for labeled-unicast, deallocate MPLS labels");
bgp->allocate_mpls_labels[afi][SAFI_UNICAST] = 0;
bgp_recalculate_afi_safi_bestpaths(bgp, afi, SAFI_UNICAST);
}
return ret; return ret;
} }
@ -3087,6 +3142,8 @@ int bgp_delete(struct bgp *bgp)
* routes to be processed still referencing the struct bgp. * routes to be processed still referencing the struct bgp.
*/ */
listnode_delete(bm->bgp, bgp); listnode_delete(bm->bgp, bgp);
if (list_isempty(bm->bgp))
bgp_close();
/* Deregister from Zebra, if needed */ /* Deregister from Zebra, if needed */
if (IS_BGP_INST_KNOWN_TO_ZEBRA(bgp)) if (IS_BGP_INST_KNOWN_TO_ZEBRA(bgp))

View File

@ -334,6 +334,9 @@ struct bgp {
/* BGP redistribute configuration. */ /* BGP redistribute configuration. */
struct list *redist[AFI_MAX][ZEBRA_ROUTE_MAX]; struct list *redist[AFI_MAX][ZEBRA_ROUTE_MAX];
/* Allocate MPLS labels */
u_char allocate_mpls_labels[AFI_MAX][SAFI_MAX];
/* timer to re-evaluate neighbor default-originate route-maps */ /* timer to re-evaluate neighbor default-originate route-maps */
struct thread *t_rmap_def_originate_eval; struct thread *t_rmap_def_originate_eval;
#define RMAP_DEFAULT_ORIGINATE_EVAL_TIMER 5 #define RMAP_DEFAULT_ORIGINATE_EVAL_TIMER 5
@ -1285,6 +1288,7 @@ extern int bgp_listen_limit_unset(struct bgp *);
extern int bgp_update_delay_active(struct bgp *); extern int bgp_update_delay_active(struct bgp *);
extern int bgp_update_delay_configured(struct bgp *); extern int bgp_update_delay_configured(struct bgp *);
extern int bgp_afi_safi_peer_exists(struct bgp *bgp, afi_t afi, safi_t safi);
extern void peer_as_change(struct peer *, as_t, int); extern void peer_as_change(struct peer *, as_t, int);
extern int peer_remote_as(struct bgp *, union sockunion *, const char *, as_t *, extern int peer_remote_as(struct bgp *, union sockunion *, const char *, as_t *,
int, afi_t, safi_t); int, afi_t, safi_t);

View File

@ -57,8 +57,8 @@ static struct zclient *zclient_vnc = NULL;
/* /*
* Routes coming from zebra get added to VNC here * Routes coming from zebra get added to VNC here
*/ */
static void vnc_redistribute_add(struct prefix *p, struct in_addr *nexthop, static void vnc_redistribute_add(struct prefix *p, u_int32_t metric,
u_int32_t metric, uint8_t type) uint8_t type)
{ {
struct bgp *bgp = bgp_get_default(); struct bgp *bgp = bgp_get_default();
struct prefix_rd prd; struct prefix_rd prd;
@ -329,156 +329,33 @@ static void vnc_redistribute_withdraw(struct bgp *bgp, afi_t afi, uint8_t type)
* *
* Assumes 1 nexthop * Assumes 1 nexthop
*/ */
static int vnc_zebra_read_ipv4(int command, struct zclient *zclient, static int vnc_zebra_read_route(int command, struct zclient *zclient,
zebra_size_t length, vrf_id_t vrf_id) zebra_size_t length, vrf_id_t vrf_id)
{ {
struct stream *s; struct zapi_route api;
struct zapi_ipv4 api; int add;
struct in_addr nexthop;
struct prefix_ipv4 p;
s = zclient->ibuf; if (zapi_route_decode(zclient->ibuf, &api) < 0)
nexthop.s_addr = 0; return -1;
/* Type, flags, message. */ /* we completely ignore srcdest routes for now. */
api.type = stream_getc(s); if (CHECK_FLAG(api.message, ZAPI_MESSAGE_SRCPFX))
api.flags = stream_getc(s);
api.message = stream_getc(s);
/* IPv4 prefix. */
memset(&p, 0, sizeof(struct prefix_ipv4));
p.family = AF_INET;
p.prefixlen = stream_getc(s);
stream_get(&p.prefix, s, PSIZE(p.prefixlen));
/* Nexthop, ifindex, distance, metric. */
if (CHECK_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP)) {
api.nexthop_num = stream_getc(s);
nexthop.s_addr = stream_get_ipv4(s);
}
if (CHECK_FLAG(api.message, ZAPI_MESSAGE_IFINDEX)) {
api.ifindex_num = stream_getc(s);
stream_getl(s);
}
if (CHECK_FLAG(api.message, ZAPI_MESSAGE_DISTANCE))
api.distance = stream_getc(s);
if (CHECK_FLAG(api.message, ZAPI_MESSAGE_METRIC))
api.metric = stream_getl(s);
else
api.metric = 0;
if (command == ZEBRA_IPV4_ROUTE_ADD) {
if (BGP_DEBUG(zebra, ZEBRA)) {
char buf[2][INET_ADDRSTRLEN];
vnc_zlog_debug_verbose(
"%s: Zebra rcvd: IPv4 route add %s %s/%d nexthop %s metric %u",
__func__, zebra_route_string(api.type),
inet_ntop(AF_INET, &p.prefix, buf[0],
sizeof(buf[0])),
p.prefixlen, inet_ntop(AF_INET, &nexthop,
buf[1], sizeof(buf[1])),
api.metric);
}
vnc_redistribute_add((struct prefix *)&p, &nexthop, api.metric,
api.type);
} else {
if (BGP_DEBUG(zebra, ZEBRA)) {
char buf[2][INET_ADDRSTRLEN];
vnc_zlog_debug_verbose(
"%s: Zebra rcvd: IPv4 route delete %s %s/%d "
"nexthop %s metric %u",
__func__, zebra_route_string(api.type),
inet_ntop(AF_INET, &p.prefix, buf[0],
sizeof(buf[0])),
p.prefixlen, inet_ntop(AF_INET, &nexthop,
buf[1], sizeof(buf[1])),
api.metric);
}
vnc_redistribute_delete((struct prefix *)&p, api.type);
}
return 0;
}
/* Zebra route add and delete treatment. */
static int vnc_zebra_read_ipv6(int command, struct zclient *zclient,
zebra_size_t length, vrf_id_t vrf_id)
{
struct stream *s;
struct zapi_ipv6 api;
struct in6_addr nexthop;
struct prefix_ipv6 p, src_p;
s = zclient->ibuf;
memset(&nexthop, 0, sizeof(struct in6_addr));
/* Type, flags, message. */
api.type = stream_getc(s);
api.flags = stream_getc(s);
api.message = stream_getc(s);
/* IPv6 prefix. */
memset(&p, 0, sizeof(struct prefix_ipv6));
p.family = AF_INET6;
p.prefixlen = stream_getc(s);
stream_get(&p.prefix, s, PSIZE(p.prefixlen));
memset(&src_p, 0, sizeof(struct prefix_ipv6));
src_p.family = AF_INET6;
if (CHECK_FLAG(api.message, ZAPI_MESSAGE_SRCPFX)) {
src_p.prefixlen = stream_getc(s);
stream_get(&src_p.prefix, s, PSIZE(src_p.prefixlen));
}
if (src_p.prefixlen)
/* we completely ignore srcdest routes for now. */
return 0; return 0;
/* Nexthop, ifindex, distance, metric. */ add = (command == ZEBRA_REDISTRIBUTE_ROUTE_ADD);
if (CHECK_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP)) { if (add)
api.nexthop_num = stream_getc(s); vnc_redistribute_add(&api.prefix, api.metric, api.type);
stream_get(&nexthop, s, 16);
}
if (CHECK_FLAG(api.message, ZAPI_MESSAGE_IFINDEX)) {
api.ifindex_num = stream_getc(s);
stream_getl(s);
}
if (CHECK_FLAG(api.message, ZAPI_MESSAGE_DISTANCE))
api.distance = stream_getc(s);
else else
api.distance = 0; vnc_redistribute_delete(&api.prefix, api.type);
if (CHECK_FLAG(api.message, ZAPI_MESSAGE_METRIC))
api.metric = stream_getl(s);
else
api.metric = 0;
/* Simply ignore link-local address. */ if (BGP_DEBUG(zebra, ZEBRA)) {
if (IN6_IS_ADDR_LINKLOCAL(&p.prefix)) char buf[PREFIX_STRLEN];
return 0;
if (command == ZEBRA_IPV6_ROUTE_ADD) { prefix2str(&api.prefix, buf, sizeof(buf));
if (BGP_DEBUG(zebra, ZEBRA)) { vnc_zlog_debug_verbose(
char buf[INET6_ADDRSTRLEN]; "%s: Zebra rcvd: route delete %s %s metric %u",
vnc_zlog_debug_verbose( __func__, zebra_route_string(api.type), buf,
"Zebra rcvd: IPv6 route add %s %s/%d metric %u", api.metric);
zebra_route_string(api.type),
inet_ntop(AF_INET6, &p.prefix, buf,
sizeof(buf)),
p.prefixlen, api.metric);
}
vnc_redistribute_add((struct prefix *)&p, NULL, api.metric,
api.type);
} else {
if (BGP_DEBUG(zebra, ZEBRA)) {
char buf[INET6_ADDRSTRLEN];
vnc_zlog_debug_verbose(
"Zebra rcvd: IPv6 route delete %s %s/%d metric %u",
zebra_route_string(api.type),
inet_ntop(AF_INET6, &p.prefix, buf,
sizeof(buf)),
p.prefixlen, api.metric);
}
vnc_redistribute_delete((struct prefix *)&p, api.type);
} }
return 0; return 0;
@ -494,83 +371,57 @@ static int vnc_zebra_read_ipv6(int command, struct zclient *zclient,
static void vnc_zebra_route_msg(struct prefix *p, int nhp_count, void *nhp_ary, static void vnc_zebra_route_msg(struct prefix *p, int nhp_count, void *nhp_ary,
int add) /* 1 = add, 0 = del */ int add) /* 1 = add, 0 = del */
{ {
struct zapi_route api;
struct zapi_nexthop *api_nh;
int i;
if (!nhp_count) { if (!nhp_count) {
vnc_zlog_debug_verbose("%s: empty nexthop list, skipping", vnc_zlog_debug_verbose("%s: empty nexthop list, skipping",
__func__); __func__);
return; return;
} }
if (p->family == AF_INET) { memset(&api, 0, sizeof(api));
api.vrf_id = VRF_DEFAULT;
api.type = ZEBRA_ROUTE_VNC;
api.safi = SAFI_UNICAST;
api.prefix = *p;
struct zapi_ipv4 api; /* Nexthops */
SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
api.nexthop_num = nhp_count;
for (i = 0; i < nhp_count; i++) {
struct in_addr *nhp_ary4;
struct in6_addr *nhp_ary6;
api.flags = 0; api_nh = &api.nexthops[i];
api.vrf_id = VRF_DEFAULT; switch (p->family) {
api.type = ZEBRA_ROUTE_VNC; case AF_INET:
api.message = 0; nhp_ary4 = nhp_ary;
SET_FLAG(api.message, memcpy(&api_nh->gate.ipv4, &nhp_ary4[i],
ZAPI_MESSAGE_NEXTHOP); /* TBD what's it mean? */ sizeof(api_nh->gate.ipv4));
api.nexthop_num = nhp_count; api_nh->type = NEXTHOP_TYPE_IPV4;
api.nexthop = nhp_ary; break;
api.ifindex_num = 0; case AF_INET6:
api.instance = 0; nhp_ary6 = nhp_ary;
api.safi = SAFI_UNICAST; memcpy(&api_nh->gate.ipv6, &nhp_ary6[i],
sizeof(api_nh->gate.ipv6));
if (BGP_DEBUG(zebra, ZEBRA)) { api_nh->type = NEXTHOP_TYPE_IPV6;
break;
char buf[INET_ADDRSTRLEN];
vnc_zlog_debug_verbose(
"%s: Zebra send: IPv4 route %s %s/%d, nhp_count=%d",
__func__, (add ? "add" : "del"),
inet_ntop(AF_INET, &p->u.prefix4, buf,
sizeof(buf)),
p->prefixlen, nhp_count);
} }
zapi_ipv4_route((add ? ZEBRA_IPV4_NEXTHOP_ADD
: ZEBRA_IPV4_NEXTHOP_DELETE),
zclient_vnc, (struct prefix_ipv4 *)p, &api);
} else if (p->family == AF_INET6) {
struct zapi_ipv6 api;
ifindex_t ifindex = 0;
/* Make Zebra API structure. */
api.flags = 0;
api.vrf_id = VRF_DEFAULT;
api.type = ZEBRA_ROUTE_VNC;
api.message = 0;
SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP); /* TBD means? */
api.nexthop_num = nhp_count;
api.nexthop = nhp_ary;
SET_FLAG(api.message, ZAPI_MESSAGE_IFINDEX);
api.ifindex_num = 1;
api.ifindex = &ifindex;
api.instance = 0;
api.safi = SAFI_UNICAST;
if (BGP_DEBUG(zebra, ZEBRA)) {
char buf[INET6_ADDRSTRLEN];
vnc_zlog_debug_verbose(
"%s: Zebra send: IPv6 route %s %s/%d nhp_count=%d",
__func__, (add ? "add" : "del"),
inet_ntop(AF_INET6, &p->u.prefix6, buf,
sizeof(buf)),
p->prefixlen, nhp_count);
}
zapi_ipv6_route((add ? ZEBRA_IPV6_NEXTHOP_ADD
: ZEBRA_IPV6_NEXTHOP_DELETE),
zclient_vnc, (struct prefix_ipv6 *)p, NULL,
&api);
} else {
vnc_zlog_debug_verbose(
"%s: unknown prefix address family, skipping",
__func__);
return;
} }
if (BGP_DEBUG(zebra, ZEBRA)) {
char buf[PREFIX_STRLEN];
prefix2str(&api.prefix, buf, sizeof(buf));
vnc_zlog_debug_verbose(
"%s: Zebra send: route %s %s, nhp_count=%d", __func__,
(add ? "add" : "del"), buf, nhp_count);
}
zclient_route_send((add ? ZEBRA_ROUTE_ADD : ZEBRA_ROUTE_DELETE),
zclient_vnc, &api);
} }
@ -1042,10 +893,8 @@ void vnc_zebra_init(struct thread_master *master)
zclient_vnc = zclient_new(master); zclient_vnc = zclient_new(master);
zclient_init(zclient_vnc, ZEBRA_ROUTE_VNC, 0); zclient_init(zclient_vnc, ZEBRA_ROUTE_VNC, 0);
zclient_vnc->redistribute_route_ipv4_add = vnc_zebra_read_ipv4; zclient_vnc->redistribute_route_add = vnc_zebra_read_route;
zclient_vnc->redistribute_route_ipv4_del = vnc_zebra_read_ipv4; zclient_vnc->redistribute_route_del = vnc_zebra_read_route;
zclient_vnc->redistribute_route_ipv6_add = vnc_zebra_read_ipv6;
zclient_vnc->redistribute_route_ipv6_del = vnc_zebra_read_ipv6;
} }
void vnc_zebra_destroy(void) void vnc_zebra_destroy(void)

View File

@ -13,8 +13,7 @@ CLIPPY_DEPS = $(HOSTTOOLS)lib/clippy $(top_srcdir)/python/clidef.py
SUFFIXES = _clippy.c .proto .pb-c.c .pb-c.h .pb.h SUFFIXES = _clippy.c .proto .pb-c.c .pb-c.h .pb.h
.c_clippy.c: .c_clippy.c:
@{ test -x $(top_builddir)/$(HOSTTOOLS)lib/clippy || $(MAKE) -C $(top_builddir)/$(HOSTTOOLS) lib/clippy; } @{ test -x $(top_builddir)/$(HOSTTOOLS)lib/clippy || $(MAKE) -C $(top_builddir)/$(HOSTTOOLS) lib/clippy; }
$(AM_V_CLIPPY)$(top_builddir)/$(HOSTTOOLS)lib/clippy $(top_srcdir)/python/clidef.py $< > $@.tmp $(AM_V_CLIPPY)$(top_builddir)/$(HOSTTOOLS)lib/clippy $(top_srcdir)/python/clidef.py -o $@ $<
@{ test -f $@ && diff $@.tmp $@ >/dev/null 2>/dev/null; } && rm $@.tmp || mv $@.tmp $@
## automake's "ylwrap" is a great piece of GNU software... not. ## automake's "ylwrap" is a great piece of GNU software... not.
.l.c: .l.c:

View File

@ -158,7 +158,7 @@ const char *eigrp_topology_ip_string(struct eigrp_prefix_entry *tn)
static char buf[EIGRP_IF_STRING_MAXLEN] = ""; static char buf[EIGRP_IF_STRING_MAXLEN] = "";
u_int32_t ifaddr; u_int32_t ifaddr;
ifaddr = ntohl(tn->destination_ipv4->prefix.s_addr); ifaddr = ntohl(tn->destination->u.prefix4.s_addr);
snprintf(buf, EIGRP_IF_STRING_MAXLEN, "%u.%u.%u.%u", snprintf(buf, EIGRP_IF_STRING_MAXLEN, "%u.%u.%u.%u",
(ifaddr >> 24) & 0xff, (ifaddr >> 16) & 0xff, (ifaddr >> 24) & 0xff, (ifaddr >> 16) & 0xff,
(ifaddr >> 8) & 0xff, ifaddr & 0xff); (ifaddr >> 8) & 0xff, ifaddr & 0xff);
@ -289,11 +289,12 @@ void show_ip_eigrp_topology_header(struct vty *vty, struct eigrp *eigrp)
void show_ip_eigrp_prefix_entry(struct vty *vty, struct eigrp_prefix_entry *tn) void show_ip_eigrp_prefix_entry(struct vty *vty, struct eigrp_prefix_entry *tn)
{ {
struct list *successors = eigrp_topology_get_successor(tn); struct list *successors = eigrp_topology_get_successor(tn);
char buffer[PREFIX_STRLEN];
vty_out(vty, "%-3c", (tn->state > 0) ? 'A' : 'P'); vty_out(vty, "%-3c", (tn->state > 0) ? 'A' : 'P');
vty_out(vty, "%s/%u, ", inet_ntoa(tn->destination_ipv4->prefix), vty_out(vty, "%s, ",
tn->destination_ipv4->prefixlen); prefix2str(tn->destination, buffer, PREFIX_STRLEN));
vty_out(vty, "%u successors, ", successors->count); vty_out(vty, "%u successors, ", successors->count);
vty_out(vty, "FD is %u, serno: %" PRIu64 " \n", tn->fdistance, vty_out(vty, "FD is %u, serno: %" PRIu64 " \n", tn->fdistance,
tn->serno); tn->serno);

View File

@ -178,7 +178,7 @@ struct {
* Return number of occurred event (arrow in diagram). * Return number of occurred event (arrow in diagram).
* *
*/ */
int eigrp_get_fsm_event(struct eigrp_fsm_action_message *msg) static int eigrp_get_fsm_event(struct eigrp_fsm_action_message *msg)
{ {
// Loading base information from message // Loading base information from message
// struct eigrp *eigrp = msg->eigrp; // struct eigrp *eigrp = msg->eigrp;
@ -204,8 +204,7 @@ int eigrp_get_fsm_event(struct eigrp_fsm_action_message *msg)
switch (actual_state) { switch (actual_state) {
case EIGRP_FSM_STATE_PASSIVE: { case EIGRP_FSM_STATE_PASSIVE: {
struct eigrp_neighbor_entry *head = struct eigrp_neighbor_entry *head =
(struct eigrp_neighbor_entry *) listnode_head(prefix->entries);
entry->prefix->entries->head->data;
if (head->reported_distance < prefix->fdistance) { if (head->reported_distance < prefix->fdistance) {
return EIGRP_FSM_KEEP_STATE; return EIGRP_FSM_KEEP_STATE;
@ -226,8 +225,7 @@ int eigrp_get_fsm_event(struct eigrp_fsm_action_message *msg)
case EIGRP_FSM_STATE_ACTIVE_0: { case EIGRP_FSM_STATE_ACTIVE_0: {
if (msg->packet_type == EIGRP_OPC_REPLY) { if (msg->packet_type == EIGRP_OPC_REPLY) {
struct eigrp_neighbor_entry *head = struct eigrp_neighbor_entry *head =
(struct eigrp_neighbor_entry *) listnode_head(prefix->entries);
entry->prefix->entries->head->data;
listnode_delete(prefix->rij, entry->adv_router); listnode_delete(prefix->rij, entry->adv_router);
if (prefix->rij->count) if (prefix->rij->count)
@ -279,8 +277,7 @@ int eigrp_get_fsm_event(struct eigrp_fsm_action_message *msg)
case EIGRP_FSM_STATE_ACTIVE_2: { case EIGRP_FSM_STATE_ACTIVE_2: {
if (msg->packet_type == EIGRP_OPC_REPLY) { if (msg->packet_type == EIGRP_OPC_REPLY) {
struct eigrp_neighbor_entry *head = struct eigrp_neighbor_entry *head =
(struct eigrp_neighbor_entry *) listnode_head(prefix->entries);
prefix->entries->head->data;
listnode_delete(prefix->rij, entry->adv_router); listnode_delete(prefix->rij, entry->adv_router);
if (prefix->rij->count) { if (prefix->rij->count) {
@ -331,8 +328,9 @@ int eigrp_get_fsm_event(struct eigrp_fsm_action_message *msg)
* Function made to execute in separate thread. * Function made to execute in separate thread.
* Load argument from thread and execute proper NSM function * Load argument from thread and execute proper NSM function
*/ */
int eigrp_fsm_event(struct eigrp_fsm_action_message *msg, int event) int eigrp_fsm_event(struct eigrp_fsm_action_message *msg)
{ {
int event = eigrp_get_fsm_event(msg);
zlog_info("EIGRP AS: %d State: %d Event: %d Network: %s", zlog_info("EIGRP AS: %d State: %d Event: %d Network: %s",
msg->eigrp->AS, msg->prefix->state, event, msg->eigrp->AS, msg->prefix->state, event,
eigrp_topology_ip_string(msg->prefix)); eigrp_topology_ip_string(msg->prefix));
@ -350,16 +348,15 @@ int eigrp_fsm_event_nq_fcn(struct eigrp_fsm_action_message *msg)
struct eigrp *eigrp = msg->eigrp; struct eigrp *eigrp = msg->eigrp;
struct eigrp_prefix_entry *prefix = msg->prefix; struct eigrp_prefix_entry *prefix = msg->prefix;
struct list *successors = eigrp_topology_get_successor(prefix); struct list *successors = eigrp_topology_get_successor(prefix);
struct eigrp_neighbor_entry *ne;
assert(successors); // If this is NULL we have shit the bed, fun huh? assert(successors); // If this is NULL we have shit the bed, fun huh?
ne = listnode_head(successors);
prefix->state = EIGRP_FSM_STATE_ACTIVE_1; prefix->state = EIGRP_FSM_STATE_ACTIVE_1;
prefix->rdistance = prefix->distance = prefix->fdistance = prefix->rdistance = prefix->distance = prefix->fdistance =
((struct eigrp_neighbor_entry *)successors->head->data) ne->distance;
->distance; prefix->reported_metric = ne->total_metric;
prefix->reported_metric =
((struct eigrp_neighbor_entry *)successors->head->data)
->total_metric;
if (eigrp_nbr_count_get()) { if (eigrp_nbr_count_get()) {
prefix->req_action |= EIGRP_FSM_NEED_QUERY; prefix->req_action |= EIGRP_FSM_NEED_QUERY;
@ -379,16 +376,15 @@ int eigrp_fsm_event_q_fcn(struct eigrp_fsm_action_message *msg)
struct eigrp *eigrp = msg->eigrp; struct eigrp *eigrp = msg->eigrp;
struct eigrp_prefix_entry *prefix = msg->prefix; struct eigrp_prefix_entry *prefix = msg->prefix;
struct list *successors = eigrp_topology_get_successor(prefix); struct list *successors = eigrp_topology_get_successor(prefix);
struct eigrp_neighbor_entry *ne;
assert(successors); // If this is NULL somebody poked us in the eye. assert(successors); // If this is NULL somebody poked us in the eye.
ne = listnode_head(successors);
prefix->state = EIGRP_FSM_STATE_ACTIVE_3; prefix->state = EIGRP_FSM_STATE_ACTIVE_3;
prefix->rdistance = prefix->distance = prefix->fdistance = prefix->rdistance = prefix->distance = prefix->fdistance =
((struct eigrp_neighbor_entry *)successors->head->data) ne->distance;
->distance; prefix->reported_metric = ne->total_metric;
prefix->reported_metric =
((struct eigrp_neighbor_entry *)successors->head->data)
->total_metric;
if (eigrp_nbr_count_get()) { if (eigrp_nbr_count_get()) {
prefix->req_action |= EIGRP_FSM_NEED_QUERY; prefix->req_action |= EIGRP_FSM_NEED_QUERY;
listnode_add(eigrp->topology_changes_internalIPV4, prefix); listnode_add(eigrp->topology_changes_internalIPV4, prefix);
@ -405,21 +401,15 @@ int eigrp_fsm_event_q_fcn(struct eigrp_fsm_action_message *msg)
int eigrp_fsm_event_keep_state(struct eigrp_fsm_action_message *msg) int eigrp_fsm_event_keep_state(struct eigrp_fsm_action_message *msg)
{ {
struct eigrp_prefix_entry *prefix = msg->prefix; struct eigrp_prefix_entry *prefix = msg->prefix;
struct eigrp_neighbor_entry *ne = listnode_head(prefix->entries);
if (prefix->state == EIGRP_FSM_STATE_PASSIVE) { if (prefix->state == EIGRP_FSM_STATE_PASSIVE) {
if (!eigrp_metrics_is_same(prefix->reported_metric, if (!eigrp_metrics_is_same(prefix->reported_metric,
((struct eigrp_neighbor_entry *) ne->total_metric)) {
prefix->entries->head->data)
->total_metric)) {
prefix->rdistance = prefix->fdistance = prefix->rdistance = prefix->fdistance =
prefix->distance = prefix->distance = ne->distance;
((struct eigrp_neighbor_entry *)
prefix->entries->head->data)
->distance;
prefix->reported_metric = prefix->reported_metric =
((struct eigrp_neighbor_entry *) ne->total_metric;
prefix->entries->head->data)
->total_metric;
if (msg->packet_type == EIGRP_OPC_QUERY) if (msg->packet_type == EIGRP_OPC_QUERY)
eigrp_send_reply(msg->adv_router, prefix); eigrp_send_reply(msg->adv_router, prefix);
prefix->req_action |= EIGRP_FSM_NEED_UPDATE; prefix->req_action |= EIGRP_FSM_NEED_UPDATE;
@ -441,22 +431,20 @@ int eigrp_fsm_event_lr(struct eigrp_fsm_action_message *msg)
{ {
struct eigrp *eigrp = msg->eigrp; struct eigrp *eigrp = msg->eigrp;
struct eigrp_prefix_entry *prefix = msg->prefix; struct eigrp_prefix_entry *prefix = msg->prefix;
struct eigrp_neighbor_entry *ne = listnode_head(prefix->entries);
prefix->fdistance = prefix->distance = prefix->rdistance = prefix->fdistance = prefix->distance = prefix->rdistance =
((struct eigrp_neighbor_entry *)(prefix->entries->head->data)) ne->distance;
->distance; prefix->reported_metric = ne->total_metric;
prefix->reported_metric =
((struct eigrp_neighbor_entry *)(prefix->entries->head->data))
->total_metric;
if (prefix->state == EIGRP_FSM_STATE_ACTIVE_3) { if (prefix->state == EIGRP_FSM_STATE_ACTIVE_3) {
struct list *successors = eigrp_topology_get_successor(prefix); struct list *successors = eigrp_topology_get_successor(prefix);
assert(successors); // It's like Napolean and Waterloo assert(successors); // It's like Napolean and Waterloo
eigrp_send_reply( ne = listnode_head(successors);
((struct eigrp_neighbor_entry *)successors->head->data) eigrp_send_reply(ne->adv_router,
->adv_router, prefix);
prefix);
list_delete(successors); list_delete(successors);
} }
@ -473,15 +461,15 @@ int eigrp_fsm_event_lr(struct eigrp_fsm_action_message *msg)
int eigrp_fsm_event_dinc(struct eigrp_fsm_action_message *msg) int eigrp_fsm_event_dinc(struct eigrp_fsm_action_message *msg)
{ {
struct list *successors = eigrp_topology_get_successor(msg->prefix); struct list *successors = eigrp_topology_get_successor(msg->prefix);
struct eigrp_neighbor_entry *ne;
assert(successors); // Trump and his big hands assert(successors); // Trump and his big hands
ne = listnode_head(successors);
msg->prefix->state = msg->prefix->state == EIGRP_FSM_STATE_ACTIVE_1 msg->prefix->state = msg->prefix->state == EIGRP_FSM_STATE_ACTIVE_1
? EIGRP_FSM_STATE_ACTIVE_0 ? EIGRP_FSM_STATE_ACTIVE_0
: EIGRP_FSM_STATE_ACTIVE_2; : EIGRP_FSM_STATE_ACTIVE_2;
msg->prefix->distance = msg->prefix->distance = ne->distance;
((struct eigrp_neighbor_entry *)successors->head->data)
->distance;
if (!msg->prefix->rij->count) if (!msg->prefix->rij->count)
(*(NSM[msg->prefix->state][eigrp_get_fsm_event(msg)].func))( (*(NSM[msg->prefix->state][eigrp_get_fsm_event(msg)].func))(
msg); msg);
@ -495,13 +483,11 @@ int eigrp_fsm_event_lr_fcs(struct eigrp_fsm_action_message *msg)
{ {
struct eigrp *eigrp = msg->eigrp; struct eigrp *eigrp = msg->eigrp;
struct eigrp_prefix_entry *prefix = msg->prefix; struct eigrp_prefix_entry *prefix = msg->prefix;
struct eigrp_neighbor_entry *ne = listnode_head(prefix->entries);
prefix->state = EIGRP_FSM_STATE_PASSIVE; prefix->state = EIGRP_FSM_STATE_PASSIVE;
prefix->distance = prefix->rdistance = prefix->distance = prefix->rdistance = ne->distance;
((struct eigrp_neighbor_entry *)(prefix->entries->head->data)) prefix->reported_metric = ne->total_metric;
->distance;
prefix->reported_metric =
((struct eigrp_neighbor_entry *)(prefix->entries->head->data))
->total_metric;
prefix->fdistance = prefix->fdistance > prefix->distance prefix->fdistance = prefix->fdistance > prefix->distance
? prefix->distance ? prefix->distance
: prefix->fdistance; : prefix->fdistance;
@ -510,11 +496,9 @@ int eigrp_fsm_event_lr_fcs(struct eigrp_fsm_action_message *msg)
assert(successors); // Having a spoon and all you need is a assert(successors); // Having a spoon and all you need is a
// knife // knife
ne = listnode_head(successors);
eigrp_send_reply( eigrp_send_reply(ne->adv_router,
((struct eigrp_neighbor_entry *)successors->head->data) prefix);
->adv_router,
prefix);
list_delete(successors); list_delete(successors);
} }
@ -531,6 +515,7 @@ int eigrp_fsm_event_lr_fcn(struct eigrp_fsm_action_message *msg)
{ {
struct eigrp *eigrp = msg->eigrp; struct eigrp *eigrp = msg->eigrp;
struct eigrp_prefix_entry *prefix = msg->prefix; struct eigrp_prefix_entry *prefix = msg->prefix;
struct eigrp_neighbor_entry *best_successor;
struct list *successors = eigrp_topology_get_successor(prefix); struct list *successors = eigrp_topology_get_successor(prefix);
assert(successors); // Routing without a stack assert(successors); // Routing without a stack
@ -538,8 +523,8 @@ int eigrp_fsm_event_lr_fcn(struct eigrp_fsm_action_message *msg)
prefix->state = prefix->state == EIGRP_FSM_STATE_ACTIVE_0 prefix->state = prefix->state == EIGRP_FSM_STATE_ACTIVE_0
? EIGRP_FSM_STATE_ACTIVE_1 ? EIGRP_FSM_STATE_ACTIVE_1
: EIGRP_FSM_STATE_ACTIVE_3; : EIGRP_FSM_STATE_ACTIVE_3;
struct eigrp_neighbor_entry *best_successor =
((struct eigrp_neighbor_entry *)(successors->head->data)); best_successor = listnode_head(successors);
prefix->rdistance = prefix->distance = best_successor->distance; prefix->rdistance = prefix->distance = best_successor->distance;
prefix->reported_metric = best_successor->total_metric; prefix->reported_metric = best_successor->total_metric;
@ -559,13 +544,13 @@ int eigrp_fsm_event_lr_fcn(struct eigrp_fsm_action_message *msg)
int eigrp_fsm_event_qact(struct eigrp_fsm_action_message *msg) int eigrp_fsm_event_qact(struct eigrp_fsm_action_message *msg)
{ {
struct list *successors = eigrp_topology_get_successor(msg->prefix); struct list *successors = eigrp_topology_get_successor(msg->prefix);
struct eigrp_neighbor_entry *ne;
assert(successors); // Cats and no Dogs assert(successors); // Cats and no Dogs
ne = listnode_head(successors);
msg->prefix->state = EIGRP_FSM_STATE_ACTIVE_2; msg->prefix->state = EIGRP_FSM_STATE_ACTIVE_2;
msg->prefix->distance = msg->prefix->distance = ne->distance;
((struct eigrp_neighbor_entry *)(successors->head->data))
->distance;
list_delete(successors); list_delete(successors);
return 1; return 1;

View File

@ -28,8 +28,7 @@
#ifndef _ZEBRA_EIGRP_FSM_H #ifndef _ZEBRA_EIGRP_FSM_H
#define _ZEBRA_EIGRP_FSM_H #define _ZEBRA_EIGRP_FSM_H
extern int eigrp_get_fsm_event(struct eigrp_fsm_action_message *); extern int eigrp_fsm_event(struct eigrp_fsm_action_message *msg);
extern int eigrp_fsm_event(struct eigrp_fsm_action_message *, int);
#endif /* _ZEBRA_EIGRP_DUAL_H */ #endif /* _ZEBRA_EIGRP_DUAL_H */

View File

@ -53,6 +53,7 @@
#include "eigrpd/eigrp_network.h" #include "eigrpd/eigrp_network.h"
#include "eigrpd/eigrp_topology.h" #include "eigrpd/eigrp_topology.h"
#include "eigrpd/eigrp_memory.h" #include "eigrpd/eigrp_memory.h"
#include "eigrpd/eigrp_fsm.h"
static void eigrp_delete_from_if(struct interface *, struct eigrp_interface *); static void eigrp_delete_from_if(struct interface *, struct eigrp_interface *);
@ -224,14 +225,14 @@ void eigrp_del_if_params(struct eigrp_if_params *eip)
struct eigrp_if_params *eigrp_lookup_if_params(struct interface *ifp, struct eigrp_if_params *eigrp_lookup_if_params(struct interface *ifp,
struct in_addr addr) struct in_addr addr)
{ {
struct prefix_ipv4 p; struct prefix p;
struct route_node *rn; struct route_node *rn;
p.family = AF_INET; p.family = AF_INET;
p.prefixlen = IPV4_MAX_PREFIXLEN; p.prefixlen = IPV4_MAX_PREFIXLEN;
p.prefix = addr; p.u.prefix4 = addr;
rn = route_node_lookup(IF_OIFS_PARAMS(ifp), (struct prefix *)&p); rn = route_node_lookup(IF_OIFS_PARAMS(ifp), &p);
if (rn) { if (rn) {
route_unlock_node(rn); route_unlock_node(rn);
@ -279,49 +280,63 @@ int eigrp_if_up(struct eigrp_interface *ei)
/*Add connected entry to topology table*/ /*Add connected entry to topology table*/
struct prefix_ipv4 dest_addr;
dest_addr.family = AF_INET;
dest_addr.prefix = ei->connected->address->u.prefix4;
dest_addr.prefixlen = ei->connected->address->prefixlen;
apply_mask_ipv4(&dest_addr);
pe = eigrp_topology_table_lookup_ipv4(eigrp->topology_table,
&dest_addr);
if (pe == NULL) {
pe = eigrp_prefix_entry_new();
pe->serno = eigrp->serno;
pe->destination_ipv4 = prefix_ipv4_new();
prefix_copy((struct prefix *)pe->destination_ipv4,
(struct prefix *)&dest_addr);
pe->af = AF_INET;
pe->nt = EIGRP_TOPOLOGY_TYPE_CONNECTED;
pe->state = EIGRP_FSM_STATE_PASSIVE;
pe->fdistance = eigrp_calculate_metrics(eigrp, metric);
pe->req_action |= EIGRP_FSM_NEED_UPDATE;
eigrp_prefix_entry_add(eigrp->topology_table, pe);
listnode_add(eigrp->topology_changes_internalIPV4, pe);
}
ne = eigrp_neighbor_entry_new(); ne = eigrp_neighbor_entry_new();
ne->ei = ei; ne->ei = ei;
ne->reported_metric = metric; ne->reported_metric = metric;
ne->total_metric = metric; ne->total_metric = metric;
ne->distance = eigrp_calculate_metrics(eigrp, metric); ne->distance = eigrp_calculate_metrics(eigrp, metric);
ne->reported_distance = 0; ne->reported_distance = 0;
ne->prefix = pe;
ne->adv_router = eigrp->neighbor_self; ne->adv_router = eigrp->neighbor_self;
ne->flags = EIGRP_NEIGHBOR_ENTRY_SUCCESSOR_FLAG; ne->flags = EIGRP_NEIGHBOR_ENTRY_SUCCESSOR_FLAG;
eigrp_neighbor_entry_add(pe, ne);
for (ALL_LIST_ELEMENTS(eigrp->eiflist, node, nnode, ei2)) { struct prefix dest_addr;
if (ei2->nbrs->count != 0) {
dest_addr.family = AF_INET;
dest_addr.u.prefix4 = ei->connected->address->u.prefix4;
dest_addr.prefixlen = ei->connected->address->prefixlen;
apply_mask(&dest_addr);
pe = eigrp_topology_table_lookup_ipv4(eigrp->topology_table,
&dest_addr);
if (pe == NULL) {
pe = eigrp_prefix_entry_new();
pe->serno = eigrp->serno;
pe->destination = (struct prefix *)prefix_ipv4_new();
prefix_copy(pe->destination, &dest_addr);
pe->af = AF_INET;
pe->nt = EIGRP_TOPOLOGY_TYPE_CONNECTED;
ne->prefix = pe;
pe->reported_metric = metric;
pe->state = EIGRP_FSM_STATE_PASSIVE;
pe->fdistance = eigrp_calculate_metrics(eigrp, metric);
pe->req_action |= EIGRP_FSM_NEED_UPDATE;
eigrp_prefix_entry_add(eigrp->topology_table, pe);
listnode_add(eigrp->topology_changes_internalIPV4, pe);
eigrp_neighbor_entry_add(pe, ne);
for (ALL_LIST_ELEMENTS(eigrp->eiflist, node, nnode, ei2)) {
eigrp_update_send(ei2); eigrp_update_send(ei2);
} }
}
pe->req_action &= ~EIGRP_FSM_NEED_UPDATE; pe->req_action &= ~EIGRP_FSM_NEED_UPDATE;
listnode_delete(eigrp->topology_changes_internalIPV4, pe); listnode_delete(eigrp->topology_changes_internalIPV4, pe);
} else {
struct eigrp_fsm_action_message msg;
ne->prefix = pe;
eigrp_neighbor_entry_add(pe, ne);
msg.packet_type = EIGRP_OPC_UPDATE;
msg.eigrp = eigrp;
msg.data_type = EIGRP_CONNECTED;
msg.adv_router = NULL;
msg.entry = ne;
msg.prefix = pe;
eigrp_fsm_event(&msg);
}
return 1; return 1;
} }
@ -416,7 +431,7 @@ u_char eigrp_default_iftype(struct interface *ifp)
void eigrp_if_free(struct eigrp_interface *ei, int source) void eigrp_if_free(struct eigrp_interface *ei, int source)
{ {
struct prefix_ipv4 dest_addr; struct prefix dest_addr;
struct eigrp_prefix_entry *pe; struct eigrp_prefix_entry *pe;
struct eigrp *eigrp = eigrp_lookup(); struct eigrp *eigrp = eigrp_lookup();
@ -425,10 +440,8 @@ void eigrp_if_free(struct eigrp_interface *ei, int source)
eigrp_hello_send(ei, EIGRP_HELLO_GRACEFUL_SHUTDOWN, NULL); eigrp_hello_send(ei, EIGRP_HELLO_GRACEFUL_SHUTDOWN, NULL);
} }
dest_addr.family = AF_INET; dest_addr = *ei->connected->address;
dest_addr.prefix = ei->connected->address->u.prefix4; apply_mask(&dest_addr);
dest_addr.prefixlen = ei->connected->address->prefixlen;
apply_mask_ipv4(&dest_addr);
pe = eigrp_topology_table_lookup_ipv4(eigrp->topology_table, pe = eigrp_topology_table_lookup_ipv4(eigrp->topology_table,
&dest_addr); &dest_addr);
if (pe) if (pe)
@ -532,11 +545,11 @@ struct eigrp_interface *eigrp_if_lookup_recv_if(struct eigrp *eigrp,
struct interface *ifp) struct interface *ifp)
{ {
struct route_node *rn; struct route_node *rn;
struct prefix_ipv4 addr; struct prefix addr;
struct eigrp_interface *ei, *match; struct eigrp_interface *ei, *match;
addr.family = AF_INET; addr.family = AF_INET;
addr.prefix = src; addr.u.prefix4 = src;
addr.prefixlen = IPV4_MAX_BITLEN; addr.prefixlen = IPV4_MAX_BITLEN;
match = NULL; match = NULL;
@ -551,7 +564,7 @@ struct eigrp_interface *eigrp_if_lookup_recv_if(struct eigrp *eigrp,
continue; continue;
if (prefix_match(CONNECTED_PREFIX(ei->connected), if (prefix_match(CONNECTED_PREFIX(ei->connected),
(struct prefix *)&addr)) { &addr)) {
if ((match == NULL) || (match->address->prefixlen if ((match == NULL) || (match->address->prefixlen
< ei->address->prefixlen)) < ei->address->prefixlen))
match = ei; match = ei;

View File

@ -357,3 +357,11 @@ void eigrp_nbr_hard_restart(struct eigrp_neighbor *nbr, struct vty *vty)
/* delete neighbor */ /* delete neighbor */
eigrp_nbr_delete(nbr); eigrp_nbr_delete(nbr);
} }
int eigrp_nbr_split_horizon_check(struct eigrp_neighbor_entry *ne, struct eigrp_interface *ei)
{
if (ne->distance == EIGRP_MAX_METRIC)
return 0;
return (ne->ei == ei);
}

View File

@ -53,4 +53,6 @@ extern struct eigrp_neighbor *eigrp_nbr_lookup_by_addr_process(struct eigrp *,
struct in_addr); struct in_addr);
extern void eigrp_nbr_hard_restart(struct eigrp_neighbor *nbr, struct vty *vty); extern void eigrp_nbr_hard_restart(struct eigrp_neighbor *nbr, struct vty *vty);
extern int eigrp_nbr_split_horizon_check(struct eigrp_neighbor_entry *ne,
struct eigrp_interface *ei);
#endif /* _ZEBRA_EIGRP_NEIGHBOR_H */ #endif /* _ZEBRA_EIGRP_NEIGHBOR_H */

View File

@ -229,7 +229,7 @@ int eigrp_if_drop_allspfrouters(struct eigrp *top, struct prefix *p,
return ret; return ret;
} }
int eigrp_network_set(struct eigrp *eigrp, struct prefix_ipv4 *p) int eigrp_network_set(struct eigrp *eigrp, struct prefix *p)
{ {
struct route_node *rn; struct route_node *rn;
struct interface *ifp; struct interface *ifp;
@ -242,7 +242,7 @@ int eigrp_network_set(struct eigrp *eigrp, struct prefix_ipv4 *p)
return 0; return 0;
} }
struct prefix_ipv4 *pref = prefix_ipv4_new(); struct prefix *pref = prefix_new();
PREFIX_COPY_IPV4(pref, p); PREFIX_COPY_IPV4(pref, p);
rn->info = (void *)pref; rn->info = (void *)pref;
@ -253,7 +253,7 @@ int eigrp_network_set(struct eigrp *eigrp, struct prefix_ipv4 *p)
/* Get target interface. */ /* Get target interface. */
for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), node, ifp)) { for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), node, ifp)) {
zlog_debug("Setting up %s", ifp->name); zlog_debug("Setting up %s", ifp->name);
eigrp_network_run_interface(eigrp, (struct prefix *)p, ifp); eigrp_network_run_interface(eigrp, p, ifp);
} }
return 1; return 1;
} }
@ -334,21 +334,21 @@ void eigrp_if_update(struct interface *ifp)
} }
} }
int eigrp_network_unset(struct eigrp *eigrp, struct prefix_ipv4 *p) int eigrp_network_unset(struct eigrp *eigrp, struct prefix *p)
{ {
struct route_node *rn; struct route_node *rn;
struct listnode *node, *nnode; struct listnode *node, *nnode;
struct eigrp_interface *ei; struct eigrp_interface *ei;
struct prefix *pref; struct prefix *pref;
rn = route_node_lookup(eigrp->networks, (struct prefix *)p); rn = route_node_lookup(eigrp->networks, p);
if (rn == NULL) if (rn == NULL)
return 0; return 0;
pref = rn->info; pref = rn->info;
route_unlock_node(rn); route_unlock_node(rn);
if (!IPV4_ADDR_SAME(&pref->u.prefix4, &p->prefix)) if (!IPV4_ADDR_SAME(&pref->u.prefix4, &p->u.prefix4))
return 0; return 0;
prefix_ipv4_free(rn->info); prefix_ipv4_free(rn->info);

View File

@ -32,8 +32,8 @@
extern int eigrp_sock_init(void); extern int eigrp_sock_init(void);
extern int eigrp_if_ipmulticast(struct eigrp *, struct prefix *, unsigned int); extern int eigrp_if_ipmulticast(struct eigrp *, struct prefix *, unsigned int);
extern int eigrp_network_set(struct eigrp *, struct prefix_ipv4 *); extern int eigrp_network_set(struct eigrp *eigrp, struct prefix *p);
extern int eigrp_network_unset(struct eigrp *eigrp, struct prefix_ipv4 *p); extern int eigrp_network_unset(struct eigrp *eigrp, struct prefix *p);
extern int eigrp_hello_timer(struct thread *); extern int eigrp_hello_timer(struct thread *);
extern void eigrp_if_update(struct interface *); extern void eigrp_if_update(struct interface *);

View File

@ -1101,6 +1101,16 @@ struct eigrp_packet *eigrp_packet_duplicate(struct eigrp_packet *old,
return new; return new;
} }
static struct TLV_IPv4_Internal_type *eigrp_IPv4_InternalTLV_new()
{
struct TLV_IPv4_Internal_type *new;
new = XCALLOC(MTYPE_EIGRP_IPV4_INT_TLV,
sizeof(struct TLV_IPv4_Internal_type));
return new;
}
struct TLV_IPv4_Internal_type *eigrp_read_ipv4_tlv(struct stream *s) struct TLV_IPv4_Internal_type *eigrp_read_ipv4_tlv(struct stream *s)
{ {
struct TLV_IPv4_Internal_type *tlv; struct TLV_IPv4_Internal_type *tlv;
@ -1157,21 +1167,21 @@ u_int16_t eigrp_add_internalTLV_to_stream(struct stream *s,
u_int16_t length; u_int16_t length;
stream_putw(s, EIGRP_TLV_IPv4_INT); stream_putw(s, EIGRP_TLV_IPv4_INT);
if (pe->destination_ipv4->prefixlen <= 8) { if (pe->destination->prefixlen <= 8) {
stream_putw(s, 0x001A); stream_putw(s, 0x001A);
length = 0x001A; length = 0x001A;
} }
if ((pe->destination_ipv4->prefixlen > 8) if ((pe->destination->prefixlen > 8)
&& (pe->destination_ipv4->prefixlen <= 16)) { && (pe->destination->prefixlen <= 16)) {
stream_putw(s, 0x001B); stream_putw(s, 0x001B);
length = 0x001B; length = 0x001B;
} }
if ((pe->destination_ipv4->prefixlen > 16) if ((pe->destination->prefixlen > 16)
&& (pe->destination_ipv4->prefixlen <= 24)) { && (pe->destination->prefixlen <= 24)) {
stream_putw(s, 0x001C); stream_putw(s, 0x001C);
length = 0x001C; length = 0x001C;
} }
if (pe->destination_ipv4->prefixlen > 24) { if (pe->destination->prefixlen > 24) {
stream_putw(s, 0x001D); stream_putw(s, 0x001D);
length = 0x001D; length = 0x001D;
} }
@ -1190,34 +1200,18 @@ u_int16_t eigrp_add_internalTLV_to_stream(struct stream *s,
stream_putc(s, pe->reported_metric.tag); stream_putc(s, pe->reported_metric.tag);
stream_putc(s, pe->reported_metric.flags); stream_putc(s, pe->reported_metric.flags);
stream_putc(s, pe->destination_ipv4->prefixlen); stream_putc(s, pe->destination->prefixlen);
if (pe->destination_ipv4->prefixlen <= 8) { stream_putc(s, pe->destination->u.prefix4.s_addr & 0xFF);
stream_putc(s, pe->destination_ipv4->prefix.s_addr & 0xFF); if (pe->destination->prefixlen > 8)
}
if ((pe->destination_ipv4->prefixlen > 8)
&& (pe->destination_ipv4->prefixlen <= 16)) {
stream_putc(s, pe->destination_ipv4->prefix.s_addr & 0xFF);
stream_putc(s, stream_putc(s,
(pe->destination_ipv4->prefix.s_addr >> 8) & 0xFF); (pe->destination->u.prefix4.s_addr >> 8) & 0xFF);
} if (pe->destination->prefixlen > 16)
if ((pe->destination_ipv4->prefixlen > 16)
&& (pe->destination_ipv4->prefixlen <= 24)) {
stream_putc(s, pe->destination_ipv4->prefix.s_addr & 0xFF);
stream_putc(s, stream_putc(s,
(pe->destination_ipv4->prefix.s_addr >> 8) & 0xFF); (pe->destination->u.prefix4.s_addr >> 16) & 0xFF);
if (pe->destination->prefixlen > 24)
stream_putc(s, stream_putc(s,
(pe->destination_ipv4->prefix.s_addr >> 16) & 0xFF); (pe->destination->u.prefix4.s_addr >> 24) & 0xFF);
}
if (pe->destination_ipv4->prefixlen > 24) {
stream_putc(s, pe->destination_ipv4->prefix.s_addr & 0xFF);
stream_putc(s,
(pe->destination_ipv4->prefix.s_addr >> 8) & 0xFF);
stream_putc(s,
(pe->destination_ipv4->prefix.s_addr >> 16) & 0xFF);
stream_putc(s,
(pe->destination_ipv4->prefix.s_addr >> 24) & 0xFF);
}
return length; return length;
} }
@ -1332,16 +1326,6 @@ void eigrp_authTLV_SHA256_free(struct TLV_SHA256_Authentication_Type *authTLV)
XFREE(MTYPE_EIGRP_AUTH_SHA256_TLV, authTLV); XFREE(MTYPE_EIGRP_AUTH_SHA256_TLV, authTLV);
} }
struct TLV_IPv4_Internal_type *eigrp_IPv4_InternalTLV_new()
{
struct TLV_IPv4_Internal_type *new;
new = XCALLOC(MTYPE_EIGRP_IPV4_INT_TLV,
sizeof(struct TLV_IPv4_Internal_type));
return new;
}
void eigrp_IPv4_InternalTLV_free( void eigrp_IPv4_InternalTLV_free(
struct TLV_IPv4_Internal_type *IPv4_InternalTLV) struct TLV_IPv4_Internal_type *IPv4_InternalTLV)
{ {

View File

@ -152,7 +152,6 @@ extern int eigrp_check_sha256_digest(struct stream *,
struct eigrp_neighbor *, u_char); struct eigrp_neighbor *, u_char);
extern struct TLV_IPv4_Internal_type *eigrp_IPv4_InternalTLV_new(void);
extern void eigrp_IPv4_InternalTLV_free(struct TLV_IPv4_Internal_type *); extern void eigrp_IPv4_InternalTLV_free(struct TLV_IPv4_Internal_type *);
extern struct TLV_Sequence_Type *eigrp_SequenceTLV_new(void); extern struct TLV_Sequence_Type *eigrp_SequenceTLV_new(void);

View File

@ -91,7 +91,7 @@ void eigrp_query_receive(struct eigrp *eigrp, struct ip *iph,
{ {
struct eigrp_neighbor *nbr; struct eigrp_neighbor *nbr;
struct TLV_IPv4_Internal_type *tlv; struct TLV_IPv4_Internal_type *tlv;
struct prefix_ipv4 dest_addr; struct prefix dest_addr;
u_int16_t type; u_int16_t type;
u_int16_t length; u_int16_t length;
@ -116,7 +116,7 @@ void eigrp_query_receive(struct eigrp *eigrp, struct ip *iph,
tlv = eigrp_read_ipv4_tlv(s); tlv = eigrp_read_ipv4_tlv(s);
dest_addr.family = AF_INET; dest_addr.family = AF_INET;
dest_addr.prefix = tlv->destination; dest_addr.u.prefix4 = tlv->destination;
dest_addr.prefixlen = tlv->prefix_length; dest_addr.prefixlen = tlv->prefix_length;
struct eigrp_prefix_entry *dest = struct eigrp_prefix_entry *dest =
eigrp_topology_table_lookup_ipv4( eigrp_topology_table_lookup_ipv4(
@ -125,22 +125,18 @@ void eigrp_query_receive(struct eigrp *eigrp, struct ip *iph,
/* If the destination exists (it should, but one never /* If the destination exists (it should, but one never
* know)*/ * know)*/
if (dest != NULL) { if (dest != NULL) {
struct eigrp_fsm_action_message *msg; struct eigrp_fsm_action_message msg;
msg = XCALLOC(MTYPE_EIGRP_FSM_MSG,
sizeof(struct
eigrp_fsm_action_message));
struct eigrp_neighbor_entry *entry = struct eigrp_neighbor_entry *entry =
eigrp_prefix_entry_lookup(dest->entries, eigrp_prefix_entry_lookup(dest->entries,
nbr); nbr);
msg->packet_type = EIGRP_OPC_QUERY; msg.packet_type = EIGRP_OPC_QUERY;
msg->eigrp = eigrp; msg.eigrp = eigrp;
msg->data_type = EIGRP_TLV_IPv4_INT; msg.data_type = EIGRP_INT;
msg->adv_router = nbr; msg.adv_router = nbr;
msg->data.ipv4_int_type = tlv; msg.metrics = tlv->metric;
msg->entry = entry; msg.entry = entry;
msg->prefix = dest; msg.prefix = dest;
int event = eigrp_get_fsm_event(msg); eigrp_fsm_event(&msg);
eigrp_fsm_event(msg, event);
} }
eigrp_IPv4_InternalTLV_free(tlv); eigrp_IPv4_InternalTLV_free(tlv);
break; break;

View File

@ -87,19 +87,19 @@ void eigrp_send_reply(struct eigrp_neighbor *nbr, struct eigrp_prefix_entry *pe)
/* Check if any list fits */ /* Check if any list fits */
if ((alist if ((alist
&& access_list_apply(alist, (struct prefix *)pe2->destination_ipv4) && access_list_apply(alist, pe2->destination)
== FILTER_DENY) == FILTER_DENY)
|| (plist || (plist
&& prefix_list_apply(plist, && prefix_list_apply(plist,
(struct prefix *)pe2->destination_ipv4) pe2->destination)
== PREFIX_DENY) == PREFIX_DENY)
|| (alist_i || (alist_i
&& access_list_apply(alist_i, && access_list_apply(alist_i,
(struct prefix *)pe2->destination_ipv4) pe2->destination)
== FILTER_DENY) == FILTER_DENY)
|| (plist_i || (plist_i
&& prefix_list_apply(plist_i, && prefix_list_apply(plist_i,
(struct prefix *)pe2->destination_ipv4) pe2->destination)
== PREFIX_DENY)) { == PREFIX_DENY)) {
zlog_info("REPLY SEND: Setting Metric to max"); zlog_info("REPLY SEND: Setting Metric to max");
pe2->reported_metric.delay = EIGRP_MAX_METRIC; pe2->reported_metric.delay = EIGRP_MAX_METRIC;
@ -179,14 +179,14 @@ void eigrp_reply_receive(struct eigrp *eigrp, struct ip *iph,
while (s->endp > s->getp) { while (s->endp > s->getp) {
type = stream_getw(s); type = stream_getw(s);
if (type == EIGRP_TLV_IPv4_INT) { if (type == EIGRP_TLV_IPv4_INT) {
struct prefix_ipv4 dest_addr; struct prefix dest_addr;
stream_set_getp(s, s->getp - sizeof(u_int16_t)); stream_set_getp(s, s->getp - sizeof(u_int16_t));
tlv = eigrp_read_ipv4_tlv(s); tlv = eigrp_read_ipv4_tlv(s);
dest_addr.family = AF_INET; dest_addr.family = AF_INET;
dest_addr.prefix = tlv->destination; dest_addr.u.prefix4 = tlv->destination;
dest_addr.prefixlen = tlv->prefix_length; dest_addr.prefixlen = tlv->prefix_length;
struct eigrp_prefix_entry *dest = struct eigrp_prefix_entry *dest =
eigrp_topology_table_lookup_ipv4( eigrp_topology_table_lookup_ipv4(
@ -196,9 +196,7 @@ void eigrp_reply_receive(struct eigrp *eigrp, struct ip *iph,
*/ */
assert(dest); assert(dest);
struct eigrp_fsm_action_message *msg; struct eigrp_fsm_action_message msg;
msg = XCALLOC(MTYPE_EIGRP_FSM_MSG,
sizeof(struct eigrp_fsm_action_message));
struct eigrp_neighbor_entry *entry = struct eigrp_neighbor_entry *entry =
eigrp_prefix_entry_lookup(dest->entries, nbr); eigrp_prefix_entry_lookup(dest->entries, nbr);
@ -237,15 +235,14 @@ void eigrp_reply_receive(struct eigrp *eigrp, struct ip *iph,
* End of filtering * End of filtering
*/ */
msg->packet_type = EIGRP_OPC_REPLY; msg.packet_type = EIGRP_OPC_REPLY;
msg->eigrp = eigrp; msg.eigrp = eigrp;
msg->data_type = EIGRP_TLV_IPv4_INT; msg.data_type = EIGRP_INT;
msg->adv_router = nbr; msg.adv_router = nbr;
msg->data.ipv4_int_type = tlv; msg.metrics = tlv->metric;
msg->entry = entry; msg.entry = entry;
msg->prefix = dest; msg.prefix = dest;
int event = eigrp_get_fsm_event(msg); eigrp_fsm_event(&msg);
eigrp_fsm_event(msg, event);
eigrp_IPv4_InternalTLV_free(tlv); eigrp_IPv4_InternalTLV_free(tlv);

View File

@ -78,14 +78,14 @@ void eigrp_siaquery_receive(struct eigrp *eigrp, struct ip *iph,
while (s->endp > s->getp) { while (s->endp > s->getp) {
type = stream_getw(s); type = stream_getw(s);
if (type == EIGRP_TLV_IPv4_INT) { if (type == EIGRP_TLV_IPv4_INT) {
struct prefix_ipv4 dest_addr; struct prefix dest_addr;
stream_set_getp(s, s->getp - sizeof(u_int16_t)); stream_set_getp(s, s->getp - sizeof(u_int16_t));
tlv = eigrp_read_ipv4_tlv(s); tlv = eigrp_read_ipv4_tlv(s);
dest_addr.family = AFI_IP; dest_addr.family = AFI_IP;
dest_addr.prefix = tlv->destination; dest_addr.u.prefix4 = tlv->destination;
dest_addr.prefixlen = tlv->prefix_length; dest_addr.prefixlen = tlv->prefix_length;
struct eigrp_prefix_entry *dest = struct eigrp_prefix_entry *dest =
eigrp_topology_table_lookup_ipv4( eigrp_topology_table_lookup_ipv4(
@ -94,22 +94,18 @@ void eigrp_siaquery_receive(struct eigrp *eigrp, struct ip *iph,
/* If the destination exists (it should, but one never /* If the destination exists (it should, but one never
* know)*/ * know)*/
if (dest != NULL) { if (dest != NULL) {
struct eigrp_fsm_action_message *msg; struct eigrp_fsm_action_message msg;
msg = XCALLOC(MTYPE_EIGRP_FSM_MSG,
sizeof(struct
eigrp_fsm_action_message));
struct eigrp_neighbor_entry *entry = struct eigrp_neighbor_entry *entry =
eigrp_prefix_entry_lookup(dest->entries, eigrp_prefix_entry_lookup(dest->entries,
nbr); nbr);
msg->packet_type = EIGRP_OPC_SIAQUERY; msg.packet_type = EIGRP_OPC_SIAQUERY;
msg->eigrp = eigrp; msg.eigrp = eigrp;
msg->data_type = EIGRP_TLV_IPv4_INT; msg.data_type = EIGRP_INT;
msg->adv_router = nbr; msg.adv_router = nbr;
msg->data.ipv4_int_type = tlv; msg.metrics = tlv->metric;
msg->entry = entry; msg.entry = entry;
msg->prefix = dest; msg.prefix = dest;
int event = eigrp_get_fsm_event(msg); eigrp_fsm_event(&msg);
eigrp_fsm_event(msg, event);
} }
eigrp_IPv4_InternalTLV_free(tlv); eigrp_IPv4_InternalTLV_free(tlv);
} }

View File

@ -77,14 +77,14 @@ void eigrp_siareply_receive(struct eigrp *eigrp, struct ip *iph,
while (s->endp > s->getp) { while (s->endp > s->getp) {
type = stream_getw(s); type = stream_getw(s);
if (type == EIGRP_TLV_IPv4_INT) { if (type == EIGRP_TLV_IPv4_INT) {
struct prefix_ipv4 dest_addr; struct prefix dest_addr;
stream_set_getp(s, s->getp - sizeof(u_int16_t)); stream_set_getp(s, s->getp - sizeof(u_int16_t));
tlv = eigrp_read_ipv4_tlv(s); tlv = eigrp_read_ipv4_tlv(s);
dest_addr.family = AFI_IP; dest_addr.family = AFI_IP;
dest_addr.prefix = tlv->destination; dest_addr.u.prefix4 = tlv->destination;
dest_addr.prefixlen = tlv->prefix_length; dest_addr.prefixlen = tlv->prefix_length;
struct eigrp_prefix_entry *dest = struct eigrp_prefix_entry *dest =
eigrp_topology_table_lookup_ipv4( eigrp_topology_table_lookup_ipv4(
@ -93,22 +93,18 @@ void eigrp_siareply_receive(struct eigrp *eigrp, struct ip *iph,
/* If the destination exists (it should, but one never /* If the destination exists (it should, but one never
* know)*/ * know)*/
if (dest != NULL) { if (dest != NULL) {
struct eigrp_fsm_action_message *msg; struct eigrp_fsm_action_message msg;
msg = XCALLOC(MTYPE_EIGRP_FSM_MSG,
sizeof(struct
eigrp_fsm_action_message));
struct eigrp_neighbor_entry *entry = struct eigrp_neighbor_entry *entry =
eigrp_prefix_entry_lookup(dest->entries, eigrp_prefix_entry_lookup(dest->entries,
nbr); nbr);
msg->packet_type = EIGRP_OPC_SIAQUERY; msg.packet_type = EIGRP_OPC_SIAQUERY;
msg->eigrp = eigrp; msg.eigrp = eigrp;
msg->data_type = EIGRP_TLV_IPv4_INT; msg.data_type = EIGRP_INT;
msg->adv_router = nbr; msg.adv_router = nbr;
msg->data.ipv4_int_type = tlv; msg.metrics = tlv->metric;
msg->entry = entry; msg.entry = entry;
msg->prefix = dest; msg.prefix = dest;
int event = eigrp_get_fsm_event(msg); eigrp_fsm_event(&msg);
eigrp_fsm_event(msg, event);
} }
eigrp_IPv4_InternalTLV_free(tlv); eigrp_IPv4_InternalTLV_free(tlv);
} }

View File

@ -469,10 +469,7 @@ struct eigrp_prefix_entry {
u_char af; // address family u_char af; // address family
u_char req_action; // required action u_char req_action; // required action
struct prefix_ipv4 struct prefix *destination;
*destination_ipv4; // pointer to struct with ipv4 address
struct prefix_ipv6
*destination_ipv6; // pointer to struct with ipv6 address
// If network type is REMOTE_EXTERNAL, pointer will have reference to // If network type is REMOTE_EXTERNAL, pointer will have reference to
// its external TLV // its external TLV
@ -499,6 +496,11 @@ struct eigrp_neighbor_entry {
}; };
//--------------------------------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------------------------------
typedef enum {
EIGRP_CONNECTED,
EIGRP_INT,
EIGRP_EXT,
} msg_data_t;
/* EIGRP Finite State Machine */ /* EIGRP Finite State Machine */
@ -508,11 +510,8 @@ struct eigrp_fsm_action_message {
struct eigrp_neighbor *adv_router; // advertising neighbor struct eigrp_neighbor *adv_router; // advertising neighbor
struct eigrp_neighbor_entry *entry; struct eigrp_neighbor_entry *entry;
struct eigrp_prefix_entry *prefix; struct eigrp_prefix_entry *prefix;
int data_type; // internal or external tlv type msg_data_t data_type; // internal or external tlv type
union { struct eigrp_metrics metrics;
struct TLV_IPv4_External_type *ipv4_ext_data;
struct TLV_IPv4_Internal_type *ipv4_int_type;
} data;
}; };
#endif /* _ZEBRA_EIGRP_STRUCTURES_H_ */ #endif /* _ZEBRA_EIGRP_STRUCTURES_H_ */

View File

@ -81,25 +81,18 @@ static int eigrp_prefix_entry_cmp(struct eigrp_prefix_entry *node1,
{ {
if (node1->af == AF_INET) { if (node1->af == AF_INET) {
if (node2->af == AF_INET) { if (node2->af == AF_INET) {
if (node1->destination_ipv4->prefix.s_addr if (node1->destination->u.prefix4.s_addr
< node2->destination_ipv4->prefix.s_addr) { < node2->destination->u.prefix4.s_addr)
return -1; // if it belong above node2 return -1;
} else { if (node1->destination->u.prefix4.s_addr
if (node1->destination_ipv4->prefix.s_addr > node2->destination->u.prefix4.s_addr)
> node2->destination_ipv4->prefix.s_addr) { return 1;
return 1; // if it belongs under node2 else
} else { return 0;
return 0; // same value... ERROR...in } else
// case of adding same prefix
// again
}
}
} else {
return 1; return 1;
} } else
} else { // TODO check if the prefix dont exists return 1;
return 1; // add to end
}
} }
/* /*
@ -125,8 +118,7 @@ struct eigrp_prefix_entry *eigrp_prefix_entry_new()
new->rij = list_new(); new->rij = list_new();
new->entries->cmp = (int (*)(void *, void *))eigrp_neighbor_entry_cmp; new->entries->cmp = (int (*)(void *, void *))eigrp_neighbor_entry_cmp;
new->distance = new->fdistance = new->rdistance = EIGRP_MAX_METRIC; new->distance = new->fdistance = new->rdistance = EIGRP_MAX_METRIC;
new->destination_ipv4 = NULL; new->destination = NULL;
new->destination_ipv6 = NULL;
return new; return new;
} }
@ -137,9 +129,8 @@ struct eigrp_prefix_entry *eigrp_prefix_entry_new()
static int eigrp_neighbor_entry_cmp(struct eigrp_neighbor_entry *entry1, static int eigrp_neighbor_entry_cmp(struct eigrp_neighbor_entry *entry1,
struct eigrp_neighbor_entry *entry2) struct eigrp_neighbor_entry *entry2)
{ {
if (entry1->distance if (entry1->distance < entry2->distance)
< entry2->distance) // parameter used in list_add_sort () return -1;
return -1; // actually set to sort by distance
if (entry1->distance > entry2->distance) if (entry1->distance > entry2->distance)
return 1; return 1;
@ -205,7 +196,7 @@ void eigrp_neighbor_entry_add(struct eigrp_prefix_entry *node,
listnode_add_sort(node->entries, entry); listnode_add_sort(node->entries, entry);
entry->prefix = node; entry->prefix = node;
eigrp_zebra_route_add(node->destination_ipv4, l); eigrp_zebra_route_add(node->destination, l);
} }
list_delete(l); list_delete(l);
@ -230,7 +221,7 @@ void eigrp_prefix_entry_delete(struct list *topology,
list_free(node->entries); list_free(node->entries);
list_free(node->rij); list_free(node->rij);
listnode_delete(topology, node); listnode_delete(topology, node);
eigrp_zebra_route_delete(node->destination_ipv4); eigrp_zebra_route_delete(node->destination);
XFREE(MTYPE_EIGRP_PREFIX_ENTRY, node); XFREE(MTYPE_EIGRP_PREFIX_ENTRY, node);
} }
} }
@ -243,7 +234,7 @@ void eigrp_neighbor_entry_delete(struct eigrp_prefix_entry *node,
{ {
if (listnode_lookup(node->entries, entry) != NULL) { if (listnode_lookup(node->entries, entry) != NULL) {
listnode_delete(node->entries, entry); listnode_delete(node->entries, entry);
eigrp_zebra_route_delete(node->destination_ipv4); eigrp_zebra_route_delete(node->destination);
XFREE(MTYPE_EIGRP_NEIGHBOR_ENTRY, entry); XFREE(MTYPE_EIGRP_NEIGHBOR_ENTRY, entry);
} }
} }
@ -270,16 +261,12 @@ unsigned int eigrp_topology_table_isempty(struct list *topology)
struct eigrp_prefix_entry * struct eigrp_prefix_entry *
eigrp_topology_table_lookup_ipv4(struct list *topology_table, eigrp_topology_table_lookup_ipv4(struct list *topology_table,
struct prefix_ipv4 *address) struct prefix *address)
{ {
struct eigrp_prefix_entry *data; struct eigrp_prefix_entry *data;
struct listnode *node; struct listnode *node;
for (ALL_LIST_ELEMENTS_RO(topology_table, node, data)) { for (ALL_LIST_ELEMENTS_RO(topology_table, node, data)) {
if ((data->af == AF_INET) if (prefix_same(data->destination, address))
&& (data->destination_ipv4->prefix.s_addr
== address->prefix.s_addr)
&& (data->destination_ipv4->prefixlen
== address->prefixlen))
return data; return data;
} }
@ -380,37 +367,56 @@ enum metric_change eigrp_topology_update_distance(struct eigrp_fsm_action_messag
struct eigrp_prefix_entry *prefix = msg->prefix; struct eigrp_prefix_entry *prefix = msg->prefix;
struct eigrp_neighbor_entry *entry = msg->entry; struct eigrp_neighbor_entry *entry = msg->entry;
enum metric_change change = METRIC_SAME; enum metric_change change = METRIC_SAME;
u_int32_t new_reported_distance;
assert(entry); assert(entry);
struct TLV_IPv4_External_type *ext_data = NULL; switch(msg->data_type) {
struct TLV_IPv4_Internal_type *int_data = NULL; case EIGRP_CONNECTED:
if (msg->data_type == EIGRP_TLV_IPv4_INT) { if (prefix->nt == EIGRP_TOPOLOGY_TYPE_CONNECTED)
u_int32_t new_reported_distance; return change;
int_data = msg->data.ipv4_int_type; change = METRIC_DECREASE;
if (eigrp_metrics_is_same(int_data->metric, break;
case EIGRP_INT:
if (prefix->nt == EIGRP_TOPOLOGY_TYPE_CONNECTED) {
change = METRIC_INCREASE;
goto distance_done;
}
if (eigrp_metrics_is_same(msg->metrics,
entry->reported_metric)) { entry->reported_metric)) {
return change; // No change return change; // No change
} }
new_reported_distance = eigrp_calculate_metrics(eigrp, new_reported_distance = eigrp_calculate_metrics(eigrp,
int_data->metric); msg->metrics);
if (entry->reported_distance < new_reported_distance) if (entry->reported_distance < new_reported_distance) {
change = METRIC_INCREASE; change = METRIC_INCREASE;
else goto distance_done;
} else
change = METRIC_DECREASE; change = METRIC_DECREASE;
entry->reported_metric = int_data->metric; entry->reported_metric = msg->metrics;
entry->reported_distance = new_reported_distance; entry->reported_distance = new_reported_distance;
eigrp_calculate_metrics(eigrp, int_data->metric); eigrp_calculate_metrics(eigrp, msg->metrics);
entry->distance = eigrp_calculate_total_metrics(eigrp, entry); entry->distance = eigrp_calculate_total_metrics(eigrp, entry);
} else { break;
ext_data = msg->data.ipv4_ext_data; case EIGRP_EXT:
if (eigrp_metrics_is_same(ext_data->metric, if (prefix->nt == EIGRP_TOPOLOGY_TYPE_REMOTE_EXTERNAL) {
entry->reported_metric)) if (eigrp_metrics_is_same(msg->metrics,
return change; entry->reported_metric))
return change;
} else {
change = METRIC_INCREASE;
goto distance_done;
}
break;
default:
zlog_err("%s: Please implement handler", __PRETTY_FUNCTION__);
break;
} }
distance_done:
/* /*
* Move to correct position in list according to new distance * Move to correct position in list according to new distance
*/ */
@ -464,13 +470,14 @@ void eigrp_update_routing_table(struct eigrp_prefix_entry *prefix)
struct eigrp_neighbor_entry *entry; struct eigrp_neighbor_entry *entry;
if (successors) { if (successors) {
eigrp_zebra_route_add(prefix->destination_ipv4, successors); eigrp_zebra_route_add(prefix->destination,
successors);
for (ALL_LIST_ELEMENTS_RO(successors, node, entry)) for (ALL_LIST_ELEMENTS_RO(successors, node, entry))
entry->flags |= EIGRP_NEIGHBOR_ENTRY_INTABLE_FLAG; entry->flags |= EIGRP_NEIGHBOR_ENTRY_INTABLE_FLAG;
list_delete(successors); list_delete(successors);
} else { } else {
eigrp_zebra_route_delete(prefix->destination_ipv4); eigrp_zebra_route_delete(prefix->destination);
for (ALL_LIST_ELEMENTS_RO(prefix->entries, node, entry)) for (ALL_LIST_ELEMENTS_RO(prefix->entries, node, entry))
entry->flags &= ~EIGRP_NEIGHBOR_ENTRY_INTABLE_FLAG; entry->flags &= ~EIGRP_NEIGHBOR_ENTRY_INTABLE_FLAG;
} }
@ -485,24 +492,19 @@ void eigrp_topology_neighbor_down(struct eigrp *eigrp,
for (ALL_LIST_ELEMENTS(eigrp->topology_table, node1, node11, prefix)) { for (ALL_LIST_ELEMENTS(eigrp->topology_table, node1, node11, prefix)) {
for (ALL_LIST_ELEMENTS(prefix->entries, node2, node22, entry)) { for (ALL_LIST_ELEMENTS(prefix->entries, node2, node22, entry)) {
if (entry->adv_router == nbr) { struct eigrp_fsm_action_message msg;
struct eigrp_fsm_action_message *msg;
msg = XCALLOC(MTYPE_EIGRP_FSM_MSG, if (entry->adv_router != nbr)
sizeof(struct continue;
eigrp_fsm_action_message));
struct TLV_IPv4_Internal_type *tlv = msg.metrics.delay = EIGRP_MAX_METRIC;
eigrp_IPv4_InternalTLV_new(); msg.packet_type = EIGRP_OPC_UPDATE;
tlv->metric.delay = EIGRP_MAX_METRIC; msg.eigrp = eigrp;
msg->packet_type = EIGRP_OPC_UPDATE; msg.data_type = EIGRP_INT;
msg->eigrp = eigrp; msg.adv_router = nbr;
msg->data_type = EIGRP_TLV_IPv4_INT; msg.entry = entry;
msg->adv_router = nbr; msg.prefix = prefix;
msg->data.ipv4_int_type = tlv; eigrp_fsm_event(&msg);
msg->entry = entry;
msg->prefix = prefix;
int event = eigrp_get_fsm_event(msg);
eigrp_fsm_event(msg, event);
}
} }
} }

View File

@ -49,7 +49,7 @@ extern void eigrp_neighbor_entry_delete(struct eigrp_prefix_entry *,
extern void eigrp_topology_delete_all(struct list *); extern void eigrp_topology_delete_all(struct list *);
extern unsigned int eigrp_topology_table_isempty(struct list *); extern unsigned int eigrp_topology_table_isempty(struct list *);
extern struct eigrp_prefix_entry * extern struct eigrp_prefix_entry *
eigrp_topology_table_lookup_ipv4(struct list *, struct prefix_ipv4 *); eigrp_topology_table_lookup_ipv4(struct list *, struct prefix *);
extern struct list *eigrp_topology_get_successor(struct eigrp_prefix_entry *); extern struct list *eigrp_topology_get_successor(struct eigrp_prefix_entry *);
extern struct list * extern struct list *
eigrp_topology_get_successor_max(struct eigrp_prefix_entry *pe, eigrp_topology_get_successor_max(struct eigrp_prefix_entry *pe,

View File

@ -112,47 +112,31 @@ static void eigrp_update_receive_GR_ask(struct eigrp *eigrp,
{ {
struct listnode *node1; struct listnode *node1;
struct eigrp_prefix_entry *prefix; struct eigrp_prefix_entry *prefix;
struct TLV_IPv4_Internal_type *tlv_max; struct eigrp_fsm_action_message fsm_msg;
/* iterate over all prefixes which weren't advertised by neighbor */ /* iterate over all prefixes which weren't advertised by neighbor */
for (ALL_LIST_ELEMENTS_RO(nbr_prefixes, node1, prefix)) { for (ALL_LIST_ELEMENTS_RO(nbr_prefixes, node1, prefix)) {
zlog_debug("GR receive: Neighbor not advertised %s/%d", char buffer[PREFIX_STRLEN];
inet_ntoa(prefix->destination_ipv4->prefix), zlog_debug("GR receive: Neighbor not advertised %s",
prefix->destination_ipv4->prefixlen); prefix2str(prefix->destination,
buffer, PREFIX_STRLEN));
/* create internal IPv4 TLV with infinite delay */ fsm_msg.metrics = prefix->reported_metric;
tlv_max = eigrp_IPv4_InternalTLV_new();
tlv_max->type = EIGRP_TLV_IPv4_INT;
tlv_max->length = 28U;
tlv_max->metric = prefix->reported_metric;
/* set delay to MAX */ /* set delay to MAX */
tlv_max->metric.delay = EIGRP_MAX_METRIC; fsm_msg.metrics.delay = EIGRP_MAX_METRIC;
tlv_max->destination = prefix->destination_ipv4->prefix;
tlv_max->prefix_length = prefix->destination_ipv4->prefixlen;
/* prepare message for FSM */
struct eigrp_fsm_action_message *fsm_msg;
fsm_msg = XCALLOC(MTYPE_EIGRP_FSM_MSG,
sizeof(struct eigrp_fsm_action_message));
struct eigrp_neighbor_entry *entry = struct eigrp_neighbor_entry *entry =
eigrp_prefix_entry_lookup(prefix->entries, nbr); eigrp_prefix_entry_lookup(prefix->entries, nbr);
fsm_msg->packet_type = EIGRP_OPC_UPDATE; fsm_msg.packet_type = EIGRP_OPC_UPDATE;
fsm_msg->eigrp = eigrp; fsm_msg.eigrp = eigrp;
fsm_msg->data_type = EIGRP_TLV_IPv4_INT; fsm_msg.data_type = EIGRP_INT;
fsm_msg->adv_router = nbr; fsm_msg.adv_router = nbr;
fsm_msg->data.ipv4_int_type = tlv_max; fsm_msg.entry = entry;
fsm_msg->entry = entry; fsm_msg.prefix = prefix;
fsm_msg->prefix = prefix;
/* send message to FSM */ /* send message to FSM */
int event = eigrp_get_fsm_event(fsm_msg); eigrp_fsm_event(&fsm_msg);
eigrp_fsm_event(fsm_msg, event);
/* free memory used by TLV */
eigrp_IPv4_InternalTLV_free(tlv_max);
} }
} }
@ -173,7 +157,7 @@ void eigrp_update_receive(struct eigrp *eigrp, struct ip *iph,
u_char same; u_char same;
struct access_list *alist; struct access_list *alist;
struct prefix_list *plist; struct prefix_list *plist;
struct prefix_ipv4 dest_addr; struct prefix dest_addr;
struct eigrp *e; struct eigrp *e;
u_char graceful_restart; u_char graceful_restart;
u_char graceful_restart_final; u_char graceful_restart_final;
@ -297,7 +281,7 @@ void eigrp_update_receive(struct eigrp *eigrp, struct ip *iph,
/*searching if destination exists */ /*searching if destination exists */
dest_addr.family = AF_INET; dest_addr.family = AF_INET;
dest_addr.prefix = tlv->destination; dest_addr.u.prefix4 = tlv->destination;
dest_addr.prefixlen = tlv->prefix_length; dest_addr.prefixlen = tlv->prefix_length;
struct eigrp_prefix_entry *dest = struct eigrp_prefix_entry *dest =
eigrp_topology_table_lookup_ipv4( eigrp_topology_table_lookup_ipv4(
@ -311,31 +295,26 @@ void eigrp_update_receive(struct eigrp *eigrp, struct ip *iph,
remove_received_prefix_gr(nbr_prefixes, remove_received_prefix_gr(nbr_prefixes,
dest); dest);
struct eigrp_fsm_action_message *msg; struct eigrp_fsm_action_message msg;
msg = XCALLOC(MTYPE_EIGRP_FSM_MSG,
sizeof(struct
eigrp_fsm_action_message));
struct eigrp_neighbor_entry *entry = struct eigrp_neighbor_entry *entry =
eigrp_prefix_entry_lookup(dest->entries, eigrp_prefix_entry_lookup(dest->entries,
nbr); nbr);
msg->packet_type = EIGRP_OPC_UPDATE; msg.packet_type = EIGRP_OPC_UPDATE;
msg->eigrp = eigrp; msg.eigrp = eigrp;
msg->data_type = EIGRP_TLV_IPv4_INT; msg.data_type = EIGRP_INT;
msg->adv_router = nbr; msg.adv_router = nbr;
msg->data.ipv4_int_type = tlv; msg.metrics = tlv->metric;
msg->entry = entry; msg.entry = entry;
msg->prefix = dest; msg.prefix = dest;
int event = eigrp_get_fsm_event(msg); eigrp_fsm_event(&msg);
eigrp_fsm_event(msg, event);
} else { } else {
/*Here comes topology information save*/ /*Here comes topology information save*/
pe = eigrp_prefix_entry_new(); pe = eigrp_prefix_entry_new();
pe->serno = eigrp->serno; pe->serno = eigrp->serno;
pe->destination_ipv4 = prefix_ipv4_new(); pe->destination = (struct prefix *)prefix_ipv4_new();
prefix_copy( prefix_copy(pe->destination,
(struct prefix *)pe->destination_ipv4, &dest_addr);
(struct prefix *)&dest_addr);
pe->af = AF_INET; pe->af = AF_INET;
pe->state = EIGRP_FSM_STATE_PASSIVE; pe->state = EIGRP_FSM_STATE_PASSIVE;
pe->nt = EIGRP_TOPOLOGY_TYPE_REMOTE; pe->nt = EIGRP_TOPOLOGY_TYPE_REMOTE;
@ -359,9 +338,8 @@ void eigrp_update_receive(struct eigrp *eigrp, struct ip *iph,
/* Check if access-list fits */ /* Check if access-list fits */
if (alist if (alist
&& access_list_apply( && access_list_apply(alist,
alist, &dest_addr)
(struct prefix *)&dest_addr)
== FILTER_DENY) { == FILTER_DENY) {
/* If yes, set reported metric to Max */ /* If yes, set reported metric to Max */
ne->reported_metric.delay = ne->reported_metric.delay =
@ -376,9 +354,8 @@ void eigrp_update_receive(struct eigrp *eigrp, struct ip *iph,
/* Check if prefix-list fits */ /* Check if prefix-list fits */
if (plist if (plist
&& prefix_list_apply( && prefix_list_apply(plist,
plist, &dest_addr)
(struct prefix *)&dest_addr)
== PREFIX_DENY) { == PREFIX_DENY) {
/* If yes, set reported metric to Max */ /* If yes, set reported metric to Max */
ne->reported_metric.delay = ne->reported_metric.delay =
@ -390,9 +367,8 @@ void eigrp_update_receive(struct eigrp *eigrp, struct ip *iph,
/* Check if access-list fits */ /* Check if access-list fits */
if (alist if (alist
&& access_list_apply( && access_list_apply(alist,
alist, &dest_addr)
(struct prefix *)&dest_addr)
== FILTER_DENY) { == FILTER_DENY) {
/* If yes, set reported metric to Max */ /* If yes, set reported metric to Max */
ne->reported_metric.delay = ne->reported_metric.delay =
@ -403,9 +379,8 @@ void eigrp_update_receive(struct eigrp *eigrp, struct ip *iph,
/* Check if prefix-list fits */ /* Check if prefix-list fits */
if (plist if (plist
&& prefix_list_apply( && prefix_list_apply(plist,
plist, &dest_addr)
(struct prefix *)&dest_addr)
== PREFIX_DENY) { == PREFIX_DENY) {
/* If yes, set reported metric to Max */ /* If yes, set reported metric to Max */
ne->reported_metric.delay = ne->reported_metric.delay =
@ -592,7 +567,7 @@ void eigrp_update_send_EOT(struct eigrp_neighbor *nbr)
struct access_list *alist_i; struct access_list *alist_i;
struct prefix_list *plist_i; struct prefix_list *plist_i;
struct eigrp *e; struct eigrp *e;
struct prefix_ipv4 *dest_addr; struct prefix *dest_addr;
u_int32_t seq_no = nbr->ei->eigrp->sequence_number; u_int32_t seq_no = nbr->ei->eigrp->sequence_number;
ep = eigrp_packet_new(nbr->ei->ifp->mtu, nbr); ep = eigrp_packet_new(nbr->ei->ifp->mtu, nbr);
@ -610,8 +585,7 @@ void eigrp_update_send_EOT(struct eigrp_neighbor *nbr)
for (ALL_LIST_ELEMENTS(nbr->ei->eigrp->topology_table, node, nnode, pe)) { for (ALL_LIST_ELEMENTS(nbr->ei->eigrp->topology_table, node, nnode, pe)) {
for (ALL_LIST_ELEMENTS(pe->entries, node2, nnode2, te)) { for (ALL_LIST_ELEMENTS(pe->entries, node2, nnode2, te)) {
if ((te->ei == nbr->ei) if (eigrp_nbr_split_horizon_check(te, nbr->ei))
&& (te->prefix->nt == EIGRP_TOPOLOGY_TYPE_REMOTE))
continue; continue;
if ((length + 0x001D) > (u_int16_t)nbr->ei->ifp->mtu) { if ((length + 0x001D) > (u_int16_t)nbr->ei->ifp->mtu) {
@ -631,7 +605,7 @@ void eigrp_update_send_EOT(struct eigrp_neighbor *nbr)
} }
} }
/* Get destination address from prefix */ /* Get destination address from prefix */
dest_addr = pe->destination_ipv4; dest_addr = pe->destination;
/* /*
* Filtering * Filtering
@ -648,13 +622,13 @@ void eigrp_update_send_EOT(struct eigrp_neighbor *nbr)
/* Check if any list fits */ /* Check if any list fits */
if ((alist if ((alist
&& access_list_apply (alist, && access_list_apply (alist,
(struct prefix *) dest_addr) == FILTER_DENY)|| dest_addr) == FILTER_DENY)||
(plist && prefix_list_apply (plist, (plist && prefix_list_apply (plist,
(struct prefix *) dest_addr) == PREFIX_DENY)|| dest_addr) == PREFIX_DENY)||
(alist_i && access_list_apply (alist_i, (alist_i && access_list_apply (alist_i,
(struct prefix *) dest_addr) == FILTER_DENY)|| dest_addr) == FILTER_DENY)||
(plist_i && prefix_list_apply (plist_i, (plist_i && prefix_list_apply (plist_i,
(struct prefix *) dest_addr) == PREFIX_DENY)) { dest_addr) == PREFIX_DENY)) {
//pe->reported_metric.delay = EIGRP_MAX_METRIC; //pe->reported_metric.delay = EIGRP_MAX_METRIC;
continue; continue;
} else { } else {
@ -678,7 +652,7 @@ void eigrp_update_send(struct eigrp_interface *ei)
struct access_list *alist_i; struct access_list *alist_i;
struct prefix_list *plist_i; struct prefix_list *plist_i;
struct eigrp *e; struct eigrp *e;
struct prefix_ipv4 *dest_addr; struct prefix *dest_addr;
u_int32_t seq_no = ei->eigrp->sequence_number; u_int32_t seq_no = ei->eigrp->sequence_number;
if (ei->nbrs->count == 0) if (ei->nbrs->count == 0)
@ -701,10 +675,15 @@ void eigrp_update_send(struct eigrp_interface *ei)
has_tlv = 0; has_tlv = 0;
for (ALL_LIST_ELEMENTS(ei->eigrp->topology_changes_internalIPV4, node, for (ALL_LIST_ELEMENTS(ei->eigrp->topology_changes_internalIPV4, node,
nnode, pe)) { nnode, pe)) {
struct eigrp_neighbor_entry *ne;
if (!(pe->req_action & EIGRP_FSM_NEED_UPDATE)) if (!(pe->req_action & EIGRP_FSM_NEED_UPDATE))
continue; continue;
ne = listnode_head(pe->entries);
if (eigrp_nbr_split_horizon_check(ne, ei))
continue;
if ((length + 0x001D) > (u_int16_t)ei->ifp->mtu) { if ((length + 0x001D) > (u_int16_t)ei->ifp->mtu) {
if ((IF_DEF_PARAMS(ei->ifp)->auth_type == EIGRP_AUTH_TYPE_MD5) if ((IF_DEF_PARAMS(ei->ifp)->auth_type == EIGRP_AUTH_TYPE_MD5)
&& (IF_DEF_PARAMS(ei->ifp)->auth_keychain != NULL)) { && (IF_DEF_PARAMS(ei->ifp)->auth_keychain != NULL)) {
@ -731,7 +710,7 @@ void eigrp_update_send(struct eigrp_interface *ei)
has_tlv = 0; has_tlv = 0;
} }
/* Get destination address from prefix */ /* Get destination address from prefix */
dest_addr = pe->destination_ipv4; dest_addr = pe->destination;
/* /*
* Filtering * Filtering
@ -747,19 +726,19 @@ void eigrp_update_send(struct eigrp_interface *ei)
/* Check if any list fits */ /* Check if any list fits */
if ((alist if ((alist
&& access_list_apply(alist, && access_list_apply(alist,
(struct prefix *)dest_addr) dest_addr)
== FILTER_DENY) == FILTER_DENY)
|| (plist || (plist
&& prefix_list_apply(plist, && prefix_list_apply(plist,
(struct prefix *)dest_addr) dest_addr)
== PREFIX_DENY) == PREFIX_DENY)
|| (alist_i || (alist_i
&& access_list_apply(alist_i, && access_list_apply(alist_i,
(struct prefix *)dest_addr) dest_addr)
== FILTER_DENY) == FILTER_DENY)
|| (plist_i || (plist_i
&& prefix_list_apply(plist_i, && prefix_list_apply(plist_i,
(struct prefix *)dest_addr) dest_addr)
== PREFIX_DENY)) { == PREFIX_DENY)) {
// pe->reported_metric.delay = EIGRP_MAX_METRIC; // pe->reported_metric.delay = EIGRP_MAX_METRIC;
continue; continue;
@ -841,14 +820,13 @@ static void eigrp_update_send_GR_part(struct eigrp_neighbor *nbr)
u_int16_t length = EIGRP_HEADER_LEN; u_int16_t length = EIGRP_HEADER_LEN;
struct listnode *node, *nnode; struct listnode *node, *nnode;
struct eigrp_prefix_entry *pe; struct eigrp_prefix_entry *pe;
struct prefix_ipv4 *dest_addr; struct prefix *dest_addr;
struct eigrp *e; struct eigrp *e;
struct access_list *alist, *alist_i; struct access_list *alist, *alist_i;
struct prefix_list *plist, *plist_i; struct prefix_list *plist, *plist_i;
struct list *prefixes; struct list *prefixes;
u_int32_t flags; u_int32_t flags;
unsigned int send_prefixes; unsigned int send_prefixes;
struct TLV_IPv4_Internal_type *tlv_max;
/* get prefixes to send to neighbor */ /* get prefixes to send to neighbor */
prefixes = nbr->nbr_gr_prefixes_send; prefixes = nbr->nbr_gr_prefixes_send;
@ -905,7 +883,7 @@ static void eigrp_update_send_GR_part(struct eigrp_neighbor *nbr)
/* /*
* Filtering * Filtering
*/ */
dest_addr = pe->destination_ipv4; dest_addr = pe->destination;
/* get list from eigrp process */ /* get list from eigrp process */
e = eigrp_lookup(); e = eigrp_lookup();
/* Get access-lists and prefix-lists from process and interface /* Get access-lists and prefix-lists from process and interface
@ -917,22 +895,20 @@ static void eigrp_update_send_GR_part(struct eigrp_neighbor *nbr)
/* Check if any list fits */ /* Check if any list fits */
if ((alist if ((alist
&& access_list_apply(alist, (struct prefix *)dest_addr) && access_list_apply(alist, dest_addr)
== FILTER_DENY) == FILTER_DENY)
|| (plist || (plist
&& prefix_list_apply(plist, (struct prefix *)dest_addr) && prefix_list_apply(plist, dest_addr)
== PREFIX_DENY) == PREFIX_DENY)
|| (alist_i || (alist_i
&& access_list_apply(alist_i, && access_list_apply(alist_i, dest_addr)
(struct prefix *)dest_addr)
== FILTER_DENY) == FILTER_DENY)
|| (plist_i || (plist_i
&& prefix_list_apply(plist_i, && prefix_list_apply(plist_i, dest_addr)
(struct prefix *)dest_addr)
== PREFIX_DENY)) { == PREFIX_DENY)) {
/* do not send filtered route */ /* do not send filtered route */
zlog_info("Filtered prefix %s won't be sent out.", zlog_info("Filtered prefix %s won't be sent out.",
inet_ntoa(dest_addr->prefix)); inet_ntoa(dest_addr->u.prefix4));
} else { } else {
/* sending route which wasn't filtered */ /* sending route which wasn't filtered */
length += eigrp_add_internalTLV_to_stream(ep->s, pe); length += eigrp_add_internalTLV_to_stream(ep->s, pe);
@ -946,56 +922,39 @@ static void eigrp_update_send_GR_part(struct eigrp_neighbor *nbr)
/* Check if any list fits */ /* Check if any list fits */
if ((alist if ((alist
&& access_list_apply(alist, (struct prefix *)dest_addr) && access_list_apply(alist, dest_addr)
== FILTER_DENY) == FILTER_DENY)
|| (plist || (plist
&& prefix_list_apply(plist, (struct prefix *)dest_addr) && prefix_list_apply(plist, dest_addr)
== PREFIX_DENY) == PREFIX_DENY)
|| (alist_i || (alist_i
&& access_list_apply(alist_i, && access_list_apply(alist_i, dest_addr)
(struct prefix *)dest_addr)
== FILTER_DENY) == FILTER_DENY)
|| (plist_i || (plist_i
&& prefix_list_apply(plist_i, && prefix_list_apply(plist_i, dest_addr)
(struct prefix *)dest_addr)
== PREFIX_DENY)) { == PREFIX_DENY)) {
/* do not send filtered route */ /* do not send filtered route */
zlog_info("Filtered prefix %s will be removed.", zlog_info("Filtered prefix %s will be removed.",
inet_ntoa(dest_addr->prefix)); inet_ntoa(dest_addr->u.prefix4));
tlv_max = eigrp_IPv4_InternalTLV_new();
tlv_max->type = EIGRP_TLV_IPv4_INT;
tlv_max->length = 28U;
tlv_max->metric = pe->reported_metric;
/* set delay to MAX */
tlv_max->metric.delay = EIGRP_MAX_METRIC;
tlv_max->destination = pe->destination_ipv4->prefix;
tlv_max->prefix_length =
pe->destination_ipv4->prefixlen;
/* prepare message for FSM */ /* prepare message for FSM */
struct eigrp_fsm_action_message *fsm_msg; struct eigrp_fsm_action_message fsm_msg;
fsm_msg = XCALLOC(
MTYPE_EIGRP_FSM_MSG,
sizeof(struct eigrp_fsm_action_message));
struct eigrp_neighbor_entry *entry = struct eigrp_neighbor_entry *entry =
eigrp_prefix_entry_lookup(pe->entries, nbr); eigrp_prefix_entry_lookup(pe->entries, nbr);
fsm_msg->packet_type = EIGRP_OPC_UPDATE; fsm_msg.packet_type = EIGRP_OPC_UPDATE;
fsm_msg->eigrp = e; fsm_msg.eigrp = e;
fsm_msg->data_type = EIGRP_TLV_IPv4_INT; fsm_msg.data_type = EIGRP_INT;
fsm_msg->adv_router = nbr; fsm_msg.adv_router = nbr;
fsm_msg->data.ipv4_int_type = tlv_max; fsm_msg.metrics = pe->reported_metric;
fsm_msg->entry = entry; /* Set delay to MAX */
fsm_msg->prefix = pe; fsm_msg.metrics.delay = EIGRP_MAX_METRIC;
fsm_msg.entry = entry;
fsm_msg.prefix = pe;
/* send message to FSM */ /* send message to FSM */
int event = eigrp_get_fsm_event(fsm_msg); eigrp_fsm_event(&fsm_msg);
eigrp_fsm_event(fsm_msg, event);
/* free memory used by TLV */
eigrp_IPv4_InternalTLV_free(tlv_max);
} }
/* /*
* End of filtering * End of filtering

View File

@ -391,10 +391,10 @@ DEFUN (eigrp_network,
"EIGRP network prefix\n") "EIGRP network prefix\n")
{ {
VTY_DECLVAR_CONTEXT(eigrp, eigrp); VTY_DECLVAR_CONTEXT(eigrp, eigrp);
struct prefix_ipv4 p; struct prefix p;
int ret; int ret;
str2prefix_ipv4(argv[1]->arg, &p); str2prefix(argv[1]->arg, &p);
ret = eigrp_network_set(eigrp, &p); ret = eigrp_network_set(eigrp, &p);
@ -414,10 +414,10 @@ DEFUN (no_eigrp_network,
"EIGRP network prefix\n") "EIGRP network prefix\n")
{ {
VTY_DECLVAR_CONTEXT(eigrp, eigrp); VTY_DECLVAR_CONTEXT(eigrp, eigrp);
struct prefix_ipv4 p; struct prefix p;
int ret; int ret;
str2prefix_ipv4(argv[2]->arg, &p); str2prefix(argv[2]->arg, &p);
ret = eigrp_network_unset(eigrp, &p); ret = eigrp_network_unset(eigrp, &p);

View File

@ -66,8 +66,8 @@ static int eigrp_interface_state_down(int, struct zclient *, zebra_size_t,
vrf_id_t vrf_id); vrf_id_t vrf_id);
static struct interface *zebra_interface_if_lookup(struct stream *); static struct interface *zebra_interface_if_lookup(struct stream *);
static int eigrp_zebra_read_ipv4(int, struct zclient *, zebra_size_t, static int eigrp_zebra_read_route(int, struct zclient *, zebra_size_t,
vrf_id_t vrf_id); vrf_id_t vrf_id);
/* Zebra structure to hold current status. */ /* Zebra structure to hold current status. */
struct zclient *zclient = NULL; struct zclient *zclient = NULL;
@ -112,59 +112,31 @@ void eigrp_zebra_init(void)
zclient->interface_down = eigrp_interface_state_down; zclient->interface_down = eigrp_interface_state_down;
zclient->interface_address_add = eigrp_interface_address_add; zclient->interface_address_add = eigrp_interface_address_add;
zclient->interface_address_delete = eigrp_interface_address_delete; zclient->interface_address_delete = eigrp_interface_address_delete;
zclient->redistribute_route_ipv4_add = eigrp_zebra_read_ipv4; zclient->redistribute_route_add = eigrp_zebra_read_route;
zclient->redistribute_route_ipv4_del = eigrp_zebra_read_ipv4; zclient->redistribute_route_del = eigrp_zebra_read_route;
} }
/* Zebra route add and delete treatment. */ /* Zebra route add and delete treatment. */
static int eigrp_zebra_read_ipv4(int command, struct zclient *zclient, static int eigrp_zebra_read_route(int command, struct zclient *zclient,
zebra_size_t length, vrf_id_t vrf_id) zebra_size_t length, vrf_id_t vrf_id)
{ {
struct stream *s; struct zapi_route api;
struct zapi_ipv4 api;
struct prefix_ipv4 p;
struct eigrp *eigrp; struct eigrp *eigrp;
s = zclient->ibuf; if (zapi_route_decode(zclient->ibuf, &api) < 0)
return -1;
/* Type, flags, message. */ if (IPV4_NET127(ntohl(api.prefix.u.prefix4.s_addr)))
api.type = stream_getc(s);
api.instance = stream_getw(s);
api.flags = stream_getc(s);
api.message = stream_getc(s);
/* IPv4 prefix. */
memset(&p, 0, sizeof(struct prefix_ipv4));
p.family = AF_INET;
p.prefixlen = stream_getc(s);
stream_get(&p.prefix, s, PSIZE(p.prefixlen));
if (IPV4_NET127(ntohl(p.prefix.s_addr)))
return 0; return 0;
/* Nexthop, ifindex, distance, metric. */
if (CHECK_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP)) {
api.nexthop_num = stream_getc(s);
stream_get_ipv4(s);
}
if (CHECK_FLAG(api.message, ZAPI_MESSAGE_IFINDEX)) {
api.ifindex_num = stream_getc(s);
/* XXX assert(api.ifindex_num == 1); */
stream_getl(s); /* ifindex, unused */
}
if (CHECK_FLAG(api.message, ZAPI_MESSAGE_DISTANCE))
api.distance = stream_getc(s);
if (CHECK_FLAG(api.message, ZAPI_MESSAGE_METRIC))
api.metric = stream_getl(s);
eigrp = eigrp_lookup(); eigrp = eigrp_lookup();
if (eigrp == NULL) if (eigrp == NULL)
return 0; return 0;
if (command == ZEBRA_IPV4_ROUTE_ADD) { if (command == ZEBRA_REDISTRIBUTE_ROUTE_ADD) {
} else /* if (command == ZEBRA_IPV4_ROUTE_DELETE) */ } else /* if (command == ZEBRA_REDISTRIBUTE_ROUTE_DEL) */
{ {
} }
@ -389,90 +361,67 @@ static struct interface *zebra_interface_if_lookup(struct stream *s)
ifname_tmp, strnlen(ifname_tmp, INTERFACE_NAMSIZ), VRF_DEFAULT); ifname_tmp, strnlen(ifname_tmp, INTERFACE_NAMSIZ), VRF_DEFAULT);
} }
void eigrp_zebra_route_add(struct prefix_ipv4 *p, struct list *successors) void eigrp_zebra_route_add(struct prefix *p, struct list *successors)
{ {
struct zapi_route api;
struct zapi_nexthop *api_nh;
struct eigrp_neighbor_entry *te; struct eigrp_neighbor_entry *te;
struct listnode *node; struct listnode *node;
u_char message; int count = 0;
u_char flags;
int psize;
struct stream *s;
if (zclient->redist[AFI_IP][ZEBRA_ROUTE_EIGRP]) { if (!zclient->redist[AFI_IP][ZEBRA_ROUTE_EIGRP])
message = 0; return;
flags = 0;
/* EIGRP pass nexthop and metric */ memset(&api, 0, sizeof(api));
SET_FLAG(message, ZAPI_MESSAGE_NEXTHOP); api.vrf_id = VRF_DEFAULT;
api.type = ZEBRA_ROUTE_EIGRP;
api.safi = SAFI_UNICAST;
memcpy(&api.prefix, p, sizeof(*p));
/* Make packet. */ SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
s = zclient->obuf; api.nexthop_num = successors->count;
stream_reset(s);
/* Put command, type, flags, message. */ /* Nexthop, ifindex, distance and metric information. */
zclient_create_header(s, ZEBRA_IPV4_ROUTE_ADD, VRF_DEFAULT); for (ALL_LIST_ELEMENTS_RO(successors, node, te)) {
stream_putc(s, ZEBRA_ROUTE_EIGRP); api_nh = &api.nexthops[count];
stream_putw(s, 0); if (te->adv_router->src.s_addr) {
stream_putl(s, flags); api_nh->gate.ipv4 = te->adv_router->src;
stream_putc(s, message); api_nh->type = NEXTHOP_TYPE_IPV4_IFINDEX;
stream_putw(s, SAFI_UNICAST); } else
api_nh->type = NEXTHOP_TYPE_IFINDEX;
api_nh->ifindex = te->ei->ifp->ifindex;
/* Put prefix information. */ count++;
psize = PSIZE(p->prefixlen);
stream_putc(s, p->prefixlen);
stream_write(s, (u_char *)&p->prefix, psize);
/* Nexthop count. */
stream_putc(s, successors->count);
/* Nexthop, ifindex, distance and metric information. */
for (ALL_LIST_ELEMENTS_RO(successors, node, te)) {
if (te->adv_router->src.s_addr) {
stream_putc(s, NEXTHOP_TYPE_IPV4_IFINDEX);
stream_put_in_addr(s, &te->adv_router->src);
} else
stream_putc(s, NEXTHOP_TYPE_IFINDEX);
stream_putl(s, te->ei->ifp->ifindex);
}
if (IS_DEBUG_EIGRP(zebra, ZEBRA_REDISTRIBUTE)) {
char buf[2][INET_ADDRSTRLEN];
zlog_debug("Zebra: Route add %s/%d nexthop %s",
inet_ntop(AF_INET, &p->prefix, buf[0],
sizeof(buf[0])),
p->prefixlen,
inet_ntop(AF_INET, 0 /*&p->nexthop*/, buf[1],
sizeof(buf[1])));
}
stream_putw_at(s, 0, stream_get_endp(s));
zclient_send_message(zclient);
} }
if (IS_DEBUG_EIGRP(zebra, ZEBRA_REDISTRIBUTE)) {
char buf[2][PREFIX_STRLEN];
zlog_debug("Zebra: Route add %s nexthop %s",
prefix2str(p, buf[0], PREFIX_STRLEN),
inet_ntop(AF_INET, 0, buf[1], PREFIX_STRLEN));
}
zclient_route_send(ZEBRA_ROUTE_ADD, zclient, &api);
} }
void eigrp_zebra_route_delete(struct prefix_ipv4 *p) void eigrp_zebra_route_delete(struct prefix *p)
{ {
struct zapi_ipv4 api; struct zapi_route api;
if (zclient->redist[AFI_IP][ZEBRA_ROUTE_EIGRP]) { if (!zclient->redist[AFI_IP][ZEBRA_ROUTE_EIGRP])
api.vrf_id = VRF_DEFAULT; return;
api.type = ZEBRA_ROUTE_EIGRP;
api.instance = 0;
api.flags = 0;
api.message = 0;
api.safi = SAFI_UNICAST;
zapi_ipv4_route(ZEBRA_IPV4_ROUTE_DELETE, zclient, p, &api);
if (IS_DEBUG_EIGRP(zebra, ZEBRA_REDISTRIBUTE)) { memset(&api, 0, sizeof(api));
char buf[2][INET_ADDRSTRLEN]; api.vrf_id = VRF_DEFAULT;
zlog_debug("Zebra: Route del %s/%d nexthop %s", api.type = ZEBRA_ROUTE_EIGRP;
inet_ntop(AF_INET, &p->prefix, buf[0], api.safi = SAFI_UNICAST;
sizeof(buf[0])), memcpy(&api.prefix, p, sizeof(*p));
p->prefixlen, zclient_route_send(ZEBRA_ROUTE_DELETE, zclient, &api);
inet_ntop(AF_INET, 0 /*&p->nexthop*/, buf[1],
sizeof(buf[1]))); if (IS_DEBUG_EIGRP(zebra, ZEBRA_REDISTRIBUTE)) {
} char buf[PREFIX_STRLEN];
zlog_debug("Zebra: Route del %s",
prefix2str(p, buf, PREFIX_STRLEN));
} }
return; return;

View File

@ -33,8 +33,8 @@
extern void eigrp_zebra_init(void); extern void eigrp_zebra_init(void);
extern void eigrp_zebra_route_add(struct prefix_ipv4 *, struct list *); extern void eigrp_zebra_route_add(struct prefix *, struct list *);
extern void eigrp_zebra_route_delete(struct prefix_ipv4 *); extern void eigrp_zebra_route_delete(struct prefix *);
extern int eigrp_redistribute_set(struct eigrp *, int, struct eigrp_metrics); extern int eigrp_redistribute_set(struct eigrp *, int, struct eigrp_metrics);
extern int eigrp_redistribute_unset(struct eigrp *, int); extern int eigrp_redistribute_unset(struct eigrp *, int);
extern int eigrp_is_type_redistributed(int); extern int eigrp_is_type_redistributed(int);

View File

@ -11,14 +11,28 @@ def run(cmd):
proc.wait() proc.wait()
return rv return rv
clangfmt = run(['git', 'show', 'master:.clang-format'])
argp = argparse.ArgumentParser(description = 'git whitespace-fixing tool') argp = argparse.ArgumentParser(description = 'git whitespace-fixing tool')
argp.add_argument('branch', metavar='BRANCH', type = str, nargs = '?', default = 'HEAD') argp.add_argument('branch', metavar='BRANCH', type = str, nargs = '?', default = 'HEAD')
args = argp.parse_args() args = argp.parse_args()
branch = args.branch branch = args.branch
commit = run(['git', 'rev-list', '-n', '1', branch, '--']).strip() commit = run(['git', 'rev-list', '-n', '1', branch, '--']).strip()
beforeid = run(['git', 'rev-list', '-n', '1', 'reindent-master-before', '--']).strip()
afterid = run(['git', 'rev-list', '-n', '1', 'reindent-master-after', '--']).strip() # frr-3.1-dev = first commit that is on master but not on stable/3.0
masterid = run(['git', 'rev-list', '-n', '1', 'frr-3.1-dev', '--']).strip()
masterbase = run(['git', 'merge-base', commit, masterid]).strip()
if masterbase == masterid:
refbranch = 'master'
else:
refbranch = '3.0'
sys.stderr.write('autodetected base: %s (can be 3.0 or master)\n' % refbranch)
beforeid = run(['git', 'rev-list', '-n', '1', 'reindent-%s-before' % refbranch, '--']).strip()
afterid = run(['git', 'rev-list', '-n', '1', 'reindent-%s-after' % refbranch, '--']).strip()
beforebase = run(['git', 'merge-base', commit, beforeid]).strip() beforebase = run(['git', 'merge-base', commit, beforeid]).strip()
afterbase = run(['git', 'merge-base', commit, afterid]).strip() afterbase = run(['git', 'merge-base', commit, afterid]).strip()
@ -28,10 +42,10 @@ if afterbase == afterid:
sys.exit(1) sys.exit(1)
if beforebase != beforeid: if beforebase != beforeid:
sys.stderr.write('you need to rebase your branch onto the tag "reindent-master-before"\n') sys.stderr.write('you need to rebase your branch onto the tag "reindent-%s-before"\n' % refbranch)
sys.exit(1) sys.exit(1)
revs = run(['git', 'rev-list', 'reindent-master-before..%s' % commit]).strip().split('\n') revs = run(['git', 'rev-list', 'reindent-%s-before..%s' % (refbranch, commit)]).strip().split('\n')
revs.reverse() revs.reverse()
srcdir = os.getcwd() srcdir = os.getcwd()
@ -39,9 +53,12 @@ tmpdir = tempfile.mkdtemp('frrindent')
os.chdir(tmpdir) os.chdir(tmpdir)
sys.stderr.write('using temporary directory %s; %d revisions\n' % (tmpdir, len(revs))) sys.stderr.write('using temporary directory %s; %d revisions\n' % (tmpdir, len(revs)))
run(['git', 'clone', '-s', '-b', 'reindent-master-after', srcdir, 'repo']) run(['git', 'clone', '-s', '-b', 'reindent-%s-after' % refbranch, srcdir, 'repo'])
os.chdir('repo') os.chdir('repo')
with open('.clang-format', 'w') as fd:
fd.write(clangfmt)
prev = beforeid prev = beforeid
for rev in revs: for rev in revs:
filestat = run(['git', 'diff', '-z', '--name-status', prev, rev]).rstrip('\0').split('\0') filestat = run(['git', 'diff', '-z', '--name-status', prev, rev]).rstrip('\0').split('\0')

View File

@ -48,14 +48,15 @@
extern struct zebra_privs_t isisd_privs; extern struct zebra_privs_t isisd_privs;
struct bpf_insn llcfilter[] = { struct bpf_insn llcfilter[] = {
BPF_STMT(BPF_LD + BPF_B + BPF_ABS, /* check first byte */
ETHER_HDR_LEN), /* check first byte */ BPF_STMT(BPF_LD + BPF_B + BPF_ABS, ETH_ALEN),
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, ISO_SAP, 0, 5), BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, ISO_SAP, 0, 5),
BPF_STMT(BPF_LD + BPF_B + BPF_ABS, ETHER_HDR_LEN + 1), /* check second byte */
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, ISO_SAP, 0, BPF_STMT(BPF_LD + BPF_B + BPF_ABS, ETH_ALEN + 1),
3), /* check second byte */ BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, ISO_SAP, 0, 3),
BPF_STMT(BPF_LD + BPF_B + BPF_ABS, ETHER_HDR_LEN + 2), /* check third byte */
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 0x03, 0, 1), /* check third byte */ BPF_STMT(BPF_LD + BPF_B + BPF_ABS, ETH_ALEN + 2),
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 0x03, 0, 1),
BPF_STMT(BPF_RET + BPF_K, (u_int)-1), BPF_STMT(BPF_RET + BPF_K, (u_int)-1),
BPF_STMT(BPF_RET + BPF_K, 0)}; BPF_STMT(BPF_RET + BPF_K, 0)};
u_int readblen = 0; u_int readblen = 0;
@ -243,15 +244,14 @@ int isis_recv_pdu_bcast(struct isis_circuit *circuit, u_char *ssnpa)
assert(bpf_hdr->bh_caplen == bpf_hdr->bh_datalen); assert(bpf_hdr->bh_caplen == bpf_hdr->bh_datalen);
offset = bpf_hdr->bh_hdrlen + LLC_LEN + ETHER_HDR_LEN; offset = bpf_hdr->bh_hdrlen + LLC_LEN + ETH_ALEN;
/* then we lose the BPF, LLC and ethernet headers */ /* then we lose the BPF, LLC and ethernet headers */
stream_write(circuit->rcv_stream, readbuff + offset, stream_write(circuit->rcv_stream, readbuff + offset,
bpf_hdr->bh_caplen - LLC_LEN - ETHER_HDR_LEN); bpf_hdr->bh_caplen - LLC_LEN - ETH_ALEN);
stream_set_getp(circuit->rcv_stream, 0); stream_set_getp(circuit->rcv_stream, 0);
memcpy(ssnpa, readbuff + bpf_hdr->bh_hdrlen + ETH_ALEN, memcpy(ssnpa, readbuff + bpf_hdr->bh_hdrlen + ETH_ALEN, ETH_ALEN);
ETH_ALEN);
if (ioctl(circuit->fd, BIOCFLUSH, &one) < 0) if (ioctl(circuit->fd, BIOCFLUSH, &one) < 0)
zlog_warn("Flushing failed: %s", safe_strerror(errno)); zlog_warn("Flushing failed: %s", safe_strerror(errno));
@ -265,7 +265,7 @@ int isis_send_pdu_bcast(struct isis_circuit *circuit, int level)
ssize_t written; ssize_t written;
size_t buflen; size_t buflen;
buflen = stream_get_endp(circuit->snd_stream) + LLC_LEN + ETHER_HDR_LEN; buflen = stream_get_endp(circuit->snd_stream) + LLC_LEN + ETH_ALEN;
if (buflen > sizeof(sock_buff)) { if (buflen > sizeof(sock_buff)) {
zlog_warn( zlog_warn(
"isis_send_pdu_bcast: sock_buff size %zu is less than " "isis_send_pdu_bcast: sock_buff size %zu is less than "
@ -291,12 +291,12 @@ int isis_send_pdu_bcast(struct isis_circuit *circuit, int level)
/* /*
* Then the LLC * Then the LLC
*/ */
sock_buff[ETHER_HDR_LEN] = ISO_SAP; sock_buff[ETH_ALEN] = ISO_SAP;
sock_buff[ETHER_HDR_LEN + 1] = ISO_SAP; sock_buff[ETH_ALEN + 1] = ISO_SAP;
sock_buff[ETHER_HDR_LEN + 2] = 0x03; sock_buff[ETH_ALEN + 2] = 0x03;
/* then we copy the data */ /* then we copy the data */
memcpy(sock_buff + (LLC_LEN + ETHER_HDR_LEN), circuit->snd_stream->data, memcpy(sock_buff + (LLC_LEN + ETH_ALEN), circuit->snd_stream->data,
stream_get_endp(circuit->snd_stream)); stream_get_endp(circuit->snd_stream));
/* now we can send this */ /* now we can send this */

View File

@ -181,7 +181,7 @@ DEFUN (no_isis_passive,
if (if_is_loopback(circuit->interface)) { if (if_is_loopback(circuit->interface)) {
vty_out(vty, "Can't set no passive for loopback interface\n"); vty_out(vty, "Can't set no passive for loopback interface\n");
return CMD_ERR_AMBIGUOUS; return CMD_WARNING_CONFIG_FAILED;
} }
isis_circuit_passive_set(circuit, 0); isis_circuit_passive_set(circuit, 0);
@ -206,7 +206,7 @@ DEFUN (isis_circuit_type,
is_type = string2circuit_t(argv[idx_level]->arg); is_type = string2circuit_t(argv[idx_level]->arg);
if (!is_type) { if (!is_type) {
vty_out(vty, "Unknown circuit-type \n"); vty_out(vty, "Unknown circuit-type \n");
return CMD_ERR_AMBIGUOUS; return CMD_WARNING_CONFIG_FAILED;
} }
if (circuit->state == C_STATE_UP if (circuit->state == C_STATE_UP
@ -214,7 +214,7 @@ DEFUN (isis_circuit_type,
&& circuit->area->is_type != is_type) { && circuit->area->is_type != is_type) {
vty_out(vty, "Invalid circuit level for area %s.\n", vty_out(vty, "Invalid circuit level for area %s.\n",
circuit->area->area_tag); circuit->area->area_tag);
return CMD_ERR_AMBIGUOUS; return CMD_WARNING_CONFIG_FAILED;
} }
isis_circuit_is_type_set(circuit, is_type); isis_circuit_is_type_set(circuit, is_type);
@ -262,7 +262,7 @@ DEFUN (isis_network,
if (isis_circuit_circ_type_set(circuit, CIRCUIT_T_P2P)) { if (isis_circuit_circ_type_set(circuit, CIRCUIT_T_P2P)) {
vty_out(vty, vty_out(vty,
"isis network point-to-point is valid only on broadcast interfaces\n"); "isis network point-to-point is valid only on broadcast interfaces\n");
return CMD_ERR_AMBIGUOUS; return CMD_WARNING_CONFIG_FAILED;
} }
return CMD_SUCCESS; return CMD_SUCCESS;
@ -283,7 +283,7 @@ DEFUN (no_isis_network,
if (isis_circuit_circ_type_set(circuit, CIRCUIT_T_BROADCAST)) { if (isis_circuit_circ_type_set(circuit, CIRCUIT_T_BROADCAST)) {
vty_out(vty, vty_out(vty,
"isis network point-to-point is valid only on broadcast interfaces\n"); "isis network point-to-point is valid only on broadcast interfaces\n");
return CMD_ERR_AMBIGUOUS; return CMD_WARNING_CONFIG_FAILED;
} }
return CMD_SUCCESS; return CMD_SUCCESS;
@ -313,7 +313,7 @@ DEFUN (isis_passwd,
argv[idx_word]->arg); argv[idx_word]->arg);
if (rv) { if (rv) {
vty_out(vty, "Too long circuit password (>254)\n"); vty_out(vty, "Too long circuit password (>254)\n");
return CMD_ERR_AMBIGUOUS; return CMD_WARNING_CONFIG_FAILED;
} }
return CMD_SUCCESS; return CMD_SUCCESS;
@ -355,7 +355,7 @@ DEFUN (isis_priority,
prio = atoi(argv[idx_number]->arg); prio = atoi(argv[idx_number]->arg);
if (prio < MIN_PRIORITY || prio > MAX_PRIORITY) { if (prio < MIN_PRIORITY || prio > MAX_PRIORITY) {
vty_out(vty, "Invalid priority %d - should be <0-127>\n", prio); vty_out(vty, "Invalid priority %d - should be <0-127>\n", prio);
return CMD_ERR_AMBIGUOUS; return CMD_WARNING_CONFIG_FAILED;
} }
circuit->priority[0] = prio; circuit->priority[0] = prio;
@ -400,7 +400,7 @@ DEFUN (isis_priority_l1,
prio = atoi(argv[idx_number]->arg); prio = atoi(argv[idx_number]->arg);
if (prio < MIN_PRIORITY || prio > MAX_PRIORITY) { if (prio < MIN_PRIORITY || prio > MAX_PRIORITY) {
vty_out(vty, "Invalid priority %d - should be <0-127>\n", prio); vty_out(vty, "Invalid priority %d - should be <0-127>\n", prio);
return CMD_ERR_AMBIGUOUS; return CMD_WARNING_CONFIG_FAILED;
} }
circuit->priority[0] = prio; circuit->priority[0] = prio;
@ -444,7 +444,7 @@ DEFUN (isis_priority_l2,
prio = atoi(argv[idx_number]->arg); prio = atoi(argv[idx_number]->arg);
if (prio < MIN_PRIORITY || prio > MAX_PRIORITY) { if (prio < MIN_PRIORITY || prio > MAX_PRIORITY) {
vty_out(vty, "Invalid priority %d - should be <0-127>\n", prio); vty_out(vty, "Invalid priority %d - should be <0-127>\n", prio);
return CMD_ERR_AMBIGUOUS; return CMD_WARNING_CONFIG_FAILED;
} }
circuit->priority[1] = prio; circuit->priority[1] = prio;
@ -494,7 +494,7 @@ DEFUN (isis_metric,
"Invalid metric %d - should be <0-63> " "Invalid metric %d - should be <0-63> "
"when narrow metric type enabled\n", "when narrow metric type enabled\n",
met); met);
return CMD_ERR_AMBIGUOUS; return CMD_WARNING_CONFIG_FAILED;
} }
/* RFC4444 */ /* RFC4444 */
@ -504,7 +504,7 @@ DEFUN (isis_metric,
"Invalid metric %d - should be <0-16777215> " "Invalid metric %d - should be <0-16777215> "
"when wide metric type enabled\n", "when wide metric type enabled\n",
met); met);
return CMD_ERR_AMBIGUOUS; return CMD_WARNING_CONFIG_FAILED;
} }
isis_circuit_metric_set(circuit, IS_LEVEL_1, met); isis_circuit_metric_set(circuit, IS_LEVEL_1, met);
@ -554,7 +554,7 @@ DEFUN (isis_metric_l1,
"Invalid metric %d - should be <0-63> " "Invalid metric %d - should be <0-63> "
"when narrow metric type enabled\n", "when narrow metric type enabled\n",
met); met);
return CMD_ERR_AMBIGUOUS; return CMD_WARNING_CONFIG_FAILED;
} }
/* RFC4444 */ /* RFC4444 */
@ -564,7 +564,7 @@ DEFUN (isis_metric_l1,
"Invalid metric %d - should be <0-16777215> " "Invalid metric %d - should be <0-16777215> "
"when wide metric type enabled\n", "when wide metric type enabled\n",
met); met);
return CMD_ERR_AMBIGUOUS; return CMD_WARNING_CONFIG_FAILED;
} }
isis_circuit_metric_set(circuit, IS_LEVEL_1, met); isis_circuit_metric_set(circuit, IS_LEVEL_1, met);
@ -613,7 +613,7 @@ DEFUN (isis_metric_l2,
"Invalid metric %d - should be <0-63> " "Invalid metric %d - should be <0-63> "
"when narrow metric type enabled\n", "when narrow metric type enabled\n",
met); met);
return CMD_ERR_AMBIGUOUS; return CMD_WARNING_CONFIG_FAILED;
} }
/* RFC4444 */ /* RFC4444 */
@ -623,7 +623,7 @@ DEFUN (isis_metric_l2,
"Invalid metric %d - should be <0-16777215> " "Invalid metric %d - should be <0-16777215> "
"when wide metric type enabled\n", "when wide metric type enabled\n",
met); met);
return CMD_ERR_AMBIGUOUS; return CMD_WARNING_CONFIG_FAILED;
} }
isis_circuit_metric_set(circuit, IS_LEVEL_2, met); isis_circuit_metric_set(circuit, IS_LEVEL_2, met);
@ -667,7 +667,7 @@ DEFUN (isis_hello_interval,
if (interval < MIN_HELLO_INTERVAL || interval > MAX_HELLO_INTERVAL) { if (interval < MIN_HELLO_INTERVAL || interval > MAX_HELLO_INTERVAL) {
vty_out(vty, "Invalid hello-interval %d - should be <1-600>\n", vty_out(vty, "Invalid hello-interval %d - should be <1-600>\n",
interval); interval);
return CMD_ERR_AMBIGUOUS; return CMD_WARNING_CONFIG_FAILED;
} }
circuit->hello_interval[0] = (u_int16_t)interval; circuit->hello_interval[0] = (u_int16_t)interval;
@ -714,7 +714,7 @@ DEFUN (isis_hello_interval_l1,
if (interval < MIN_HELLO_INTERVAL || interval > MAX_HELLO_INTERVAL) { if (interval < MIN_HELLO_INTERVAL || interval > MAX_HELLO_INTERVAL) {
vty_out(vty, "Invalid hello-interval %ld - should be <1-600>\n", vty_out(vty, "Invalid hello-interval %ld - should be <1-600>\n",
interval); interval);
return CMD_ERR_AMBIGUOUS; return CMD_WARNING_CONFIG_FAILED;
} }
circuit->hello_interval[0] = (u_int16_t)interval; circuit->hello_interval[0] = (u_int16_t)interval;
@ -760,7 +760,7 @@ DEFUN (isis_hello_interval_l2,
if (interval < MIN_HELLO_INTERVAL || interval > MAX_HELLO_INTERVAL) { if (interval < MIN_HELLO_INTERVAL || interval > MAX_HELLO_INTERVAL) {
vty_out(vty, "Invalid hello-interval %ld - should be <1-600>\n", vty_out(vty, "Invalid hello-interval %ld - should be <1-600>\n",
interval); interval);
return CMD_ERR_AMBIGUOUS; return CMD_WARNING_CONFIG_FAILED;
} }
circuit->hello_interval[1] = (u_int16_t)interval; circuit->hello_interval[1] = (u_int16_t)interval;
@ -806,7 +806,7 @@ DEFUN (isis_hello_multiplier,
vty_out(vty, vty_out(vty,
"Invalid hello-multiplier %d - should be <2-100>\n", "Invalid hello-multiplier %d - should be <2-100>\n",
mult); mult);
return CMD_ERR_AMBIGUOUS; return CMD_WARNING_CONFIG_FAILED;
} }
circuit->hello_multiplier[0] = (u_int16_t)mult; circuit->hello_multiplier[0] = (u_int16_t)mult;
@ -854,7 +854,7 @@ DEFUN (isis_hello_multiplier_l1,
vty_out(vty, vty_out(vty,
"Invalid hello-multiplier %d - should be <2-100>\n", "Invalid hello-multiplier %d - should be <2-100>\n",
mult); mult);
return CMD_ERR_AMBIGUOUS; return CMD_WARNING_CONFIG_FAILED;
} }
circuit->hello_multiplier[0] = (u_int16_t)mult; circuit->hello_multiplier[0] = (u_int16_t)mult;
@ -901,7 +901,7 @@ DEFUN (isis_hello_multiplier_l2,
vty_out(vty, vty_out(vty,
"Invalid hello-multiplier %d - should be <2-100>\n", "Invalid hello-multiplier %d - should be <2-100>\n",
mult); mult);
return CMD_ERR_AMBIGUOUS; return CMD_WARNING_CONFIG_FAILED;
} }
circuit->hello_multiplier[1] = (u_int16_t)mult; circuit->hello_multiplier[1] = (u_int16_t)mult;
@ -979,7 +979,7 @@ DEFUN (csnp_interval,
if (interval < MIN_CSNP_INTERVAL || interval > MAX_CSNP_INTERVAL) { if (interval < MIN_CSNP_INTERVAL || interval > MAX_CSNP_INTERVAL) {
vty_out(vty, "Invalid csnp-interval %lu - should be <1-600>\n", vty_out(vty, "Invalid csnp-interval %lu - should be <1-600>\n",
interval); interval);
return CMD_ERR_AMBIGUOUS; return CMD_WARNING_CONFIG_FAILED;
} }
circuit->csnp_interval[0] = (u_int16_t)interval; circuit->csnp_interval[0] = (u_int16_t)interval;
@ -1026,7 +1026,7 @@ DEFUN (csnp_interval_l1,
if (interval < MIN_CSNP_INTERVAL || interval > MAX_CSNP_INTERVAL) { if (interval < MIN_CSNP_INTERVAL || interval > MAX_CSNP_INTERVAL) {
vty_out(vty, "Invalid csnp-interval %lu - should be <1-600>\n", vty_out(vty, "Invalid csnp-interval %lu - should be <1-600>\n",
interval); interval);
return CMD_ERR_AMBIGUOUS; return CMD_WARNING_CONFIG_FAILED;
} }
circuit->csnp_interval[0] = (u_int16_t)interval; circuit->csnp_interval[0] = (u_int16_t)interval;
@ -1072,7 +1072,7 @@ DEFUN (csnp_interval_l2,
if (interval < MIN_CSNP_INTERVAL || interval > MAX_CSNP_INTERVAL) { if (interval < MIN_CSNP_INTERVAL || interval > MAX_CSNP_INTERVAL) {
vty_out(vty, "Invalid csnp-interval %lu - should be <1-600>\n", vty_out(vty, "Invalid csnp-interval %lu - should be <1-600>\n",
interval); interval);
return CMD_ERR_AMBIGUOUS; return CMD_WARNING_CONFIG_FAILED;
} }
circuit->csnp_interval[1] = (u_int16_t)interval; circuit->csnp_interval[1] = (u_int16_t)interval;
@ -1117,7 +1117,7 @@ DEFUN (psnp_interval,
if (interval < MIN_PSNP_INTERVAL || interval > MAX_PSNP_INTERVAL) { if (interval < MIN_PSNP_INTERVAL || interval > MAX_PSNP_INTERVAL) {
vty_out(vty, "Invalid psnp-interval %lu - should be <1-120>\n", vty_out(vty, "Invalid psnp-interval %lu - should be <1-120>\n",
interval); interval);
return CMD_ERR_AMBIGUOUS; return CMD_WARNING_CONFIG_FAILED;
} }
circuit->psnp_interval[0] = (u_int16_t)interval; circuit->psnp_interval[0] = (u_int16_t)interval;
@ -1164,7 +1164,7 @@ DEFUN (psnp_interval_l1,
if (interval < MIN_PSNP_INTERVAL || interval > MAX_PSNP_INTERVAL) { if (interval < MIN_PSNP_INTERVAL || interval > MAX_PSNP_INTERVAL) {
vty_out(vty, "Invalid psnp-interval %lu - should be <1-120>\n", vty_out(vty, "Invalid psnp-interval %lu - should be <1-120>\n",
interval); interval);
return CMD_ERR_AMBIGUOUS; return CMD_WARNING_CONFIG_FAILED;
} }
circuit->psnp_interval[0] = (u_int16_t)interval; circuit->psnp_interval[0] = (u_int16_t)interval;
@ -1210,7 +1210,7 @@ DEFUN (psnp_interval_l2,
if (interval < MIN_PSNP_INTERVAL || interval > MAX_PSNP_INTERVAL) { if (interval < MIN_PSNP_INTERVAL || interval > MAX_PSNP_INTERVAL) {
vty_out(vty, "Invalid psnp-interval %lu - should be <1-120>\n", vty_out(vty, "Invalid psnp-interval %lu - should be <1-120>\n",
interval); interval);
return CMD_ERR_AMBIGUOUS; return CMD_WARNING_CONFIG_FAILED;
} }
circuit->psnp_interval[1] = (u_int16_t)interval; circuit->psnp_interval[1] = (u_int16_t)interval;
@ -1253,12 +1253,12 @@ DEFUN (circuit_topology,
if (circuit->area && circuit->area->oldmetric) { if (circuit->area && circuit->area->oldmetric) {
vty_out(vty, vty_out(vty,
"Multi topology IS-IS can only be used with wide metrics\n"); "Multi topology IS-IS can only be used with wide metrics\n");
return CMD_ERR_AMBIGUOUS; return CMD_WARNING_CONFIG_FAILED;
} }
if (mtid == (uint16_t)-1) { if (mtid == (uint16_t)-1) {
vty_out(vty, "Don't know topology '%s'\n", arg); vty_out(vty, "Don't know topology '%s'\n", arg);
return CMD_ERR_AMBIGUOUS; return CMD_WARNING_CONFIG_FAILED;
} }
return isis_circuit_mt_enabled_set(circuit, mtid, true); return isis_circuit_mt_enabled_set(circuit, mtid, true);
@ -1281,12 +1281,12 @@ DEFUN (no_circuit_topology,
if (circuit->area && circuit->area->oldmetric) { if (circuit->area && circuit->area->oldmetric) {
vty_out(vty, vty_out(vty,
"Multi topology IS-IS can only be used with wide metrics\n"); "Multi topology IS-IS can only be used with wide metrics\n");
return CMD_ERR_AMBIGUOUS; return CMD_WARNING_CONFIG_FAILED;
} }
if (mtid == (uint16_t)-1) { if (mtid == (uint16_t)-1) {
vty_out(vty, "Don't know topology '%s'\n", arg); vty_out(vty, "Don't know topology '%s'\n", arg);
return CMD_ERR_AMBIGUOUS; return CMD_WARNING_CONFIG_FAILED;
} }
return isis_circuit_mt_enabled_set(circuit, mtid, false); return isis_circuit_mt_enabled_set(circuit, mtid, false);
@ -1298,11 +1298,11 @@ static int validate_metric_style_narrow(struct vty *vty, struct isis_area *area)
struct listnode *node; struct listnode *node;
if (!vty) if (!vty)
return CMD_ERR_AMBIGUOUS; return CMD_WARNING_CONFIG_FAILED;
if (!area) { if (!area) {
vty_out(vty, "ISIS area is invalid\n"); vty_out(vty, "ISIS area is invalid\n");
return CMD_ERR_AMBIGUOUS; return CMD_WARNING_CONFIG_FAILED;
} }
for (ALL_LIST_ELEMENTS_RO(area->circuit_list, node, circuit)) { for (ALL_LIST_ELEMENTS_RO(area->circuit_list, node, circuit)) {
@ -1311,14 +1311,14 @@ static int validate_metric_style_narrow(struct vty *vty, struct isis_area *area)
&& (circuit->te_metric[0] > MAX_NARROW_LINK_METRIC)) { && (circuit->te_metric[0] > MAX_NARROW_LINK_METRIC)) {
vty_out(vty, "ISIS circuit %s metric is invalid\n", vty_out(vty, "ISIS circuit %s metric is invalid\n",
circuit->interface->name); circuit->interface->name);
return CMD_ERR_AMBIGUOUS; return CMD_WARNING_CONFIG_FAILED;
} }
if ((area->is_type & IS_LEVEL_2) if ((area->is_type & IS_LEVEL_2)
&& (circuit->is_type & IS_LEVEL_2) && (circuit->is_type & IS_LEVEL_2)
&& (circuit->te_metric[1] > MAX_NARROW_LINK_METRIC)) { && (circuit->te_metric[1] > MAX_NARROW_LINK_METRIC)) {
vty_out(vty, "ISIS circuit %s metric is invalid\n", vty_out(vty, "ISIS circuit %s metric is invalid\n",
circuit->interface->name); circuit->interface->name);
return CMD_ERR_AMBIGUOUS; return CMD_WARNING_CONFIG_FAILED;
} }
} }
@ -1345,7 +1345,7 @@ DEFUN (metric_style,
if (area_is_mt(area)) { if (area_is_mt(area)) {
vty_out(vty, vty_out(vty,
"Narrow metrics cannot be used while multi topology IS-IS is active\n"); "Narrow metrics cannot be used while multi topology IS-IS is active\n");
return CMD_ERR_AMBIGUOUS; return CMD_WARNING_CONFIG_FAILED;
} }
ret = validate_metric_style_narrow(vty, area); ret = validate_metric_style_narrow(vty, area);
@ -1373,7 +1373,7 @@ DEFUN (no_metric_style,
if (area_is_mt(area)) { if (area_is_mt(area)) {
vty_out(vty, vty_out(vty,
"Narrow metrics cannot be used while multi topology IS-IS is active\n"); "Narrow metrics cannot be used while multi topology IS-IS is active\n");
return CMD_ERR_AMBIGUOUS; return CMD_WARNING_CONFIG_FAILED;
} }
ret = validate_metric_style_narrow(vty, area); ret = validate_metric_style_narrow(vty, area);
@ -1470,7 +1470,7 @@ static int area_lsp_mtu_set(struct vty *vty, unsigned int lsp_mtu)
"ISIS area contains circuit %s, which has a maximum PDU size of %zu.\n", "ISIS area contains circuit %s, which has a maximum PDU size of %zu.\n",
circuit->interface->name, circuit->interface->name,
isis_circuit_pdu_size(circuit)); isis_circuit_pdu_size(circuit));
return CMD_ERR_AMBIGUOUS; return CMD_WARNING_CONFIG_FAILED;
} }
} }
@ -1568,7 +1568,7 @@ static int set_lsp_gen_interval(struct vty *vty, struct isis_area *area,
"LSP gen interval %us must be less than " "LSP gen interval %us must be less than "
"the LSP refresh interval %us\n", "the LSP refresh interval %us\n",
interval, area->lsp_refresh[lvl - 1]); interval, area->lsp_refresh[lvl - 1]);
return CMD_ERR_AMBIGUOUS; return CMD_WARNING_CONFIG_FAILED;
} }
} }
@ -1817,7 +1817,7 @@ static int area_max_lsp_lifetime_set(struct vty *vty, int level,
"the configured LSP gen interval %us\n", "the configured LSP gen interval %us\n",
refresh_interval, refresh_interval,
area->lsp_gen_interval[lvl - 1]); area->lsp_gen_interval[lvl - 1]);
return CMD_ERR_AMBIGUOUS; return CMD_WARNING_CONFIG_FAILED;
} }
} }
} }
@ -1890,14 +1890,14 @@ static int area_lsp_refresh_interval_set(struct vty *vty, int level,
"LSP refresh interval %us must be greater than " "LSP refresh interval %us must be greater than "
"the configured LSP gen interval %us\n", "the configured LSP gen interval %us\n",
interval, area->lsp_gen_interval[lvl - 1]); interval, area->lsp_gen_interval[lvl - 1]);
return CMD_ERR_AMBIGUOUS; return CMD_WARNING_CONFIG_FAILED;
} }
if (interval > (area->max_lsp_lifetime[lvl - 1] - 300)) { if (interval > (area->max_lsp_lifetime[lvl - 1] - 300)) {
vty_out(vty, vty_out(vty,
"LSP refresh interval %us must be less than " "LSP refresh interval %us must be less than "
"the configured LSP lifetime %us less 300\n", "the configured LSP lifetime %us less 300\n",
interval, area->max_lsp_lifetime[lvl - 1]); interval, area->max_lsp_lifetime[lvl - 1]);
return CMD_ERR_AMBIGUOUS; return CMD_WARNING_CONFIG_FAILED;
} }
} }
@ -1961,7 +1961,7 @@ static int area_passwd_set(struct vty *vty, int level,
if (passwd && strlen(passwd) > 254) { if (passwd && strlen(passwd) > 254) {
vty_out(vty, "Too long area password (>254)\n"); vty_out(vty, "Too long area password (>254)\n");
return CMD_ERR_AMBIGUOUS; return CMD_WARNING_CONFIG_FAILED;
} }
type_set(area, level, passwd, snp_auth); type_set(area, level, passwd, snp_auth);

View File

@ -245,260 +245,91 @@ static int isis_zebra_link_params(int command, struct zclient *zclient,
return 0; return 0;
} }
static void isis_zebra_route_add_ipv4(struct prefix *prefix, static void isis_zebra_route_add_route(struct prefix *prefix,
struct isis_route_info *route_info) struct isis_route_info *route_info)
{ {
u_char message; struct zapi_route api;
u_int32_t flags; struct zapi_nexthop *api_nh;
int psize;
struct stream *stream;
struct isis_nexthop *nexthop; struct isis_nexthop *nexthop;
struct listnode *node;
if (CHECK_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED))
return;
if (vrf_bitmap_check(zclient->redist[AFI_IP][ZEBRA_ROUTE_ISIS],
VRF_DEFAULT)) {
message = 0;
flags = 0;
SET_FLAG(message, ZAPI_MESSAGE_NEXTHOP);
SET_FLAG(message, ZAPI_MESSAGE_METRIC);
#if 0
SET_FLAG (message, ZAPI_MESSAGE_DISTANCE);
#endif
stream = zclient->obuf;
stream_reset(stream);
zclient_create_header(stream, ZEBRA_IPV4_ROUTE_ADD,
VRF_DEFAULT);
/* type */
stream_putc(stream, ZEBRA_ROUTE_ISIS);
/* instance */
stream_putw(stream, 0);
/* flags */
stream_putl(stream, flags);
/* message */
stream_putc(stream, message);
/* SAFI */
stream_putw(stream, SAFI_UNICAST);
/* prefix information */
psize = PSIZE(prefix->prefixlen);
stream_putc(stream, prefix->prefixlen);
stream_write(stream, (u_char *)&prefix->u.prefix4, psize);
stream_putc(stream, listcount(route_info->nexthops));
/* Nexthop, ifindex, distance and metric information */
for (ALL_LIST_ELEMENTS_RO(route_info->nexthops, node,
nexthop)) {
/* FIXME: can it be ? */
if (nexthop->ip.s_addr != INADDR_ANY) {
stream_putc(stream, NEXTHOP_TYPE_IPV4_IFINDEX);
stream_put_in_addr(stream, &nexthop->ip);
stream_putl(stream, nexthop->ifindex);
} else {
stream_putc(stream, NEXTHOP_TYPE_IFINDEX);
stream_putl(stream, nexthop->ifindex);
}
}
#if 0
if (CHECK_FLAG (message, ZAPI_MESSAGE_DISTANCE))
stream_putc (stream, route_info->depth);
#endif
if (CHECK_FLAG(message, ZAPI_MESSAGE_METRIC))
stream_putl(stream, route_info->cost);
stream_putw_at(stream, 0, stream_get_endp(stream));
zclient_send_message(zclient);
SET_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED);
UNSET_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_RESYNC);
}
}
static void isis_zebra_route_del_ipv4(struct prefix *prefix,
struct isis_route_info *route_info)
{
struct zapi_ipv4 api;
struct prefix_ipv4 prefix4;
if (vrf_bitmap_check(zclient->redist[AFI_IP][ZEBRA_ROUTE_ISIS],
VRF_DEFAULT)) {
api.vrf_id = VRF_DEFAULT;
api.type = ZEBRA_ROUTE_ISIS;
api.instance = 0;
api.flags = 0;
api.message = 0;
api.safi = SAFI_UNICAST;
prefix4.family = AF_INET;
prefix4.prefixlen = prefix->prefixlen;
prefix4.prefix = prefix->u.prefix4;
zapi_ipv4_route(ZEBRA_IPV4_ROUTE_DELETE, zclient, &prefix4,
&api);
}
UNSET_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED);
return;
}
static void isis_zebra_route_add_ipv6(struct prefix *prefix,
struct isis_route_info *route_info)
{
struct zapi_ipv6 api;
struct in6_addr **nexthop_list;
ifindex_t *ifindex_list;
struct isis_nexthop6 *nexthop6; struct isis_nexthop6 *nexthop6;
int i, size;
struct listnode *node; struct listnode *node;
struct prefix_ipv6 prefix6; int count = 0;
if (CHECK_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED)) if (CHECK_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED))
return; return;
memset(&api, 0, sizeof(api));
api.vrf_id = VRF_DEFAULT; api.vrf_id = VRF_DEFAULT;
api.type = ZEBRA_ROUTE_ISIS; api.type = ZEBRA_ROUTE_ISIS;
api.instance = 0;
api.flags = 0;
api.message = 0;
api.safi = SAFI_UNICAST; api.safi = SAFI_UNICAST;
api.prefix = *prefix;
SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP); SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
SET_FLAG(api.message, ZAPI_MESSAGE_IFINDEX);
SET_FLAG(api.message, ZAPI_MESSAGE_METRIC); SET_FLAG(api.message, ZAPI_MESSAGE_METRIC);
api.metric = route_info->cost; api.metric = route_info->cost;
#if 0 #if 0
SET_FLAG (api.message, ZAPI_MESSAGE_DISTANCE); SET_FLAG(api.message, ZAPI_MESSAGE_DISTANCE);
api.distance = route_info->depth; api.distance = route_info->depth;
#endif #endif
api.nexthop_num = listcount(route_info->nexthops6);
api.ifindex_num = listcount(route_info->nexthops6);
/* allocate memory for nexthop_list */ /* Nexthops */
size = sizeof(struct isis_nexthop6 *) switch (prefix->family) {
* listcount(route_info->nexthops6); case AF_INET:
nexthop_list = (struct in6_addr **)XMALLOC(MTYPE_ISIS_TMP, size); for (ALL_LIST_ELEMENTS_RO(route_info->nexthops, node,
if (!nexthop_list) { nexthop)) {
zlog_err("isis_zebra_add_route_ipv6: out of memory!"); api_nh = &api.nexthops[count];
return; /* FIXME: can it be ? */
} if (nexthop->ip.s_addr != INADDR_ANY) {
api_nh->type = NEXTHOP_TYPE_IPV4_IFINDEX;
/* allocate memory for ifindex_list */ api_nh->gate.ipv4 = nexthop->ip;
size = sizeof(unsigned int) * listcount(route_info->nexthops6); } else {
ifindex_list = (ifindex_t *)XMALLOC(MTYPE_ISIS_TMP, size); api_nh->type = NEXTHOP_TYPE_IFINDEX;
if (!ifindex_list) { }
zlog_err("isis_zebra_add_route_ipv6: out of memory!"); api_nh->ifindex = nexthop->ifindex;
XFREE(MTYPE_ISIS_TMP, nexthop_list); count++;
return;
}
/* for each nexthop */
i = 0;
for (ALL_LIST_ELEMENTS_RO(route_info->nexthops6, node, nexthop6)) {
if (!IN6_IS_ADDR_LINKLOCAL(&nexthop6->ip6)
&& !IN6_IS_ADDR_UNSPECIFIED(&nexthop6->ip6)) {
api.nexthop_num--;
api.ifindex_num--;
continue;
} }
break;
case AF_INET6:
for (ALL_LIST_ELEMENTS_RO(route_info->nexthops6, node,
nexthop6)) {
if (!IN6_IS_ADDR_LINKLOCAL(&nexthop6->ip6)
&& !IN6_IS_ADDR_UNSPECIFIED(&nexthop6->ip6)) {
continue;
}
nexthop_list[i] = &nexthop6->ip6; api_nh = &api.nexthops[count];
ifindex_list[i] = nexthop6->ifindex; api_nh->gate.ipv6 = nexthop6->ip6;
i++; api_nh->ifindex = nexthop6->ifindex;
api_nh->type = NEXTHOP_TYPE_IPV6_IFINDEX;
count++;
}
break;
} }
if (!count)
return;
api.nexthop = nexthop_list; api.nexthop_num = count;
api.ifindex = ifindex_list;
if (api.nexthop_num && api.ifindex_num) { zclient_route_send(ZEBRA_ROUTE_ADD, zclient, &api);
prefix6.family = AF_INET6; SET_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED);
prefix6.prefixlen = prefix->prefixlen; UNSET_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_RESYNC);
memcpy(&prefix6.prefix, &prefix->u.prefix6,
sizeof(struct in6_addr));
zapi_ipv6_route(ZEBRA_IPV6_ROUTE_ADD, zclient, &prefix6, NULL,
&api);
SET_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED);
UNSET_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_RESYNC);
}
XFREE(MTYPE_ISIS_TMP, nexthop_list);
XFREE(MTYPE_ISIS_TMP, ifindex_list);
return;
} }
static void isis_zebra_route_del_ipv6(struct prefix *prefix, static void isis_zebra_route_del_route(struct prefix *prefix,
struct isis_route_info *route_info) struct isis_route_info *route_info)
{ {
struct zapi_ipv6 api; struct zapi_route api;
struct in6_addr **nexthop_list;
ifindex_t *ifindex_list;
struct isis_nexthop6 *nexthop6;
int i, size;
struct listnode *node;
struct prefix_ipv6 prefix6;
if (!CHECK_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED)) if (!CHECK_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED))
return; return;
memset(&api, 0, sizeof(api));
api.vrf_id = VRF_DEFAULT; api.vrf_id = VRF_DEFAULT;
api.type = ZEBRA_ROUTE_ISIS; api.type = ZEBRA_ROUTE_ISIS;
api.instance = 0;
api.flags = 0;
api.message = 0;
api.safi = SAFI_UNICAST; api.safi = SAFI_UNICAST;
SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP); api.prefix = *prefix;
SET_FLAG(api.message, ZAPI_MESSAGE_IFINDEX);
api.nexthop_num = listcount(route_info->nexthops6);
api.ifindex_num = listcount(route_info->nexthops6);
/* allocate memory for nexthop_list */ zclient_route_send(ZEBRA_ROUTE_DELETE, zclient, &api);
size = sizeof(struct isis_nexthop6 *) UNSET_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED);
* listcount(route_info->nexthops6);
nexthop_list = (struct in6_addr **)XMALLOC(MTYPE_ISIS_TMP, size);
if (!nexthop_list) {
zlog_err("isis_zebra_route_del_ipv6: out of memory!");
return;
}
/* allocate memory for ifindex_list */
size = sizeof(unsigned int) * listcount(route_info->nexthops6);
ifindex_list = (ifindex_t *)XMALLOC(MTYPE_ISIS_TMP, size);
if (!ifindex_list) {
zlog_err("isis_zebra_route_del_ipv6: out of memory!");
XFREE(MTYPE_ISIS_TMP, nexthop_list);
return;
}
/* for each nexthop */
i = 0;
for (ALL_LIST_ELEMENTS_RO(route_info->nexthops6, node, nexthop6)) {
if (!IN6_IS_ADDR_LINKLOCAL(&nexthop6->ip6)
&& !IN6_IS_ADDR_UNSPECIFIED(&nexthop6->ip6)) {
api.nexthop_num--;
api.ifindex_num--;
continue;
}
nexthop_list[i] = &nexthop6->ip6;
ifindex_list[i] = nexthop6->ifindex;
i++;
}
api.nexthop = nexthop_list;
api.ifindex = ifindex_list;
if (api.nexthop_num && api.ifindex_num) {
prefix6.family = AF_INET6;
prefix6.prefixlen = prefix->prefixlen;
memcpy(&prefix6.prefix, &prefix->u.prefix6,
sizeof(struct in6_addr));
zapi_ipv6_route(ZEBRA_IPV6_ROUTE_DELETE, zclient, &prefix6,
NULL, &api);
UNSET_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED);
}
XFREE(MTYPE_ISIS_TMP, nexthop_list);
XFREE(MTYPE_ISIS_TMP, ifindex_list);
} }
void isis_zebra_route_update(struct prefix *prefix, void isis_zebra_route_update(struct prefix *prefix,
@ -507,144 +338,38 @@ void isis_zebra_route_update(struct prefix *prefix,
if (zclient->sock < 0) if (zclient->sock < 0)
return; return;
if ((prefix->family == AF_INET if (CHECK_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ACTIVE))
&& !vrf_bitmap_check(zclient->redist[AFI_IP][ZEBRA_ROUTE_ISIS], isis_zebra_route_add_route(prefix, route_info);
VRF_DEFAULT))
|| (prefix->family == AF_INET6
&& !vrf_bitmap_check(zclient->redist[AFI_IP6][ZEBRA_ROUTE_ISIS],
VRF_DEFAULT)))
return;
if (CHECK_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ACTIVE)) {
if (prefix->family == AF_INET)
isis_zebra_route_add_ipv4(prefix, route_info);
else if (prefix->family == AF_INET6)
isis_zebra_route_add_ipv6(prefix, route_info);
} else {
if (prefix->family == AF_INET)
isis_zebra_route_del_ipv4(prefix, route_info);
else if (prefix->family == AF_INET6)
isis_zebra_route_del_ipv6(prefix, route_info);
}
return;
}
static int isis_zebra_read_ipv4(int command, struct zclient *zclient,
zebra_size_t length, vrf_id_t vrf_id)
{
struct stream *stream;
struct zapi_ipv4 api;
struct prefix_ipv4 p;
struct prefix *p_generic = (struct prefix *)&p;
stream = zclient->ibuf;
memset(&api, 0, sizeof(api));
memset(&p, 0, sizeof(struct prefix_ipv4));
api.type = stream_getc(stream);
api.instance = stream_getw(stream);
api.flags = stream_getl(stream);
api.message = stream_getc(stream);
p.family = AF_INET;
p.prefixlen = MIN(IPV4_MAX_PREFIXLEN, stream_getc(stream));
stream_get(&p.prefix, stream, PSIZE(p.prefixlen));
if (CHECK_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP)) {
api.nexthop_num = stream_getc(stream);
(void)stream_get_ipv4(stream);
}
if (CHECK_FLAG(api.message, ZAPI_MESSAGE_IFINDEX)) {
api.ifindex_num = stream_getc(stream);
stream_getl(stream);
}
if (CHECK_FLAG(api.message, ZAPI_MESSAGE_DISTANCE))
api.distance = stream_getc(stream);
if (CHECK_FLAG(api.message, ZAPI_MESSAGE_METRIC))
api.metric = stream_getl(stream);
/*
* Avoid advertising a false default reachability. (A default
* route installed by IS-IS gets redistributed from zebra back
* into IS-IS causing us to start advertising default reachabity
* without this check)
*/
if (p.prefixlen == 0 && api.type == ZEBRA_ROUTE_ISIS)
command = ZEBRA_IPV4_ROUTE_DELETE;
if (command == ZEBRA_REDISTRIBUTE_IPV4_ADD)
isis_redist_add(api.type, p_generic, api.distance, api.metric);
else else
isis_redist_delete(api.type, p_generic); isis_zebra_route_del_route(prefix, route_info);
return 0;
} }
static int isis_zebra_read_ipv6(int command, struct zclient *zclient, static int isis_zebra_read(int command, struct zclient *zclient,
zebra_size_t length, vrf_id_t vrf_id) zebra_size_t length, vrf_id_t vrf_id)
{ {
struct stream *stream; struct zapi_route api;
struct zapi_ipv6 api;
struct prefix_ipv6 p;
struct prefix src_p;
struct prefix *p_generic = (struct prefix *)&p;
struct in6_addr nexthop;
unsigned long ifindex __attribute__((unused));
stream = zclient->ibuf; if (zapi_route_decode(zclient->ibuf, &api) < 0)
memset(&api, 0, sizeof(api)); return -1;
memset(&p, 0, sizeof(struct prefix_ipv6));
memset(&nexthop, 0, sizeof(nexthop));
ifindex = 0;
api.type = stream_getc(stream); /* we completely ignore srcdest routes for now. */
api.instance = stream_getw(stream); if (CHECK_FLAG(api.message, ZAPI_MESSAGE_SRCPFX))
api.flags = stream_getl(stream);
api.message = stream_getc(stream);
p.family = AF_INET6;
p.prefixlen = stream_getc(stream);
stream_get(&p.prefix, stream, PSIZE(p.prefixlen));
memset(&src_p, 0, sizeof(struct prefix));
src_p.family = AF_INET6;
if (CHECK_FLAG(api.message, ZAPI_MESSAGE_SRCPFX)) {
src_p.prefixlen = stream_getc(stream);
stream_get(&src_p.u.prefix6, stream, PSIZE(src_p.prefixlen));
}
if (src_p.prefixlen)
/* we completely ignore srcdest routes for now. */
return 0; return 0;
if (CHECK_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP)) {
api.nexthop_num = stream_getc(stream); /* this is always 1 */
stream_get(&nexthop, stream, sizeof(nexthop));
}
if (CHECK_FLAG(api.message, ZAPI_MESSAGE_IFINDEX)) {
api.ifindex_num = stream_getc(stream);
ifindex = stream_getl(stream);
}
if (CHECK_FLAG(api.message, ZAPI_MESSAGE_DISTANCE))
api.distance = stream_getc(stream);
if (CHECK_FLAG(api.message, ZAPI_MESSAGE_METRIC))
api.metric = stream_getl(stream);
if (CHECK_FLAG(api.message, ZAPI_MESSAGE_TAG))
api.tag = stream_getl(stream);
/* /*
* Avoid advertising a false default reachability. (A default * Avoid advertising a false default reachability. (A default
* route installed by IS-IS gets redistributed from zebra back * route installed by IS-IS gets redistributed from zebra back
* into IS-IS causing us to start advertising default reachabity * into IS-IS causing us to start advertising default reachabity
* without this check) * without this check)
*/ */
if (p.prefixlen == 0 && api.type == ZEBRA_ROUTE_ISIS) if (api.prefix.prefixlen == 0 && api.type == ZEBRA_ROUTE_ISIS)
command = ZEBRA_IPV6_ROUTE_DELETE; command = ZEBRA_REDISTRIBUTE_ROUTE_DEL;
if (command == ZEBRA_REDISTRIBUTE_IPV6_ADD) if (command == ZEBRA_REDISTRIBUTE_ROUTE_ADD)
isis_redist_add(api.type, p_generic, api.distance, api.metric); isis_redist_add(api.type, &api.prefix, api.distance,
api.metric);
else else
isis_redist_delete(api.type, p_generic); isis_redist_delete(api.type, &api.prefix);
return 0; return 0;
} }
@ -692,10 +417,8 @@ void isis_zebra_init(struct thread_master *master)
zclient->interface_address_add = isis_zebra_if_address_add; zclient->interface_address_add = isis_zebra_if_address_add;
zclient->interface_address_delete = isis_zebra_if_address_del; zclient->interface_address_delete = isis_zebra_if_address_del;
zclient->interface_link_params = isis_zebra_link_params; zclient->interface_link_params = isis_zebra_link_params;
zclient->redistribute_route_ipv4_add = isis_zebra_read_ipv4; zclient->redistribute_route_add = isis_zebra_read;
zclient->redistribute_route_ipv4_del = isis_zebra_read_ipv4; zclient->redistribute_route_del = isis_zebra_read;
zclient->redistribute_route_ipv6_add = isis_zebra_read_ipv6;
zclient->redistribute_route_ipv6_del = isis_zebra_read_ipv6;
return; return;
} }

View File

@ -347,14 +347,14 @@ int area_net_title(struct vty *vty, const char *net_title)
"area address must be at least 8..20 octets long (%d)\n", "area address must be at least 8..20 octets long (%d)\n",
addr->addr_len); addr->addr_len);
XFREE(MTYPE_ISIS_AREA_ADDR, addr); XFREE(MTYPE_ISIS_AREA_ADDR, addr);
return CMD_ERR_AMBIGUOUS; return CMD_WARNING_CONFIG_FAILED;
} }
if (addr->area_addr[addr->addr_len - 1] != 0) { if (addr->area_addr[addr->addr_len - 1] != 0) {
vty_out(vty, vty_out(vty,
"nsel byte (last byte) in area address must be 0\n"); "nsel byte (last byte) in area address must be 0\n");
XFREE(MTYPE_ISIS_AREA_ADDR, addr); XFREE(MTYPE_ISIS_AREA_ADDR, addr);
return CMD_ERR_AMBIGUOUS; return CMD_WARNING_CONFIG_FAILED;
} }
if (isis->sysid_set == 0) { if (isis->sysid_set == 0) {
@ -374,7 +374,7 @@ int area_net_title(struct vty *vty, const char *net_title)
vty_out(vty, vty_out(vty,
"System ID must not change when defining additional area addresses\n"); "System ID must not change when defining additional area addresses\n");
XFREE(MTYPE_ISIS_AREA_ADDR, addr); XFREE(MTYPE_ISIS_AREA_ADDR, addr);
return CMD_ERR_AMBIGUOUS; return CMD_WARNING_CONFIG_FAILED;
} }
/* now we see that we don't already have this address */ /* now we see that we don't already have this address */
@ -419,7 +419,7 @@ int area_clear_net_title(struct vty *vty, const char *net_title)
vty_out(vty, vty_out(vty,
"Unsupported area address length %d, should be 8...20 \n", "Unsupported area address length %d, should be 8...20 \n",
addr.addr_len); addr.addr_len);
return CMD_ERR_AMBIGUOUS; return CMD_WARNING_CONFIG_FAILED;
} }
memcpy(addr.area_addr, buff, (int)addr.addr_len); memcpy(addr.area_addr, buff, (int)addr.addr_len);
@ -1260,8 +1260,8 @@ DEFUN (show_isis_spf_ietf,
if (area->spf_timer[level - 1]) { if (area->spf_timer[level - 1]) {
struct timeval remain = thread_timer_remain( struct timeval remain = thread_timer_remain(
area->spf_timer[level - 1]); area->spf_timer[level - 1]);
vty_out(vty, "Pending, due in %ld msec\n", vty_out(vty, "Pending, due in %lld msec\n",
remain.tv_sec * 1000 (long long)remain.tv_sec * 1000
+ remain.tv_usec / 1000); + remain.tv_usec / 1000);
} else { } else {
vty_out(vty, "Not scheduled\n"); vty_out(vty, "Not scheduled\n");
@ -1405,7 +1405,7 @@ static int show_isis_database(struct vty *vty, const char *argv, int ui_level)
(u_char)strtol((char *)number, NULL, 16); (u_char)strtol((char *)number, NULL, 16);
pos -= 4; pos -= 4;
if (strncmp(pos, ".", 1) != 0) if (strncmp(pos, ".", 1) != 0)
return CMD_ERR_AMBIGUOUS; return CMD_WARNING;
} }
if (strncmp(pos, ".", 1) == 0) { if (strncmp(pos, ".", 1) == 0) {
memcpy(number, ++pos, 2); memcpy(number, ++pos, 2);
@ -1570,16 +1570,16 @@ DEFUN (isis_topology,
if (area->oldmetric) { if (area->oldmetric) {
vty_out(vty, vty_out(vty,
"Multi topology IS-IS can only be used with wide metrics\n"); "Multi topology IS-IS can only be used with wide metrics\n");
return CMD_ERR_AMBIGUOUS; return CMD_WARNING_CONFIG_FAILED;
} }
if (mtid == (uint16_t)-1) { if (mtid == (uint16_t)-1) {
vty_out(vty, "Don't know topology '%s'\n", arg); vty_out(vty, "Don't know topology '%s'\n", arg);
return CMD_ERR_AMBIGUOUS; return CMD_WARNING_CONFIG_FAILED;
} }
if (mtid == ISIS_MT_IPV4_UNICAST) { if (mtid == ISIS_MT_IPV4_UNICAST) {
vty_out(vty, "Cannot configure IPv4 unicast topology\n"); vty_out(vty, "Cannot configure IPv4 unicast topology\n");
return CMD_ERR_AMBIGUOUS; return CMD_WARNING_CONFIG_FAILED;
} }
area_set_mt_enabled(area, mtid, true); area_set_mt_enabled(area, mtid, true);
@ -1603,16 +1603,16 @@ DEFUN (no_isis_topology,
if (area->oldmetric) { if (area->oldmetric) {
vty_out(vty, vty_out(vty,
"Multi topology IS-IS can only be used with wide metrics\n"); "Multi topology IS-IS can only be used with wide metrics\n");
return CMD_ERR_AMBIGUOUS; return CMD_WARNING_CONFIG_FAILED;
} }
if (mtid == (uint16_t)-1) { if (mtid == (uint16_t)-1) {
vty_out(vty, "Don't know topology '%s'\n", arg); vty_out(vty, "Don't know topology '%s'\n", arg);
return CMD_ERR_AMBIGUOUS; return CMD_WARNING_CONFIG_FAILED;
} }
if (mtid == ISIS_MT_IPV4_UNICAST) { if (mtid == ISIS_MT_IPV4_UNICAST) {
vty_out(vty, "Cannot configure IPv4 unicast topology\n"); vty_out(vty, "Cannot configure IPv4 unicast topology\n");
return CMD_ERR_AMBIGUOUS; return CMD_WARNING_CONFIG_FAILED;
} }
area_set_mt_enabled(area, mtid, false); area_set_mt_enabled(area, mtid, false);

View File

@ -396,19 +396,34 @@ static int
ldp_zebra_read_route(int command, struct zclient *zclient, zebra_size_t length, ldp_zebra_read_route(int command, struct zclient *zclient, zebra_size_t length,
vrf_id_t vrf_id) vrf_id_t vrf_id)
{ {
struct stream *s; struct zapi_route api;
u_char type; struct zapi_nexthop *api_nh;
u_char message_flags;
struct kroute kr; struct kroute kr;
int nhnum = 0, nhlen; int i, add = 0;
size_t nhmark;
int add = 0; if (zapi_route_decode(zclient->ibuf, &api) < 0)
return -1;
/* we completely ignore srcdest routes for now. */
if (CHECK_FLAG(api.message, ZAPI_MESSAGE_SRCPFX))
return (0);
memset(&kr, 0, sizeof(kr)); memset(&kr, 0, sizeof(kr));
s = zclient->ibuf; kr.af = api.prefix.family;
switch (kr.af) {
case AF_INET:
kr.prefix.v4 = api.prefix.u.prefix4;
break;
case AF_INET6:
kr.prefix.v6 = api.prefix.u.prefix6;
break;
default:
break;
}
kr.prefixlen = api.prefix.prefixlen;
kr.priority = api.distance;
type = stream_getc(s); switch (api.type) {
switch (type) {
case ZEBRA_ROUTE_CONNECT: case ZEBRA_ROUTE_CONNECT:
kr.flags |= F_CONNECTED; kr.flags |= F_CONNECTED;
break; break;
@ -419,84 +434,38 @@ ldp_zebra_read_route(int command, struct zclient *zclient, zebra_size_t length,
break; break;
} }
stream_getl(s); /* flags, unused */
stream_getw(s); /* instance, unused */
message_flags = stream_getc(s);
switch (command) {
case ZEBRA_REDISTRIBUTE_IPV4_ADD:
case ZEBRA_REDISTRIBUTE_IPV4_DEL:
kr.af = AF_INET;
nhlen = sizeof(struct in_addr);
break;
case ZEBRA_REDISTRIBUTE_IPV6_ADD:
case ZEBRA_REDISTRIBUTE_IPV6_DEL:
kr.af = AF_INET6;
nhlen = sizeof(struct in6_addr);
break;
default:
fatalx("ldp_zebra_read_route: unknown command");
}
kr.prefixlen = stream_getc(s);
stream_get(&kr.prefix, s, PSIZE(kr.prefixlen));
if (bad_addr(kr.af, &kr.prefix) || if (bad_addr(kr.af, &kr.prefix) ||
(kr.af == AF_INET6 && IN6_IS_SCOPE_EMBED(&kr.prefix.v6))) (kr.af == AF_INET6 && IN6_IS_SCOPE_EMBED(&kr.prefix.v6)))
return (0); return (0);
if (kr.af == AF_INET6 && if (command == ZEBRA_REDISTRIBUTE_ROUTE_ADD)
CHECK_FLAG(message_flags, ZAPI_MESSAGE_SRCPFX)) {
uint8_t src_prefixlen;
src_prefixlen = stream_getc(s);
/* we completely ignore srcdest routes for now. */
if (src_prefixlen)
return (0);
}
if (CHECK_FLAG(message_flags, ZAPI_MESSAGE_NEXTHOP)) {
nhnum = stream_getc(s);
nhmark = stream_get_getp(s);
stream_set_getp(s, nhmark + nhnum * (nhlen + 5));
}
if (CHECK_FLAG(message_flags, ZAPI_MESSAGE_DISTANCE))
kr.priority = stream_getc(s);
if (CHECK_FLAG(message_flags, ZAPI_MESSAGE_METRIC))
stream_getl(s); /* metric, not used */
if (CHECK_FLAG(message_flags, ZAPI_MESSAGE_NEXTHOP))
stream_set_getp(s, nhmark);
if (command == ZEBRA_REDISTRIBUTE_IPV4_ADD ||
command == ZEBRA_REDISTRIBUTE_IPV6_ADD)
add = 1; add = 1;
if (nhnum == 0) if (api.nexthop_num == 0)
debug_zebra_in("route %s %s/%d (%s)", (add) ? "add" : "delete", debug_zebra_in("route %s %s/%d (%s)", (add) ? "add" : "delete",
log_addr(kr.af, &kr.prefix), kr.prefixlen, log_addr(kr.af, &kr.prefix), kr.prefixlen,
zebra_route_string(type)); zebra_route_string(api.type));
/* loop through all the nexthops */ /* loop through all the nexthops */
for (; nhnum > 0; nhnum--) { for (i = 0; i < api.nexthop_num; i++) {
api_nh = &api.nexthops[i];
switch (kr.af) { switch (kr.af) {
case AF_INET: case AF_INET:
kr.nexthop.v4.s_addr = stream_get_ipv4(s); kr.nexthop.v4 = api_nh->gate.ipv4;
break; break;
case AF_INET6: case AF_INET6:
stream_get(&kr.nexthop.v6, s, sizeof(kr.nexthop.v6)); kr.nexthop.v6 = api_nh->gate.ipv6;
break; break;
default: default:
break; break;
} }
stream_getc(s); /* ifindex_num, unused. */ kr.ifindex = api_nh->ifindex;;
kr.ifindex = stream_getl(s);
debug_zebra_in("route %s %s/%d nexthop %s ifindex %u (%s)", debug_zebra_in("route %s %s/%d nexthop %s ifindex %u (%s)",
(add) ? "add" : "delete", log_addr(kr.af, &kr.prefix), (add) ? "add" : "delete", log_addr(kr.af, &kr.prefix),
kr.prefixlen, log_addr(kr.af, &kr.nexthop), kr.ifindex, kr.prefixlen, log_addr(kr.af, &kr.nexthop), kr.ifindex,
zebra_route_string(type)); zebra_route_string(api.type));
if (add) if (add)
main_imsg_compose_lde(IMSG_NETWORK_ADD, 0, &kr, main_imsg_compose_lde(IMSG_NETWORK_ADD, 0, &kr,
@ -553,10 +522,8 @@ ldp_zebra_init(struct thread_master *master)
zclient->interface_down = ldp_interface_status_change; zclient->interface_down = ldp_interface_status_change;
zclient->interface_address_add = ldp_interface_address_add; zclient->interface_address_add = ldp_interface_address_add;
zclient->interface_address_delete = ldp_interface_address_delete; zclient->interface_address_delete = ldp_interface_address_delete;
zclient->redistribute_route_ipv4_add = ldp_zebra_read_route; zclient->redistribute_route_add = ldp_zebra_read_route;
zclient->redistribute_route_ipv4_del = ldp_zebra_read_route; zclient->redistribute_route_del = ldp_zebra_read_route;
zclient->redistribute_route_ipv6_add = ldp_zebra_read_route;
zclient->redistribute_route_ipv6_del = ldp_zebra_read_route;
zclient->pw_status_update = ldp_zebra_read_pw_status_update; zclient->pw_status_update = ldp_zebra_read_pw_status_update;
} }

View File

@ -42,6 +42,7 @@
#include "command_graph.h" #include "command_graph.h"
#include "qobj.h" #include "qobj.h"
#include "defaults.h" #include "defaults.h"
#include "libfrr.h"
DEFINE_MTYPE(LIB, HOST, "Host config") DEFINE_MTYPE(LIB, HOST, "Host config")
DEFINE_MTYPE(LIB, STRVEC, "String vector") DEFINE_MTYPE(LIB, STRVEC, "String vector")
@ -359,21 +360,23 @@ void install_element(enum node_type ntype, struct cmd_element *cmd)
return; return;
} }
cnode = vector_slot(cmdvec, ntype); cnode = vector_lookup(cmdvec, ntype);
if (cnode == NULL) { if (cnode == NULL) {
fprintf(stderr, fprintf(stderr,
"Command node %d doesn't exist, please check it\n", "%s[%s]:\n"
ntype); "\tnode %d (%s) does not exist.\n"
fprintf(stderr, "\tplease call install_node() before install_element()\n",
"Have you called install_node before this install_element?\n"); cmd->name, cmd->string, ntype, node_names[ntype]);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
if (hash_lookup(cnode->cmd_hash, cmd) != NULL) { if (hash_lookup(cnode->cmd_hash, cmd) != NULL) {
fprintf(stderr, fprintf(stderr,
"Multiple command installs to node %d of command:\n%s\n", "%s[%s]:\n"
ntype, cmd->string); "\tnode %d (%s) already has this command installed.\n"
"\tduplicate install_element call?\n",
cmd->name, cmd->string, ntype, node_names[ntype]);
return; return;
} }
@ -406,21 +409,23 @@ void uninstall_element(enum node_type ntype, struct cmd_element *cmd)
return; return;
} }
cnode = vector_slot(cmdvec, ntype); cnode = vector_lookup(cmdvec, ntype);
if (cnode == NULL) { if (cnode == NULL) {
fprintf(stderr, fprintf(stderr,
"Command node %d doesn't exist, please check it\n", "%s[%s]:\n"
ntype); "\tnode %d (%s) does not exist.\n"
fprintf(stderr, "\tplease call install_node() before uninstall_element()\n",
"Have you called install_node before this install_element?\n"); cmd->name, cmd->string, ntype, node_names[ntype]);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
if (hash_release(cnode->cmd_hash, cmd) == NULL) { if (hash_release(cnode->cmd_hash, cmd) == NULL) {
fprintf(stderr, fprintf(stderr,
"Trying to uninstall non-installed command (node %d):\n%s\n", "%s[%s]:\n"
ntype, cmd->string); "\tnode %d (%s) does not have this command installed.\n"
"\tduplicate uninstall_element call?\n",
cmd->name, cmd->string, ntype, node_names[ntype]);
return; return;
} }
@ -555,6 +560,9 @@ static int config_write_host(struct vty *vty)
else if (!host.motd) else if (!host.motd)
vty_out(vty, "no banner motd\n"); vty_out(vty, "no banner motd\n");
if (debug_memstats_at_exit)
vty_out(vty, "!\ndebug memstats-at-exit\n");
return 1; return 1;
} }
@ -2366,6 +2374,17 @@ DEFUN (no_config_log_timestamp_precision,
return CMD_SUCCESS; return CMD_SUCCESS;
} }
DEFUN (debug_memstats,
debug_memstats_cmd,
"[no] debug memstats-at-exit",
NO_STR
DEBUG_STR
"Print memory type statistics at exit\n")
{
debug_memstats_at_exit = !!strcmp(argv[0]->text, "no");
return CMD_SUCCESS;
}
int cmd_banner_motd_file(const char *file) int cmd_banner_motd_file(const char *file)
{ {
int success = CMD_SUCCESS; int success = CMD_SUCCESS;
@ -2527,6 +2546,7 @@ void cmd_init(int terminal)
/* Each node's basic commands. */ /* Each node's basic commands. */
install_element(VIEW_NODE, &show_version_cmd); install_element(VIEW_NODE, &show_version_cmd);
install_element(ENABLE_NODE, &show_startup_config_cmd); install_element(ENABLE_NODE, &show_startup_config_cmd);
install_element(ENABLE_NODE, &debug_memstats_cmd);
if (terminal) { if (terminal) {
install_element(VIEW_NODE, &config_list_cmd); install_element(VIEW_NODE, &config_list_cmd);
@ -2560,6 +2580,7 @@ void cmd_init(int terminal)
install_element(CONFIG_NODE, &hostname_cmd); install_element(CONFIG_NODE, &hostname_cmd);
install_element(CONFIG_NODE, &no_hostname_cmd); install_element(CONFIG_NODE, &no_hostname_cmd);
install_element(CONFIG_NODE, &frr_version_defaults_cmd); install_element(CONFIG_NODE, &frr_version_defaults_cmd);
install_element(CONFIG_NODE, &debug_memstats_cmd);
if (terminal > 0) { if (terminal > 0) {
install_element(CONFIG_NODE, &password_cmd); install_element(CONFIG_NODE, &password_cmd);

View File

@ -46,8 +46,9 @@ DEFINE_MTYPE_STATIC(LIB, CMD_MATCHSTACK, "Command Match Stack")
static int add_nexthops(struct list *, struct graph_node *, static int add_nexthops(struct list *, struct graph_node *,
struct graph_node **, size_t); struct graph_node **, size_t);
static struct list *command_match_r(struct graph_node *, vector, unsigned int, static enum matcher_rv command_match_r(struct graph_node *, vector,
struct graph_node **); unsigned int, struct graph_node **,
struct list **);
static int score_precedence(enum cmd_token_type); static int score_precedence(enum cmd_token_type);
@ -80,14 +81,12 @@ static enum match_type match_variable(struct cmd_token *, const char *);
static enum match_type match_mac(const char *, bool); static enum match_type match_mac(const char *, bool);
/* matching functions */
static enum matcher_rv matcher_rv;
enum matcher_rv command_match(struct graph *cmdgraph, vector vline, enum matcher_rv command_match(struct graph *cmdgraph, vector vline,
struct list **argv, const struct cmd_element **el) struct list **argv, const struct cmd_element **el)
{ {
struct graph_node *stack[MAXDEPTH]; struct graph_node *stack[MAXDEPTH];
matcher_rv = MATCHER_NO_MATCH; enum matcher_rv status;
*argv = NULL;
// prepend a dummy token to match that pesky start node // prepend a dummy token to match that pesky start node
vector vvline = vector_init(vline->alloced + 1); vector vvline = vector_init(vline->alloced + 1);
@ -97,9 +96,8 @@ enum matcher_rv command_match(struct graph *cmdgraph, vector vline,
vvline->active = vline->active + 1; vvline->active = vline->active + 1;
struct graph_node *start = vector_slot(cmdgraph->nodes, 0); struct graph_node *start = vector_slot(cmdgraph->nodes, 0);
if ((*argv = command_match_r(start, vvline, 0, status = command_match_r(start, vvline, 0, stack, argv);
stack))) // successful match if (status == MATCHER_OK) { // successful match
{
struct listnode *head = listhead(*argv); struct listnode *head = listhead(*argv);
struct listnode *tail = listtail(*argv); struct listnode *tail = listtail(*argv);
@ -115,6 +113,9 @@ enum matcher_rv command_match(struct graph *cmdgraph, vector vline,
// input, with each cmd_token->arg holding the corresponding // input, with each cmd_token->arg holding the corresponding
// input // input
assert(*el); assert(*el);
} else if (*argv) {
del_arglist(*argv);
*argv = NULL;
} }
if (!*el) { if (!*el) {
@ -129,7 +130,7 @@ enum matcher_rv command_match(struct graph *cmdgraph, vector vline,
// free vector // free vector
vector_free(vvline); vector_free(vvline);
return matcher_rv; return status;
} }
/** /**
@ -183,11 +184,15 @@ enum matcher_rv command_match(struct graph *cmdgraph, vector vline,
* *
* If no match was found, the return value is NULL. * If no match was found, the return value is NULL.
*/ */
static struct list *command_match_r(struct graph_node *start, vector vline, static enum matcher_rv command_match_r(struct graph_node *start, vector vline,
unsigned int n, struct graph_node **stack) unsigned int n,
struct graph_node **stack,
struct list **currbest)
{ {
assert(n < vector_active(vline)); assert(n < vector_active(vline));
enum matcher_rv status = MATCHER_NO_MATCH;
// get the minimum match level that can count as a full match // get the minimum match level that can count as a full match
struct cmd_token *token = start->data; struct cmd_token *token = start->data;
enum match_type minmatch = min_match_level(token->type); enum match_type minmatch = min_match_level(token->type);
@ -196,11 +201,11 @@ static struct list *command_match_r(struct graph_node *start, vector vline,
* this disallows matching the same one more than once if there is a * this disallows matching the same one more than once if there is a
* circle in the graph (used for keyword arguments) */ * circle in the graph (used for keyword arguments) */
if (n == MAXDEPTH) if (n == MAXDEPTH)
return NULL; return MATCHER_NO_MATCH;
if (!token->allowrepeat) if (!token->allowrepeat)
for (size_t s = 0; s < n; s++) for (size_t s = 0; s < n; s++)
if (stack[s] == start) if (stack[s] == start)
return NULL; return MATCHER_NO_MATCH;
// get the current operating input token // get the current operating input token
char *input_token = vector_slot(vline, n); char *input_token = vector_slot(vline, n);
@ -231,7 +236,7 @@ static struct list *command_match_r(struct graph_node *start, vector vline,
// if we don't match this node, die // if we don't match this node, die
if (match_token(token, input_token) < minmatch) if (match_token(token, input_token) < minmatch)
return NULL; return MATCHER_NO_MATCH;
stack[n] = start; stack[n] = start;
@ -244,86 +249,92 @@ static struct list *command_match_r(struct graph_node *start, vector vline,
add_nexthops(next, start, NULL, 0); add_nexthops(next, start, NULL, 0);
// determine the best match // determine the best match
int ambiguous = 0;
struct list *currbest = NULL;
for (ALL_LIST_ELEMENTS_RO(next, ln, gn)) { for (ALL_LIST_ELEMENTS_RO(next, ln, gn)) {
// if we've matched all input we're looking for END_TKN // if we've matched all input we're looking for END_TKN
if (n + 1 == vector_active(vline)) { if (n + 1 == vector_active(vline)) {
struct cmd_token *tok = gn->data; struct cmd_token *tok = gn->data;
if (tok->type == END_TKN) { if (tok->type == END_TKN) {
if (currbest) // there is more than one END_TKN // if more than one END_TKN in the follow set
// in the follow set if (*currbest) {
{ status = MATCHER_AMBIGUOUS;
ambiguous = 1;
break; break;
} else {
status = MATCHER_OK;
} }
currbest = list_new(); *currbest = list_new();
// node should have one child node with the // node should have one child node with the
// element // element
struct graph_node *leaf = struct graph_node *leaf =
vector_slot(gn->to, 0); vector_slot(gn->to, 0);
// last node in the list will hold the // last node in the list will hold the
// cmd_element; // cmd_element; this is important because
// this is important because list_delete() // list_delete() expects that all nodes have
// expects // the same data type, so when deleting this
// that all nodes have the same data type, so // list the last node must be manually deleted
// when
// deleting this list the last node must be
// manually deleted
struct cmd_element *el = leaf->data; struct cmd_element *el = leaf->data;
listnode_add(currbest, el); listnode_add(*currbest, el);
currbest->del = (*currbest)->del =
(void (*)(void *)) & cmd_token_del; (void (*)(void *)) & cmd_token_del;
// do not break immediately; continue walking // do not break immediately; continue walking
// through the follow set // through the follow set to ensure that there
// to ensure that there is exactly one END_TKN // is exactly one END_TKN
} }
continue; continue;
} }
// else recurse on candidate child node // else recurse on candidate child node
struct list *result = command_match_r(gn, vline, n + 1, stack); struct list *result = NULL;
enum matcher_rv rstat =
command_match_r(gn, vline, n + 1, stack, &result);
// save the best match // save the best match
if (result && currbest) { if (result && *currbest) {
// pick the best of two matches // pick the best of two matches
struct list *newbest = struct list *newbest =
disambiguate(currbest, result, vline, n + 1); disambiguate(*currbest, result, vline, n + 1);
// set ambiguity flag
ambiguous = // current best and result are ambiguous
!newbest || (ambiguous && newbest == currbest); if (!newbest)
status = MATCHER_AMBIGUOUS;
// current best is still the best, but ambiguous
else if (newbest == *currbest
&& status == MATCHER_AMBIGUOUS)
status = MATCHER_AMBIGUOUS;
// result is better, but also ambiguous
else if (newbest == result
&& rstat == MATCHER_AMBIGUOUS)
status = MATCHER_AMBIGUOUS;
// one or the other is superior and not ambiguous
else
status = MATCHER_OK;
// delete the unnecessary result // delete the unnecessary result
struct list *todelete = struct list *todelete =
((newbest && newbest == result) ? currbest ((newbest && newbest == result) ? *currbest
: result); : result);
del_arglist(todelete); del_arglist(todelete);
currbest = newbest ? newbest : currbest; *currbest = newbest ? newbest : *currbest;
} else if (result) } else if (result) {
currbest = result; status = rstat;
} *currbest = result;
} else if (!*currbest) {
if (currbest) { status = MAX(rstat, status);
if (ambiguous) {
del_arglist(currbest);
currbest = NULL;
matcher_rv = MATCHER_AMBIGUOUS;
} else {
// copy token, set arg and prepend to currbest
struct cmd_token *token = start->data;
struct cmd_token *copy = cmd_token_dup(token);
copy->arg = XSTRDUP(MTYPE_CMD_ARG, input_token);
listnode_add_before(currbest, currbest->head, copy);
matcher_rv = MATCHER_OK;
} }
} else if (n + 1 == vector_active(vline) }
&& matcher_rv == MATCHER_NO_MATCH) if (*currbest) {
matcher_rv = MATCHER_INCOMPLETE; // copy token, set arg and prepend to currbest
struct cmd_token *token = start->data;
struct cmd_token *copy = cmd_token_dup(token);
copy->arg = XSTRDUP(MTYPE_CMD_ARG, input_token);
listnode_add_before(*currbest, (*currbest)->head, copy);
} else if (n + 1 == vector_active(vline) && status == MATCHER_NO_MATCH)
status = MATCHER_INCOMPLETE;
// cleanup // cleanup
list_delete(next); list_delete(next);
return currbest; return status;
} }
static void stack_del(void *val) static void stack_del(void *val)
@ -432,12 +443,12 @@ enum matcher_rv command_complete(struct graph *graph, vector vline,
* next = set of all nodes reachable from all nodes in `matched` * next = set of all nodes reachable from all nodes in `matched`
*/ */
matcher_rv = idx == vector_active(vline) && next->count enum matcher_rv mrv = idx == vector_active(vline) && next->count
? MATCHER_OK ? MATCHER_OK
: MATCHER_NO_MATCH; : MATCHER_NO_MATCH;
*completions = NULL; *completions = NULL;
if (!MATCHER_ERROR(matcher_rv)) { if (!MATCHER_ERROR(mrv)) {
// extract cmd_token into list // extract cmd_token into list
*completions = list_new(); *completions = list_new();
for (ALL_LIST_ELEMENTS_RO(next, node, gstack)) { for (ALL_LIST_ELEMENTS_RO(next, node, gstack)) {
@ -448,7 +459,7 @@ enum matcher_rv command_complete(struct graph *graph, vector vline,
list_delete(current); list_delete(current);
list_delete(next); list_delete(next);
return matcher_rv; return mrv;
} }
/** /**

81
lib/compiler.h Normal file
View File

@ -0,0 +1,81 @@
/*
* Copyright (c) 2015-2017 David Lamparter, for NetDEF, Inc.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef _FRR_COMPILER_H
#define _FRR_COMPILER_H
/* function attributes, use like
* void prototype(void) __attribute__((_CONSTRUCTOR(100)));
*/
#if defined(__clang__)
# if __clang_major__ > 3 || (__clang_major__ == 3 && __clang_minor__ >= 5)
# define _RET_NONNULL , returns_nonnull
# endif
# define _CONSTRUCTOR(x) constructor(x)
#elif defined(__GNUC__)
# if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 9)
# define _RET_NONNULL , returns_nonnull
# endif
# if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)
# define _CONSTRUCTOR(x) constructor(x)
# define _DESTRUCTOR(x) destructor(x)
# define _ALLOC_SIZE(x) alloc_size(x)
# endif
#endif
#ifdef __sun
/* Solaris doesn't do constructor priorities due to linker restrictions */
# undef _CONSTRUCTOR
# undef _DESTRUCTOR
#endif
/* fallback versions */
#ifndef _RET_NONNULL
# define _RET_NONNULL
#endif
#ifndef _CONSTRUCTOR
# define _CONSTRUCTOR(x) constructor
#endif
#ifndef _DESTRUCTOR
# define _DESTRUCTOR(x) destructor
#endif
#ifndef _ALLOC_SIZE
# define _ALLOC_SIZE(x)
#endif
/*
* for warnings on macros, put in the macro content like this:
* #define MACRO BLA CPP_WARN("MACRO has been deprecated")
*/
#define CPP_STR(X) #X
#if defined(__ICC)
#define CPP_NOTICE(text) _Pragma(CPP_STR(message __FILE__ ": " text))
#define CPP_WARN(text) CPP_NOTICE(text)
#elif (defined(__GNUC__) \
&& (__GNUC__ >= 5 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8))) \
|| (defined(__clang__) \
&& (__clang_major__ >= 4 \
|| (__clang_major__ == 3 && __clang_minor__ >= 5)))
#define CPP_WARN(text) _Pragma(CPP_STR(GCC warning text))
#define CPP_NOTICE(text) _Pragma(CPP_STR(message text))
#else
#define CPP_WARN(text)
#endif
#endif /* _FRR_COMPILER_H */

View File

@ -404,7 +404,8 @@ DEFUN (grammar_findambig,
nodegraph = cnode->cmdgraph; nodegraph = cnode->cmdgraph;
if (!nodegraph) if (!nodegraph)
continue; continue;
vty_out(vty, "scanning node %d\n", scannode - 1); vty_out(vty, "scanning node %d (%s)\n",
scannode - 1, node_names[scannode - 1]);
} }
commands = cmd_graph_permutations(nodegraph); commands = cmd_graph_permutations(nodegraph);

View File

@ -52,6 +52,8 @@ char frr_zclientpath[256];
static char pidfile_default[256]; static char pidfile_default[256];
static char vtypath_default[256]; static char vtypath_default[256];
bool debug_memstats_at_exit = 0;
static char comb_optstr[256]; static char comb_optstr[256];
static struct option comb_lo[64]; static struct option comb_lo[64];
static struct option *comb_next_lo = &comb_lo[0]; static struct option *comb_next_lo = &comb_lo[0];
@ -639,7 +641,10 @@ static void frr_daemon_wait(int fd)
exit(0); exit(0);
/* child failed one way or another ... */ /* child failed one way or another ... */
if (WIFEXITED(exitstat)) if (WIFEXITED(exitstat) && WEXITSTATUS(exitstat) == 0)
/* can happen in --terminal case if exit is fast enough */
(void)0;
else if (WIFEXITED(exitstat))
fprintf(stderr, "%s failed to start, exited %d\n", di->name, fprintf(stderr, "%s failed to start, exited %d\n", di->name,
WEXITSTATUS(exitstat)); WEXITSTATUS(exitstat));
else if (WIFSIGNALED(exitstat)) else if (WIFSIGNALED(exitstat))
@ -841,6 +846,10 @@ void frr_early_fini(void)
void frr_fini(void) void frr_fini(void)
{ {
FILE *fp;
char filename[128];
int have_leftovers;
hook_call(frr_fini); hook_call(frr_fini);
/* memory_init -> nothing needed */ /* memory_init -> nothing needed */
@ -851,4 +860,28 @@ void frr_fini(void)
thread_master_free(master); thread_master_free(master);
closezlog(); closezlog();
/* frrmod_init -> nothing needed / hooks */ /* frrmod_init -> nothing needed / hooks */
if (!debug_memstats_at_exit)
return;
have_leftovers = log_memstats(stderr, di->name);
/* in case we decide at runtime that we want exit-memstats for
* a daemon, but it has no stderr because it's daemonized
* (only do this if we actually have something to print though)
*/
if (!have_leftovers)
return;
snprintf(filename, sizeof(filename),
"/tmp/frr-memstats-%s-%llu-%llu",
di->name,
(unsigned long long)getpid(),
(unsigned long long)time(NULL));
fp = fopen(filename, "w");
if (fp) {
log_memstats(fp, di->name);
fclose(fp);
}
} }

View File

@ -121,4 +121,6 @@ extern const char frr_moduledir[];
extern char frr_protoname[]; extern char frr_protoname[];
extern char frr_protonameinst[]; extern char frr_protonameinst[];
extern bool debug_memstats_at_exit;
#endif /* _ZEBRA_FRR_H */ #endif /* _ZEBRA_FRR_H */

View File

@ -701,7 +701,7 @@ void _zlog_assert_failed(const char *assertion, const char *file,
assertion, file, line, (function ? function : "?")); assertion, file, line, (function ? function : "?"));
zlog_backtrace(LOG_CRIT); zlog_backtrace(LOG_CRIT);
zlog_thread_info(LOG_CRIT); zlog_thread_info(LOG_CRIT);
log_memstats_stderr("log"); log_memstats(stderr, "log");
abort(); abort();
} }
@ -867,6 +867,8 @@ static const struct zebra_desc_table command_types[] = {
DESC_ENTRY(ZEBRA_INTERFACE_UP), DESC_ENTRY(ZEBRA_INTERFACE_UP),
DESC_ENTRY(ZEBRA_INTERFACE_DOWN), DESC_ENTRY(ZEBRA_INTERFACE_DOWN),
DESC_ENTRY(ZEBRA_INTERFACE_SET_MASTER), DESC_ENTRY(ZEBRA_INTERFACE_SET_MASTER),
DESC_ENTRY(ZEBRA_ROUTE_ADD),
DESC_ENTRY(ZEBRA_ROUTE_DELETE),
DESC_ENTRY(ZEBRA_IPV4_ROUTE_ADD), DESC_ENTRY(ZEBRA_IPV4_ROUTE_ADD),
DESC_ENTRY(ZEBRA_IPV4_ROUTE_DELETE), DESC_ENTRY(ZEBRA_IPV4_ROUTE_DELETE),
DESC_ENTRY(ZEBRA_IPV6_ROUTE_ADD), DESC_ENTRY(ZEBRA_IPV6_ROUTE_ADD),
@ -893,10 +895,8 @@ static const struct zebra_desc_table command_types[] = {
DESC_ENTRY(ZEBRA_BFD_DEST_DEREGISTER), DESC_ENTRY(ZEBRA_BFD_DEST_DEREGISTER),
DESC_ENTRY(ZEBRA_BFD_DEST_UPDATE), DESC_ENTRY(ZEBRA_BFD_DEST_UPDATE),
DESC_ENTRY(ZEBRA_BFD_DEST_REPLAY), DESC_ENTRY(ZEBRA_BFD_DEST_REPLAY),
DESC_ENTRY(ZEBRA_REDISTRIBUTE_IPV4_ADD), DESC_ENTRY(ZEBRA_REDISTRIBUTE_ROUTE_ADD),
DESC_ENTRY(ZEBRA_REDISTRIBUTE_IPV4_DEL), DESC_ENTRY(ZEBRA_REDISTRIBUTE_ROUTE_DEL),
DESC_ENTRY(ZEBRA_REDISTRIBUTE_IPV6_ADD),
DESC_ENTRY(ZEBRA_REDISTRIBUTE_IPV6_DEL),
DESC_ENTRY(ZEBRA_VRF_UNREGISTER), DESC_ENTRY(ZEBRA_VRF_UNREGISTER),
DESC_ENTRY(ZEBRA_VRF_ADD), DESC_ENTRY(ZEBRA_VRF_ADD),
DESC_ENTRY(ZEBRA_VRF_DELETE), DESC_ENTRY(ZEBRA_VRF_DELETE),
@ -908,10 +908,6 @@ static const struct zebra_desc_table command_types[] = {
DESC_ENTRY(ZEBRA_INTERFACE_LINK_PARAMS), DESC_ENTRY(ZEBRA_INTERFACE_LINK_PARAMS),
DESC_ENTRY(ZEBRA_MPLS_LABELS_ADD), DESC_ENTRY(ZEBRA_MPLS_LABELS_ADD),
DESC_ENTRY(ZEBRA_MPLS_LABELS_DELETE), DESC_ENTRY(ZEBRA_MPLS_LABELS_DELETE),
DESC_ENTRY(ZEBRA_IPV4_NEXTHOP_ADD),
DESC_ENTRY(ZEBRA_IPV4_NEXTHOP_DELETE),
DESC_ENTRY(ZEBRA_IPV6_NEXTHOP_ADD),
DESC_ENTRY(ZEBRA_IPV6_NEXTHOP_DELETE),
DESC_ENTRY(ZEBRA_IPMR_ROUTE_STATS), DESC_ENTRY(ZEBRA_IPMR_ROUTE_STATS),
DESC_ENTRY(ZEBRA_LABEL_MANAGER_CONNECT), DESC_ENTRY(ZEBRA_LABEL_MANAGER_CONNECT),
DESC_ENTRY(ZEBRA_GET_LABEL_CHUNK), DESC_ENTRY(ZEBRA_GET_LABEL_CHUNK),

View File

@ -104,6 +104,7 @@ int qmem_walk(qmem_walk_fn *func, void *arg)
} }
struct exit_dump_args { struct exit_dump_args {
FILE *fp;
const char *prefix; const char *prefix;
int error; int error;
}; };
@ -113,7 +114,7 @@ static int qmem_exit_walker(void *arg, struct memgroup *mg, struct memtype *mt)
struct exit_dump_args *eda = arg; struct exit_dump_args *eda = arg;
if (!mt) { if (!mt) {
fprintf(stderr, fprintf(eda->fp,
"%s: showing active allocations in " "%s: showing active allocations in "
"memory group %s\n", "memory group %s\n",
eda->prefix, mg->name); eda->prefix, mg->name);
@ -122,15 +123,16 @@ static int qmem_exit_walker(void *arg, struct memgroup *mg, struct memtype *mt)
char size[32]; char size[32];
eda->error++; eda->error++;
snprintf(size, sizeof(size), "%10zu", mt->size); snprintf(size, sizeof(size), "%10zu", mt->size);
fprintf(stderr, "%s: memstats: %-30s: %6zu * %s\n", fprintf(eda->fp, "%s: memstats: %-30s: %6zu * %s\n",
eda->prefix, mt->name, mt->n_alloc, eda->prefix, mt->name, mt->n_alloc,
mt->size == SIZE_VAR ? "(variably sized)" : size); mt->size == SIZE_VAR ? "(variably sized)" : size);
} }
return 0; return 0;
} }
void log_memstats_stderr(const char *prefix) int log_memstats(FILE *fp, const char *prefix)
{ {
struct exit_dump_args eda = {.prefix = prefix, .error = 0}; struct exit_dump_args eda = { .fp = fp, .prefix = prefix, .error = 0 };
qmem_walk(qmem_exit_walker, &eda); qmem_walk(qmem_exit_walker, &eda);
return eda.error;
} }

View File

@ -18,7 +18,9 @@
#define _QUAGGA_MEMORY_H #define _QUAGGA_MEMORY_H
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h>
#include <frratomic.h> #include <frratomic.h>
#include "compiler.h"
#define array_size(ar) (sizeof(ar) / sizeof(ar[0])) #define array_size(ar) (sizeof(ar) / sizeof(ar[0]))
@ -36,41 +38,6 @@ struct memgroup {
const char *name; const char *name;
}; };
#if defined(__clang__)
#if __clang_major__ > 3 || (__clang_major__ == 3 && __clang_minor__ >= 5)
# define _RET_NONNULL , returns_nonnull
#endif
# define _CONSTRUCTOR(x) constructor(x)
#elif defined(__GNUC__)
#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 9)
# define _RET_NONNULL , returns_nonnull
#endif
#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)
# define _CONSTRUCTOR(x) constructor(x)
# define _DESTRUCTOR(x) destructor(x)
# define _ALLOC_SIZE(x) alloc_size(x)
#endif
#endif
#ifdef __sun
/* Solaris doesn't do constructor priorities due to linker restrictions */
#undef _CONSTRUCTOR
#undef _DESTRUCTOR
#endif
#ifndef _RET_NONNULL
# define _RET_NONNULL
#endif
#ifndef _CONSTRUCTOR
# define _CONSTRUCTOR(x) constructor
#endif
#ifndef _DESTRUCTOR
# define _DESTRUCTOR(x) destructor
#endif
#ifndef _ALLOC_SIZE
# define _ALLOC_SIZE(x)
#endif
/* macro usage: /* macro usage:
* *
* mydaemon.h * mydaemon.h
@ -194,7 +161,8 @@ static inline size_t mtype_stats_alloc(struct memtype *mt)
* last value from qmem_walk_fn. */ * last value from qmem_walk_fn. */
typedef int qmem_walk_fn(void *arg, struct memgroup *mg, struct memtype *mt); typedef int qmem_walk_fn(void *arg, struct memgroup *mg, struct memtype *mt);
extern int qmem_walk(qmem_walk_fn *func, void *arg); extern int qmem_walk(qmem_walk_fn *func, void *arg);
extern void log_memstats_stderr(const char *); extern int log_memstats(FILE *fp, const char *);
#define log_memstats_stderr(prefix) log_memstats(stderr, prefix)
extern void memory_oom(size_t size, const char *name); extern void memory_oom(size_t size, const char *name);

View File

@ -42,8 +42,10 @@ static struct frrmod_info frrmod_default_info = {
.description = "libfrr core module", .description = "libfrr core module",
}; };
union _frrmod_runtime_u frrmod_default = { union _frrmod_runtime_u frrmod_default = {
.r.info = &frrmod_default_info, .r = {
.r.finished_loading = 1, .info = &frrmod_default_info,
.finished_loading = 1,
},
}; };
// if defined(HAVE_SYS_WEAK_ALIAS_ATTRIBUTE) // if defined(HAVE_SYS_WEAK_ALIAS_ATTRIBUTE)

View File

@ -44,6 +44,9 @@
#define MPLS_DEFAULT_MIN_SRGB_LABEL 16000 #define MPLS_DEFAULT_MIN_SRGB_LABEL 16000
#define MPLS_DEFAULT_MAX_SRGB_LABEL 23999 #define MPLS_DEFAULT_MAX_SRGB_LABEL 23999
/* Maximum # labels that can be pushed. */
#define MPLS_MAX_LABELS 16
#define IS_MPLS_RESERVED_LABEL(label) \ #define IS_MPLS_RESERVED_LABEL(label) \
(label >= MPLS_MIN_RESERVED_LABEL && label <= MPLS_MAX_RESERVED_LABEL) (label >= MPLS_MIN_RESERVED_LABEL && label <= MPLS_MAX_RESERVED_LABEL)

View File

@ -122,6 +122,14 @@ const char *prefix_list_name(struct prefix_list *plist)
return plist->name; return plist->name;
} }
afi_t prefix_list_afi(struct prefix_list *plist)
{
if (plist->master == &prefix_master_ipv4
|| plist->master == &prefix_master_orf_v4)
return AFI_IP;
return AFI_IP6;
}
/* Lookup prefix_list from list of prefix_list by name. */ /* Lookup prefix_list from list of prefix_list by name. */
static struct prefix_list *prefix_list_lookup_do(afi_t afi, int orf, static struct prefix_list *prefix_list_lookup_do(afi_t afi, int orf,
const char *name) const char *name)

View File

@ -48,6 +48,7 @@ extern void prefix_list_add_hook(void (*func)(struct prefix_list *));
extern void prefix_list_delete_hook(void (*func)(struct prefix_list *)); extern void prefix_list_delete_hook(void (*func)(struct prefix_list *));
extern const char *prefix_list_name(struct prefix_list *); extern const char *prefix_list_name(struct prefix_list *);
extern afi_t prefix_list_afi(struct prefix_list *);
extern struct prefix_list *prefix_list_lookup(afi_t, const char *); extern struct prefix_list *prefix_list_lookup(afi_t, const char *);
extern enum prefix_list_type prefix_list_apply(struct prefix_list *, void *); extern enum prefix_list_type prefix_list_apply(struct prefix_list *, void *);

View File

@ -1263,5 +1263,6 @@ unsigned prefix_hash_key(void *pp)
* padding and unused prefix bytes. */ * padding and unused prefix bytes. */
memset(&copy, 0, sizeof(copy)); memset(&copy, 0, sizeof(copy));
prefix_copy(&copy, (struct prefix *)pp); prefix_copy(&copy, (struct prefix *)pp);
return jhash(&copy, sizeof(copy), 0x55aa5a5a); return jhash(&copy, offsetof(struct prefix, u.prefix)
+ PSIZE(copy.prefixlen), 0x55aa5a5a);
} }

View File

@ -33,28 +33,13 @@
#endif #endif
#include "sockunion.h" #include "sockunion.h"
#include "ipaddr.h" #include "ipaddr.h"
#include "compiler.h"
#ifndef ETH_ALEN #ifndef ETH_ALEN
#define ETH_ALEN 6 #define ETH_ALEN 6
#endif #endif
/* for compatibility */ /* for compatibility */
#if defined(__ICC)
#define CPP_WARN_STR(X) #X
#define CPP_WARN(text) _Pragma(CPP_WARN_STR(message __FILE__ ": " text))
#elif (defined(__GNUC__) \
&& (__GNUC__ >= 5 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8))) \
|| (defined(__clang__) \
&& (__clang_major__ >= 4 \
|| (__clang_major__ == 3 && __clang_minor__ >= 5)))
#define CPP_WARN_STR(X) #X
#define CPP_WARN(text) _Pragma(CPP_WARN_STR(GCC warning text))
#else
#define CPP_WARN(text)
#endif
#ifdef ETHER_ADDR_LEN #ifdef ETHER_ADDR_LEN
#undef ETHER_ADDR_LEN #undef ETHER_ADDR_LEN
#endif #endif
@ -140,7 +125,7 @@ struct prefix {
struct in_addr adv_router; struct in_addr adv_router;
} lp; } lp;
struct ethaddr prefix_eth; /* AF_ETHERNET */ struct ethaddr prefix_eth; /* AF_ETHERNET */
u_char val[8]; u_char val[16];
uintptr_t ptr; uintptr_t ptr;
struct evpn_addr prefix_evpn; /* AF_EVPN */ struct evpn_addr prefix_evpn; /* AF_EVPN */
} u __attribute__((aligned(8))); } u __attribute__((aligned(8)));

View File

@ -245,7 +245,7 @@ core_handler(int signo
#endif #endif
); );
/* dump memory stats on core */ /* dump memory stats on core */
log_memstats_stderr("core_handler"); log_memstats(stderr, "core_handler");
abort(); abort();
} }

View File

@ -226,8 +226,9 @@ void spf_backoff_show(struct spf_backoff *backoff, struct vty *vty,
if (backoff->t_holddown) { if (backoff->t_holddown) {
struct timeval remain = struct timeval remain =
thread_timer_remain(backoff->t_holddown); thread_timer_remain(backoff->t_holddown);
vty_out(vty, "%s Still runs for %ld msec\n", vty_out(vty, "%s Still runs for %lld msec\n",
prefix, remain.tv_sec * 1000 + remain.tv_usec / 1000); prefix, (long long)remain.tv_sec * 1000
+ remain.tv_usec / 1000);
} else { } else {
vty_out(vty, "%s Inactive\n", prefix); vty_out(vty, "%s Inactive\n", prefix);
} }
@ -237,8 +238,9 @@ void spf_backoff_show(struct spf_backoff *backoff, struct vty *vty,
if (backoff->t_timetolearn) { if (backoff->t_timetolearn) {
struct timeval remain = struct timeval remain =
thread_timer_remain(backoff->t_timetolearn); thread_timer_remain(backoff->t_timetolearn);
vty_out(vty, "%s Still runs for %ld msec\n", vty_out(vty, "%s Still runs for %lld msec\n",
prefix, remain.tv_sec * 1000 + remain.tv_usec / 1000); prefix, (long long)remain.tv_sec * 1000
+ remain.tv_usec / 1000);
} else { } else {
vty_out(vty, "%s Inactive\n", prefix); vty_out(vty, "%s Inactive\n", prefix);
} }

View File

@ -85,6 +85,7 @@ pkginclude_HEADERS += \
lib/command.h \ lib/command.h \
lib/command_graph.h \ lib/command_graph.h \
lib/command_match.h \ lib/command_match.h \
lib/compiler.h \
lib/csv.h \ lib/csv.h \
lib/distribute.h \ lib/distribute.h \
lib/event_counter.h \ lib/event_counter.h \

View File

@ -227,7 +227,7 @@ extern void route_table_iter_cleanup(route_table_iter_t *iter);
/* Lock node. */ /* Lock node. */
static inline struct route_node *route_lock_node(struct route_node *node) static inline struct route_node *route_lock_node(struct route_node *node)
{ {
node->lock++; (*(unsigned *)&node->lock)++;
return node; return node;
} }
@ -235,7 +235,7 @@ static inline struct route_node *route_lock_node(struct route_node *node)
static inline void route_unlock_node(struct route_node *node) static inline void route_unlock_node(struct route_node *node)
{ {
assert(node->lock > 0); assert(node->lock > 0);
node->lock--; (*(unsigned *)&node->lock)--;
if (node->lock == 0) if (node->lock == 0)
route_node_delete(node); route_node_delete(node);

View File

@ -31,48 +31,60 @@ struct ttable_style ttable_styles[] = {
.corner = '+', .corner = '+',
.rownums_on = false, .rownums_on = false,
.indent = 1, .indent = 1,
.border.top = '-', .border = {
.border.bottom = '-', .top = '-',
.border.left = '|', .bottom = '-',
.border.right = '|', .left = '|',
.border.top_on = true, .right = '|',
.border.bottom_on = true, .top_on = true,
.border.left_on = true, .bottom_on = true,
.border.right_on = true, .left_on = true,
.cell.lpad = 1, .right_on = true,
.cell.rpad = 1, },
.cell.align = LEFT, .cell = {
.cell.border.bottom = '-', .lpad = 1,
.cell.border.bottom_on = true, .rpad = 1,
.cell.border.top = '-', .align = LEFT,
.cell.border.top_on = false, .border = {
.cell.border.right = '|', .bottom = '-',
.cell.border.right_on = true, .bottom_on = true,
.cell.border.left = '|', .top = '-',
.cell.border.left_on = false, .top_on = false,
.right = '|',
.right_on = true,
.left = '|',
.left_on = false,
},
},
}, { // blank, suitable for plaintext alignment }, { // blank, suitable for plaintext alignment
.corner = ' ', .corner = ' ',
.rownums_on = false, .rownums_on = false,
.indent = 1, .indent = 1,
.border.top = ' ', .border = {
.border.bottom = ' ', .top = ' ',
.border.left = ' ', .bottom = ' ',
.border.right = ' ', .left = ' ',
.border.top_on = false, .right = ' ',
.border.bottom_on = false, .top_on = false,
.border.left_on = false, .bottom_on = false,
.border.right_on = false, .left_on = false,
.cell.lpad = 0, .right_on = false,
.cell.rpad = 3, },
.cell.align = LEFT, .cell = {
.cell.border.bottom = ' ', .lpad = 0,
.cell.border.bottom_on = false, .rpad = 3,
.cell.border.top = ' ', .align = LEFT,
.cell.border.top_on = false, .border = {
.cell.border.right = ' ', .bottom = ' ',
.cell.border.right_on = false, .bottom_on = false,
.cell.border.left = ' ', .top = ' ',
.cell.border.left_on = false, .top_on = false,
.right = ' ',
.right_on = false,
.left = ' ',
.left_on = false,
},
}
} }
}; };
/* clang-format on */ /* clang-format on */

View File

@ -25,6 +25,7 @@
#include "log.h" #include "log.h"
#include "sockunion.h" #include "sockunion.h"
#include "qobj.h" #include "qobj.h"
#include "compiler.h"
#define VTY_BUFSIZ 4096 #define VTY_BUFSIZ 4096
#define VTY_MAXHIST 20 #define VTY_MAXHIST 20
@ -182,23 +183,11 @@ struct vty_arg {
/* Integrated configuration file. */ /* Integrated configuration file. */
#define INTEGRATE_DEFAULT_CONFIG "frr.conf" #define INTEGRATE_DEFAULT_CONFIG "frr.conf"
/* for compatibility */ #if CONFDATE > 20180401
#if defined(__ICC) CPP_NOTICE("It's probably time to remove VTY_NEWLINE compatibility foo.")
#define CPP_WARN_STR(X) #X
#define CPP_WARN(text) _Pragma(CPP_WARN_STR(message __FILE__ ": " text))
#elif (defined(__GNUC__) \
&& (__GNUC__ >= 5 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8))) \
|| (defined(__clang__) \
&& (__clang_major__ >= 4 \
|| (__clang_major__ == 3 && __clang_minor__ >= 5)))
#define CPP_WARN_STR(X) #X
#define CPP_WARN(text) _Pragma(CPP_WARN_STR(GCC warning text))
#else
#define CPP_WARN(text)
#endif #endif
/* for compatibility */
#define VNL "\n" CPP_WARN("VNL has been replaced with \\n.") #define VNL "\n" CPP_WARN("VNL has been replaced with \\n.")
#define VTYNL "\n" CPP_WARN("VTYNL has been replaced with \\n.") #define VTYNL "\n" CPP_WARN("VTYNL has been replaced with \\n.")
#define VTY_NEWLINE "\n" CPP_WARN("VTY_NEWLINE has been replaced with \\n.") #define VTY_NEWLINE "\n" CPP_WARN("VTY_NEWLINE has been replaced with \\n.")

View File

@ -352,10 +352,6 @@ void zclient_send_reg_requests(struct zclient *zclient, vrf_id_t vrf_id)
int i; int i;
afi_t afi; afi_t afi;
/* zclient is disabled. */
if (!zclient->enable)
return;
/* If not connected to the zebra yet. */ /* If not connected to the zebra yet. */
if (zclient->sock < 0) if (zclient->sock < 0)
return; return;
@ -418,10 +414,6 @@ void zclient_send_dereg_requests(struct zclient *zclient, vrf_id_t vrf_id)
int i; int i;
afi_t afi; afi_t afi;
/* zclient is disabled. */
if (!zclient->enable)
return;
/* If not connected to the zebra yet. */ /* If not connected to the zebra yet. */
if (zclient->sock < 0) if (zclient->sock < 0)
return; return;
@ -485,10 +477,6 @@ void zclient_send_interface_radv_req(struct zclient *zclient, vrf_id_t vrf_id,
{ {
struct stream *s; struct stream *s;
/* zclient is disabled. */
if (!zclient->enable)
return;
/* If not connected to the zebra yet. */ /* If not connected to the zebra yet. */
if (zclient->sock < 0) if (zclient->sock < 0)
return; return;
@ -516,10 +504,6 @@ int zclient_start(struct zclient *zclient)
if (zclient_debug) if (zclient_debug)
zlog_info("zclient_start is called"); zlog_info("zclient_start is called");
/* zclient is disabled. */
if (!zclient->enable)
return 0;
/* If already connected to the zebra. */ /* If already connected to the zebra. */
if (zclient->sock >= 0) if (zclient->sock >= 0)
return 0; return 0;
@ -564,9 +548,6 @@ void zclient_init(struct zclient *zclient, int redist_default, u_short instance)
{ {
int afi, i; int afi, i;
/* Enable zebra client connection by default. */
zclient->enable = 1;
/* Set -1 to the default socket value. */ /* Set -1 to the default socket value. */
zclient->sock = -1; zclient->sock = -1;
@ -911,24 +892,23 @@ int zapi_ipv6_route(u_char cmd, struct zclient *zclient, struct prefix_ipv6 *p,
return zclient_send_message(zclient); return zclient_send_message(zclient);
} }
int zapi_route(u_char cmd, struct zclient *zclient, struct prefix *p, int zclient_route_send(u_char cmd, struct zclient *zclient,
struct prefix_ipv6 *src_p, struct zapi_route *api) struct zapi_route *api)
{ {
if (zapi_route_encode(cmd, zclient->obuf, api) < 0)
return -1;
return zclient_send_message(zclient);
}
int zapi_route_encode(u_char cmd, struct stream *s, struct zapi_route *api)
{
struct zapi_nexthop *api_nh;
int i; int i;
int psize; 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);
/* Reset stream. */
s = zclient->obuf;
stream_reset(s); stream_reset(s);
zclient_create_header(s, cmd, api->vrf_id); zclient_create_header(s, cmd, api->vrf_id);
/* Put type and nexthop. */
stream_putc(s, api->type); stream_putc(s, api->type);
stream_putw(s, api->instance); stream_putw(s, api->instance);
stream_putl(s, api->flags); stream_putl(s, api->flags);
@ -936,72 +916,84 @@ int zapi_route(u_char cmd, struct zclient *zclient, struct prefix *p,
stream_putw(s, api->safi); stream_putw(s, api->safi);
/* Put prefix information. */ /* Put prefix information. */
psize = PSIZE(p->prefixlen); stream_putc(s, api->prefix.family);
stream_putc(s, p->prefixlen); psize = PSIZE(api->prefix.prefixlen);
stream_write(s, (u_char *)&p->u.prefix, psize); stream_putc(s, api->prefix.prefixlen);
stream_write(s, (u_char *)&api->prefix.u.prefix, psize);
if (CHECK_FLAG(api->message, ZAPI_MESSAGE_SRCPFX)) { if (CHECK_FLAG(api->message, ZAPI_MESSAGE_SRCPFX)) {
psize = PSIZE(src_p->prefixlen); psize = PSIZE(api->src_prefix.prefixlen);
stream_putc(s, src_p->prefixlen); stream_putc(s, api->src_prefix.prefixlen);
stream_write(s, (u_char *)&src_p->prefix, psize); stream_write(s, (u_char *)&api->src_prefix.prefix, psize);
} }
/* Nexthop, ifindex, distance and metric information. */ /* Nexthops. */
if (CHECK_FLAG(api->message, ZAPI_MESSAGE_NEXTHOP)) { if (CHECK_FLAG(api->message, ZAPI_MESSAGE_NEXTHOP)) {
stream_putc(s, api->nexthop_num); /* 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_putw(s, api->nexthop_num);
for (i = 0; i < api->nexthop_num; i++) { for (i = 0; i < api->nexthop_num; i++) {
stream_putc(s, api->nexthop[i]->type); api_nh = &api->nexthops[i];
switch (api->nexthop[i]->type) {
stream_putc(s, api_nh->type);
switch (api_nh->type) {
case NEXTHOP_TYPE_BLACKHOLE: case NEXTHOP_TYPE_BLACKHOLE:
break; break;
case NEXTHOP_TYPE_IPV4: case NEXTHOP_TYPE_IPV4:
stream_put_in_addr(s, stream_put_in_addr(s, &api_nh->gate.ipv4);
&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]);
break; break;
case NEXTHOP_TYPE_IPV4_IFINDEX: case NEXTHOP_TYPE_IPV4_IFINDEX:
stream_put_in_addr(s, stream_put_in_addr(s, &api_nh->gate.ipv4);
&api->nexthop[i]->gate.ipv4); stream_putl(s, api_nh->ifindex);
stream_putl(s, api->nexthop[i]->ifindex);
break; break;
case NEXTHOP_TYPE_IFINDEX: case NEXTHOP_TYPE_IFINDEX:
stream_putl(s, api->nexthop[i]->ifindex); stream_putl(s, api_nh->ifindex);
break; break;
case NEXTHOP_TYPE_IPV6: case NEXTHOP_TYPE_IPV6:
stream_write( stream_write(s, (u_char *)&api_nh->gate.ipv6,
s, 16);
(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]);
break; break;
case NEXTHOP_TYPE_IPV6_IFINDEX: case NEXTHOP_TYPE_IPV6_IFINDEX:
stream_write( stream_write(s, (u_char *)&api_nh->gate.ipv6,
s, 16);
(u_char *)&api->nexthop[i]->gate.ipv6, stream_putl(s, api_nh->ifindex);
16);
stream_putl(s, api->nexthop[i]->ifindex);
break; break;
} }
/* MPLS labels for BGP-LU or Segment Routing */
if (CHECK_FLAG(api->message, ZAPI_MESSAGE_LABEL)) {
if (api_nh->label_num > MPLS_MAX_LABELS) {
char buf[PREFIX2STR_BUFFER];
prefix2str(&api->prefix, buf,
sizeof(buf));
zlog_err(
"%s: prefix %s: can't encode "
"%u labels (maximum is %u)",
__func__, buf,
api_nh->label_num,
MPLS_MAX_LABELS);
return -1;
}
stream_putc(s, api_nh->label_num);
stream_put(s, &api_nh->labels[0],
api_nh->label_num
* sizeof(mpls_label_t));
}
} }
} }
/* Attributes. */
if (CHECK_FLAG(api->message, ZAPI_MESSAGE_DISTANCE)) if (CHECK_FLAG(api->message, ZAPI_MESSAGE_DISTANCE))
stream_putc(s, api->distance); stream_putc(s, api->distance);
if (CHECK_FLAG(api->message, ZAPI_MESSAGE_METRIC)) if (CHECK_FLAG(api->message, ZAPI_MESSAGE_METRIC))
@ -1014,7 +1006,110 @@ int zapi_route(u_char cmd, struct zclient *zclient, struct prefix *p,
/* Put length at the first point of the stream. */ /* Put length at the first point of the stream. */
stream_putw_at(s, 0, stream_get_endp(s)); stream_putw_at(s, 0, stream_get_endp(s));
return zclient_send_message(zclient); return 0;
}
int zapi_route_decode(struct stream *s, struct zapi_route *api)
{
struct zapi_nexthop *api_nh;
int i;
memset(api, 0, sizeof(*api));
/* Type, flags, message. */
api->type = stream_getc(s);
api->instance = stream_getw(s);
api->flags = stream_getl(s);
api->message = stream_getc(s);
api->safi = stream_getw(s);
/* Prefix. */
api->prefix.family = stream_getc(s);
switch (api->prefix.family) {
case AF_INET:
api->prefix.prefixlen = MIN(IPV4_MAX_PREFIXLEN, stream_getc(s));
break;
case AF_INET6:
api->prefix.prefixlen = MIN(IPV6_MAX_PREFIXLEN, stream_getc(s));
break;
}
stream_get(&api->prefix.u.prefix, s, PSIZE(api->prefix.prefixlen));
if (CHECK_FLAG(api->message, ZAPI_MESSAGE_SRCPFX)) {
api->src_prefix.family = AF_INET6;
api->src_prefix.prefixlen = stream_getc(s);
stream_get(&api->src_prefix.prefix, s,
PSIZE(api->src_prefix.prefixlen));
if (api->prefix.family != AF_INET6
|| api->src_prefix.prefixlen == 0)
UNSET_FLAG(api->message, ZAPI_MESSAGE_SRCPFX);
}
/* Nexthops. */
if (CHECK_FLAG(api->message, ZAPI_MESSAGE_NEXTHOP)) {
api->nexthop_num = stream_getw(s);
if (api->nexthop_num > MULTIPATH_NUM) {
zlog_warn("%s: invalid number of nexthops (%u)",
__func__, api->nexthop_num);
return -1;
}
for (i = 0; i < api->nexthop_num; i++) {
api_nh = &api->nexthops[i];
api_nh->type = stream_getc(s);
switch (api_nh->type) {
case NEXTHOP_TYPE_BLACKHOLE:
break;
case NEXTHOP_TYPE_IPV4:
api_nh->gate.ipv4.s_addr = stream_get_ipv4(s);
break;
case NEXTHOP_TYPE_IPV4_IFINDEX:
api_nh->gate.ipv4.s_addr = stream_get_ipv4(s);
api_nh->ifindex = stream_getl(s);
break;
case NEXTHOP_TYPE_IFINDEX:
api_nh->ifindex = stream_getl(s);
break;
case NEXTHOP_TYPE_IPV6:
stream_get(&api_nh->gate.ipv6, s, 16);
break;
case NEXTHOP_TYPE_IPV6_IFINDEX:
stream_get(&api_nh->gate.ipv6, s, 16);
api_nh->ifindex = stream_getl(s);
break;
}
/* MPLS labels for BGP-LU or Segment Routing */
if (CHECK_FLAG(api->message, ZAPI_MESSAGE_LABEL)) {
api_nh->label_num = stream_getc(s);
if (api_nh->label_num > MPLS_MAX_LABELS) {
zlog_warn(
"%s: invalid number of MPLS "
"labels (%u)",
__func__, api_nh->label_num);
return -1;
}
stream_get(&api_nh->labels[0], s,
api_nh->label_num
* sizeof(mpls_label_t));
}
}
}
/* Attributes. */
if (CHECK_FLAG(api->message, ZAPI_MESSAGE_DISTANCE))
api->distance = stream_getc(s);
if (CHECK_FLAG(api->message, ZAPI_MESSAGE_METRIC))
api->metric = stream_getl(s);
if (CHECK_FLAG(api->message, ZAPI_MESSAGE_TAG))
api->tag = stream_getl(s);
if (CHECK_FLAG(api->message, ZAPI_MESSAGE_MTU))
api->mtu = stream_getl(s);
return 0;
} }
/* /*
@ -2017,25 +2112,15 @@ static int zclient_read(struct thread *thread)
(*zclient->bfd_dest_replay)(command, zclient, length, (*zclient->bfd_dest_replay)(command, zclient, length,
vrf_id); vrf_id);
break; break;
case ZEBRA_REDISTRIBUTE_IPV4_ADD: case ZEBRA_REDISTRIBUTE_ROUTE_ADD:
if (zclient->redistribute_route_ipv4_add) if (zclient->redistribute_route_add)
(*zclient->redistribute_route_ipv4_add)( (*zclient->redistribute_route_add)(command, zclient,
command, zclient, length, vrf_id); length, vrf_id);
break; break;
case ZEBRA_REDISTRIBUTE_IPV4_DEL: case ZEBRA_REDISTRIBUTE_ROUTE_DEL:
if (zclient->redistribute_route_ipv4_del) if (zclient->redistribute_route_del)
(*zclient->redistribute_route_ipv4_del)( (*zclient->redistribute_route_del)(command, zclient,
command, zclient, length, vrf_id); length, vrf_id);
break;
case ZEBRA_REDISTRIBUTE_IPV6_ADD:
if (zclient->redistribute_route_ipv6_add)
(*zclient->redistribute_route_ipv6_add)(
command, zclient, length, vrf_id);
break;
case ZEBRA_REDISTRIBUTE_IPV6_DEL:
if (zclient->redistribute_route_ipv6_del)
(*zclient->redistribute_route_ipv6_del)(
command, zclient, length, vrf_id);
break; break;
case ZEBRA_INTERFACE_LINK_PARAMS: case ZEBRA_INTERFACE_LINK_PARAMS:
if (zclient->interface_link_params) if (zclient->interface_link_params)

View File

@ -21,7 +21,7 @@
#ifndef _ZEBRA_ZCLIENT_H #ifndef _ZEBRA_ZCLIENT_H
#define _ZEBRA_ZCLIENT_H #define _ZEBRA_ZCLIENT_H
/* For struct zapi_ipv{4,6}. */ /* For struct zapi_route. */
#include "prefix.h" #include "prefix.h"
/* For struct interface and struct connected. */ /* For struct interface and struct connected. */
@ -59,6 +59,8 @@ typedef enum {
ZEBRA_INTERFACE_UP, ZEBRA_INTERFACE_UP,
ZEBRA_INTERFACE_DOWN, ZEBRA_INTERFACE_DOWN,
ZEBRA_INTERFACE_SET_MASTER, ZEBRA_INTERFACE_SET_MASTER,
ZEBRA_ROUTE_ADD,
ZEBRA_ROUTE_DELETE,
ZEBRA_IPV4_ROUTE_ADD, ZEBRA_IPV4_ROUTE_ADD,
ZEBRA_IPV4_ROUTE_DELETE, ZEBRA_IPV4_ROUTE_DELETE,
ZEBRA_IPV6_ROUTE_ADD, ZEBRA_IPV6_ROUTE_ADD,
@ -85,10 +87,8 @@ typedef enum {
ZEBRA_BFD_DEST_DEREGISTER, ZEBRA_BFD_DEST_DEREGISTER,
ZEBRA_BFD_DEST_UPDATE, ZEBRA_BFD_DEST_UPDATE,
ZEBRA_BFD_DEST_REPLAY, ZEBRA_BFD_DEST_REPLAY,
ZEBRA_REDISTRIBUTE_IPV4_ADD, ZEBRA_REDISTRIBUTE_ROUTE_ADD,
ZEBRA_REDISTRIBUTE_IPV4_DEL, ZEBRA_REDISTRIBUTE_ROUTE_DEL,
ZEBRA_REDISTRIBUTE_IPV6_ADD,
ZEBRA_REDISTRIBUTE_IPV6_DEL,
ZEBRA_VRF_UNREGISTER, ZEBRA_VRF_UNREGISTER,
ZEBRA_VRF_ADD, ZEBRA_VRF_ADD,
ZEBRA_VRF_DELETE, ZEBRA_VRF_DELETE,
@ -100,10 +100,6 @@ typedef enum {
ZEBRA_INTERFACE_LINK_PARAMS, ZEBRA_INTERFACE_LINK_PARAMS,
ZEBRA_MPLS_LABELS_ADD, ZEBRA_MPLS_LABELS_ADD,
ZEBRA_MPLS_LABELS_DELETE, ZEBRA_MPLS_LABELS_DELETE,
ZEBRA_IPV4_NEXTHOP_ADD,
ZEBRA_IPV4_NEXTHOP_DELETE,
ZEBRA_IPV6_NEXTHOP_ADD,
ZEBRA_IPV6_NEXTHOP_DELETE,
ZEBRA_IPMR_ROUTE_STATS, ZEBRA_IPMR_ROUTE_STATS,
ZEBRA_LABEL_MANAGER_CONNECT, ZEBRA_LABEL_MANAGER_CONNECT,
ZEBRA_GET_LABEL_CHUNK, ZEBRA_GET_LABEL_CHUNK,
@ -141,10 +137,6 @@ struct zclient {
/* Socket to zebra daemon. */ /* Socket to zebra daemon. */
int sock; int sock;
/* Flag of communication to zebra is enabled or not. Default is on.
This flag is disabled by `no router zebra' statement. */
int enable;
/* Connection failure count. */ /* Connection failure count. */
int fail; int fail;
@ -194,14 +186,10 @@ struct zclient {
int (*nexthop_update)(int, struct zclient *, uint16_t, vrf_id_t); int (*nexthop_update)(int, struct zclient *, uint16_t, vrf_id_t);
int (*import_check_update)(int, struct zclient *, uint16_t, vrf_id_t); int (*import_check_update)(int, struct zclient *, uint16_t, vrf_id_t);
int (*bfd_dest_replay)(int, struct zclient *, uint16_t, vrf_id_t); int (*bfd_dest_replay)(int, struct zclient *, uint16_t, vrf_id_t);
int (*redistribute_route_ipv4_add)(int, struct zclient *, uint16_t, int (*redistribute_route_add)(int, struct zclient *, uint16_t,
vrf_id_t); vrf_id_t);
int (*redistribute_route_ipv4_del)(int, struct zclient *, uint16_t, int (*redistribute_route_del)(int, struct zclient *, uint16_t,
vrf_id_t); vrf_id_t);
int (*redistribute_route_ipv6_add)(int, struct zclient *, uint16_t,
vrf_id_t);
int (*redistribute_route_ipv6_del)(int, struct zclient *, uint16_t,
vrf_id_t);
int (*fec_update)(int, struct zclient *, uint16_t); int (*fec_update)(int, struct zclient *, uint16_t);
int (*local_vni_add)(int, struct zclient *, uint16_t, vrf_id_t); int (*local_vni_add)(int, struct zclient *, uint16_t, vrf_id_t);
int (*local_vni_del)(int, struct zclient *, uint16_t, vrf_id_t); int (*local_vni_del)(int, struct zclient *, uint16_t, vrf_id_t);
@ -212,13 +200,12 @@ struct zclient {
/* Zebra API message flag. */ /* Zebra API message flag. */
#define ZAPI_MESSAGE_NEXTHOP 0x01 #define ZAPI_MESSAGE_NEXTHOP 0x01
#define ZAPI_MESSAGE_IFINDEX 0x02 #define ZAPI_MESSAGE_DISTANCE 0x02
#define ZAPI_MESSAGE_DISTANCE 0x04 #define ZAPI_MESSAGE_METRIC 0x04
#define ZAPI_MESSAGE_METRIC 0x08 #define ZAPI_MESSAGE_TAG 0x08
#define ZAPI_MESSAGE_TAG 0x10 #define ZAPI_MESSAGE_MTU 0x10
#define ZAPI_MESSAGE_MTU 0x20 #define ZAPI_MESSAGE_SRCPFX 0x20
#define ZAPI_MESSAGE_SRCPFX 0x40 #define ZAPI_MESSAGE_LABEL 0x40
#define ZAPI_MESSAGE_LABEL 0x80
/* Zserv protocol message header */ /* Zserv protocol message header */
struct zserv_header { struct zserv_header {
@ -232,6 +219,16 @@ struct zserv_header {
uint16_t command; uint16_t command;
}; };
struct zapi_nexthop {
enum nexthop_types_t type;
ifindex_t ifindex;
union g_addr gate;
/* MPLS labels for BGP-LU or Segment Routing */
uint8_t label_num;
mpls_label_t labels[MPLS_MAX_LABELS];
};
struct zapi_route { struct zapi_route {
u_char type; u_char type;
u_short instance; u_short instance;
@ -242,8 +239,11 @@ struct zapi_route {
safi_t safi; safi_t safi;
u_char nexthop_num; struct prefix prefix;
struct nexthop **nexthop; struct prefix_ipv6 src_prefix;
u_int16_t nexthop_num;
struct zapi_nexthop nexthops[MULTIPATH_NUM];
u_char distance; u_char distance;
@ -369,7 +369,7 @@ 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_interface_if_set_value(struct stream *, struct interface *);
extern void zebra_router_id_update_read(struct stream *s, struct prefix *rid); extern void zebra_router_id_update_read(struct stream *s, struct prefix *rid);
extern int zapi_ipv4_route(u_char, struct zclient *, struct prefix_ipv4 *, extern int zapi_ipv4_route(u_char, struct zclient *, struct prefix_ipv4 *,
struct zapi_ipv4 *); struct zapi_ipv4 *) __attribute__((deprecated));
extern struct interface *zebra_interface_link_params_read(struct stream *); extern struct interface *zebra_interface_link_params_read(struct stream *);
extern size_t zebra_interface_link_params_write(struct stream *, extern size_t zebra_interface_link_params_write(struct stream *,
@ -420,11 +420,13 @@ struct zapi_ipv6 {
extern int zapi_ipv6_route(u_char cmd, struct zclient *zclient, extern int zapi_ipv6_route(u_char cmd, struct zclient *zclient,
struct prefix_ipv6 *p, struct prefix_ipv6 *src_p, struct prefix_ipv6 *p, struct prefix_ipv6 *src_p,
struct zapi_ipv6 *api); struct zapi_ipv6 *api) __attribute__((deprecated));
extern int zapi_ipv4_route_ipv6_nexthop(u_char, struct zclient *, extern int zapi_ipv4_route_ipv6_nexthop(u_char, struct zclient *,
struct prefix_ipv4 *, struct prefix_ipv4 *,
struct zapi_ipv6 *); struct zapi_ipv6 *)
extern int zapi_route(u_char cmd, struct zclient *zclient, struct prefix *p, __attribute__((deprecated));
struct prefix_ipv6 *src_p, struct zapi_route *api); extern int zclient_route_send(u_char, struct zclient *, struct zapi_route *);
extern int zapi_route_encode(u_char, struct stream *, struct zapi_route *);
extern int zapi_route_decode(struct stream *, struct zapi_route *);
#endif /* _ZEBRA_ZCLIENT_H */ #endif /* _ZEBRA_ZCLIENT_H */

View File

@ -86,14 +86,20 @@ void nhrp_route_update_nhrp(const struct prefix *p, struct interface *ifp)
void nhrp_route_announce(int add, enum nhrp_cache_type type, const struct prefix *p, struct interface *ifp, const union sockunion *nexthop, uint32_t mtu) void nhrp_route_announce(int add, enum nhrp_cache_type type, const struct prefix *p, struct interface *ifp, const union sockunion *nexthop, uint32_t mtu)
{ {
int flags = 0; struct zapi_route api;
struct zapi_nexthop *api_nh;
if (zclient->sock < 0) if (zclient->sock < 0)
return; return;
memset(&api, 0, sizeof(api));
api.type = ZEBRA_ROUTE_NHRP;
api.safi = SAFI_UNICAST;
api.prefix = *p;
switch (type) { switch (type) {
case NHRP_CACHE_NEGATIVE: case NHRP_CACHE_NEGATIVE:
SET_FLAG(flags, ZEBRA_FLAG_REJECT); SET_FLAG(api.flags, ZEBRA_FLAG_REJECT);
break; break;
case NHRP_CACHE_DYNAMIC: case NHRP_CACHE_DYNAMIC:
case NHRP_CACHE_NHS: case NHRP_CACHE_NHS:
@ -102,158 +108,106 @@ void nhrp_route_announce(int add, enum nhrp_cache_type type, const struct prefix
* to other routing daemons */ * to other routing daemons */
break; break;
default: default:
SET_FLAG(flags, ZEBRA_FLAG_FIB_OVERRIDE); SET_FLAG(api.flags, ZEBRA_FLAG_FIB_OVERRIDE);
break; break;
} }
SET_FLAG(flags, ZEBRA_FLAG_INTERNAL); SET_FLAG(api.flags, ZEBRA_FLAG_INTERNAL);
if (p->family == AF_INET) { SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
struct in_addr *nexthop_ipv4; api.nexthop_num = 1;
struct zapi_ipv4 api; api_nh = &api.nexthops[0];
memset(&api, 0, sizeof(api)); switch (api.prefix.family) {
api.flags = flags; case AF_INET:
api.type = ZEBRA_ROUTE_NHRP;
api.safi = SAFI_UNICAST;
SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
if (nexthop) { if (nexthop) {
nexthop_ipv4 = (struct in_addr *) sockunion_get_addr(nexthop); api_nh->gate.ipv4 = nexthop->sin.sin_addr;
api.nexthop_num = 1; api_nh->type = NEXTHOP_TYPE_IPV4;
api.nexthop = &nexthop_ipv4;
} }
if (ifp) { if (ifp) {
SET_FLAG(api.message, ZAPI_MESSAGE_IFINDEX); api_nh->ifindex = ifp->ifindex;
api.ifindex_num = 1; if (api_nh->type == NEXTHOP_TYPE_IPV4)
api.ifindex = &ifp->ifindex; api_nh->type = NEXTHOP_TYPE_IPV4_IFINDEX;
else
api_nh->type = NEXTHOP_TYPE_IFINDEX;
} }
if (mtu) { break;
SET_FLAG(api.message, ZAPI_MESSAGE_MTU); case AF_INET6:
api.mtu = mtu;
}
if (unlikely(debug_flags & NHRP_DEBUG_ROUTE)) {
char buf[2][INET_ADDRSTRLEN];
zlog_debug("Zebra send: IPv4 route %s %s/%d nexthop %s metric %u"
" count %d dev %s",
add ? "add" : "del",
inet_ntop(AF_INET, &p->u.prefix4, buf[0], sizeof(buf[0])),
p->prefixlen,
nexthop ? inet_ntop(AF_INET, api.nexthop[0], buf[1], sizeof(buf[1])) : "<onlink>",
api.metric, api.nexthop_num, ifp->name);
}
zapi_ipv4_route(
add ? ZEBRA_IPV4_ROUTE_ADD : ZEBRA_IPV4_ROUTE_DELETE,
zclient, (struct prefix_ipv4 *) p, &api);
} else if (p->family == AF_INET6) {
struct in6_addr *nexthop_ipv6;
struct zapi_ipv6 api;
memset(&api, 0, sizeof(api));
api.flags = flags;
api.type = ZEBRA_ROUTE_NHRP;
api.safi = SAFI_UNICAST;
SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
if (nexthop) { if (nexthop) {
nexthop_ipv6 = (struct in6_addr *) sockunion_get_addr(nexthop); api_nh->gate.ipv6 = nexthop->sin6.sin6_addr;
api.nexthop_num = 1; api_nh->type = NEXTHOP_TYPE_IPV6;
api.nexthop = &nexthop_ipv6;
} }
if (ifp) { if (ifp) {
SET_FLAG(api.message, ZAPI_MESSAGE_IFINDEX); api_nh->ifindex = ifp->ifindex;
api.ifindex_num = 1; if (api_nh->type == NEXTHOP_TYPE_IPV6)
api.ifindex = &ifp->ifindex; api_nh->type = NEXTHOP_TYPE_IPV6_IFINDEX;
else
api_nh->type = NEXTHOP_TYPE_IFINDEX;
} }
if (mtu) { break;
SET_FLAG(api.message, ZAPI_MESSAGE_MTU);
api.mtu = mtu;
}
if (unlikely(debug_flags & NHRP_DEBUG_ROUTE)) {
char buf[2][INET6_ADDRSTRLEN];
zlog_debug("Zebra send: IPv6 route %s %s/%d nexthop %s metric %u"
" count %d dev %s",
add ? "add" : "del",
inet_ntop(AF_INET6, &p->u.prefix6, buf[0], sizeof(buf[0])),
p->prefixlen,
nexthop ? inet_ntop(AF_INET6, api.nexthop[0], buf[1], sizeof(buf[1])) : "<onlink>",
api.metric, api.nexthop_num, ifp->name);
}
zapi_ipv6_route(
add ? ZEBRA_IPV6_ROUTE_ADD : ZEBRA_IPV6_ROUTE_DELETE,
zclient, (struct prefix_ipv6 *) p, NULL, &api);
} }
if (mtu) {
SET_FLAG(api.message, ZAPI_MESSAGE_MTU);
api.mtu = mtu;
}
if (unlikely(debug_flags & NHRP_DEBUG_ROUTE)) {
char buf[2][PREFIX_STRLEN];
prefix2str(&api.prefix, buf[0], sizeof(buf[0]));
zlog_debug("Zebra send: route %s %s nexthop %s metric %u"
" count %d dev %s",
add ? "add" : "del", buf[0],
nexthop ? inet_ntop(api.prefix.family, &api_nh->gate, buf[1], sizeof(buf[1])) : "<onlink>",
api.metric, api.nexthop_num, ifp->name);
}
zclient_route_send(add ? ZEBRA_ROUTE_ADD : ZEBRA_ROUTE_DELETE, zclient,
&api);
} }
int nhrp_route_read(int cmd, struct zclient *zclient, zebra_size_t length, vrf_id_t vrf_id) int nhrp_route_read(int cmd, struct zclient *zclient, zebra_size_t length, vrf_id_t vrf_id)
{ {
struct stream *s; struct zapi_route api;
struct zapi_nexthop *api_nh;
struct interface *ifp = NULL; struct interface *ifp = NULL;
struct prefix prefix;
union sockunion nexthop_addr; union sockunion nexthop_addr;
unsigned char message, nexthop_num, ifindex_num;
unsigned ifindex;
char buf[2][PREFIX_STRLEN]; char buf[2][PREFIX_STRLEN];
int i, afaddrlen, added; int added;
s = zclient->ibuf; if (zapi_route_decode(zclient->ibuf, &api) < 0)
memset(&prefix, 0, sizeof(prefix));
sockunion_family(&nexthop_addr) = AF_UNSPEC;
/* Type, flags, message. */
/*type =*/ stream_getc(s);
/*instance =*/ stream_getw(s);
/*flags =*/ stream_getl(s);
message = stream_getc(s);
/* Prefix */
switch (cmd) {
case ZEBRA_REDISTRIBUTE_IPV4_ADD:
case ZEBRA_REDISTRIBUTE_IPV4_DEL:
prefix.family = AF_INET;
break;
case ZEBRA_REDISTRIBUTE_IPV6_ADD:
case ZEBRA_REDISTRIBUTE_IPV6_DEL:
prefix.family = AF_INET6;
break;
default:
return -1; return -1;
}
afaddrlen = family2addrsize(prefix.family);
prefix.prefixlen = stream_getc(s);
stream_get(&prefix.u.val, s, PSIZE(prefix.prefixlen));
/* Nexthop, ifindex, distance, metric. */ /* we completely ignore srcdest routes for now. */
if (CHECK_FLAG(message, ZAPI_MESSAGE_NEXTHOP|ZAPI_MESSAGE_IFINDEX)) { if (CHECK_FLAG(api.message, ZAPI_MESSAGE_SRCPFX))
nexthop_num = stream_getc(s); return 0;
for (i = 0; i < nexthop_num; i++) {
stream_get(buf[0], s, afaddrlen);
if (i == 0) sockunion_set(&nexthop_addr, prefix.family, (u_char*) buf[0], afaddrlen);
}
ifindex_num = stream_getc(s);
for (i = 0; i < ifindex_num; i++) {
ifindex = stream_getl(s);
if (i == 0 && ifindex != IFINDEX_INTERNAL)
ifp = if_lookup_by_index(ifindex, VRF_DEFAULT);
}
}
if (CHECK_FLAG(message, ZAPI_MESSAGE_DISTANCE))
/*distance =*/ stream_getc(s);
if (CHECK_FLAG(message, ZAPI_MESSAGE_METRIC))
/*metric =*/ stream_getl(s);
added = (cmd == ZEBRA_REDISTRIBUTE_IPV4_ADD || cmd == ZEBRA_REDISTRIBUTE_IPV6_ADD); sockunion_family(&nexthop_addr) = AF_UNSPEC;
if (CHECK_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP)) {
api_nh = &api.nexthops[0];
nexthop_addr.sa.sa_family = api.prefix.family;
switch (nexthop_addr.sa.sa_family) {
case AF_INET:
nexthop_addr.sin.sin_addr = api_nh->gate.ipv4;
break;
case AF_INET6:
nexthop_addr.sin6.sin6_addr = api_nh->gate.ipv6;
break;
}
if (api_nh->ifindex != IFINDEX_INTERNAL)
ifp = if_lookup_by_index(api_nh->ifindex, VRF_DEFAULT);
}
added = (cmd == ZEBRA_REDISTRIBUTE_ROUTE_ADD);
debugf(NHRP_DEBUG_ROUTE, "if-route-%s: %s via %s dev %s", debugf(NHRP_DEBUG_ROUTE, "if-route-%s: %s via %s dev %s",
added ? "add" : "del", added ? "add" : "del",
prefix2str(&prefix, buf[0], sizeof buf[0]), prefix2str(&api.prefix, buf[0], sizeof buf[0]),
sockunion2str(&nexthop_addr, buf[1], sizeof buf[1]), sockunion2str(&nexthop_addr, buf[1], sizeof buf[1]),
ifp ? ifp->name : "(none)"); ifp ? ifp->name : "(none)");
nhrp_route_update_zebra(&prefix, &nexthop_addr, ifp); nhrp_route_update_zebra(&api.prefix, &nexthop_addr, ifp);
nhrp_shortcut_prefix_change(&prefix, !added); nhrp_shortcut_prefix_change(&api.prefix, !added);
return 0; return 0;
} }
@ -366,10 +320,8 @@ void nhrp_zebra_init(void)
zclient->interface_down = nhrp_interface_down; zclient->interface_down = nhrp_interface_down;
zclient->interface_address_add = nhrp_interface_address_add; zclient->interface_address_add = nhrp_interface_address_add;
zclient->interface_address_delete = nhrp_interface_address_delete; zclient->interface_address_delete = nhrp_interface_address_delete;
zclient->redistribute_route_ipv4_add = nhrp_route_read; zclient->redistribute_route_add = nhrp_route_read;
zclient->redistribute_route_ipv4_del = nhrp_route_read; zclient->redistribute_route_del = nhrp_route_read;
zclient->redistribute_route_ipv6_add = nhrp_route_read;
zclient->redistribute_route_ipv6_del = nhrp_route_read;
zclient_init(zclient, ZEBRA_ROUTE_NHRP, 0); zclient_init(zclient, ZEBRA_ROUTE_NHRP, 0);
} }
@ -381,4 +333,3 @@ void nhrp_zebra_terminate(void)
route_table_finish(zebra_rib[AFI_IP]); route_table_finish(zebra_rib[AFI_IP]);
route_table_finish(zebra_rib[AFI_IP6]); route_table_finish(zebra_rib[AFI_IP6]);
} }

View File

@ -386,27 +386,20 @@ int ospf6_abr_originate_summary_to_area(struct ospf6_route *route,
} }
/* Check filter-list */ /* Check filter-list */
if (PREFIX_NAME_OUT(area)) { if (PREFIX_LIST_OUT(area))
if (PREFIX_LIST_OUT(area) == NULL) if (prefix_list_apply(PREFIX_LIST_OUT(area), &route->prefix)
PREFIX_LIST_OUT(area) = prefix_list_lookup( != PREFIX_PERMIT) {
AFI_IP6, PREFIX_NAME_OUT(area)); if (is_debug) {
inet_ntop(AF_INET,
if (PREFIX_LIST_OUT(area)) &(ADV_ROUTER_IN_PREFIX(
if (prefix_list_apply(PREFIX_LIST_OUT(area), &route->prefix)),
&route->prefix) buf, sizeof(buf));
!= PREFIX_PERMIT) { zlog_debug(
if (is_debug) { "prefix %s was denied by filter-list out",
inet_ntop(AF_INET, buf);
&(ADV_ROUTER_IN_PREFIX(
&route->prefix)),
buf, sizeof(buf));
zlog_debug(
"prefix %s was denied by filter-list out",
buf);
}
return 0;
} }
} return 0;
}
/* the route is going to be originated. store it in area's summary_table /* the route is going to be originated. store it in area's summary_table
*/ */
@ -873,22 +866,16 @@ void ospf6_abr_examin_summary(struct ospf6_lsa *lsa, struct ospf6_area *oa)
} }
/* Check input prefix-list */ /* Check input prefix-list */
if (PREFIX_NAME_IN(oa)) { if (PREFIX_LIST_IN(oa))
if (PREFIX_LIST_IN(oa) == NULL) if (prefix_list_apply(PREFIX_LIST_IN(oa), &prefix)
PREFIX_LIST_IN(oa) = != PREFIX_PERMIT) {
prefix_list_lookup(AFI_IP6, PREFIX_NAME_IN(oa)); if (is_debug)
zlog_debug(
if (PREFIX_LIST_IN(oa)) "Prefix was denied by prefix-list");
if (prefix_list_apply(PREFIX_LIST_IN(oa), &prefix) if (old)
!= PREFIX_PERMIT) { ospf6_route_remove(old, table);
if (is_debug) return;
zlog_debug( }
"Prefix was denied by prefix-list");
if (old)
ospf6_route_remove(old, table);
return;
}
}
/* (5),(6): the path preference is handled by the sorting /* (5),(6): the path preference is handled by the sorting
in the routing table. Always install the path by substituting in the routing table. Always install the path by substituting

View File

@ -45,6 +45,8 @@
#include "ospf6_asbr.h" #include "ospf6_asbr.h"
#include "ospf6d.h" #include "ospf6d.h"
DEFINE_MTYPE_STATIC(OSPF6D, OSPF6_PLISTNAME, "Prefix list name")
int ospf6_area_cmp(void *va, void *vb) int ospf6_area_cmp(void *va, void *vb)
{ {
struct ospf6_area *oa = (struct ospf6_area *)va; struct ospf6_area *oa = (struct ospf6_area *)va;
@ -579,17 +581,15 @@ DEFUN (area_filter_list,
plist = prefix_list_lookup(AFI_IP6, plistname); plist = prefix_list_lookup(AFI_IP6, plistname);
if (strmatch(inout, "in")) { if (strmatch(inout, "in")) {
PREFIX_LIST_IN(area) = plist; PREFIX_LIST_IN(area) = plist;
if (PREFIX_NAME_IN(area)) XFREE(MTYPE_OSPF6_PLISTNAME, PREFIX_NAME_IN(area));
free(PREFIX_NAME_IN(area)); PREFIX_NAME_IN(area) = XSTRDUP(MTYPE_OSPF6_PLISTNAME,
plistname);
PREFIX_NAME_IN(area) = strdup(plistname);
ospf6_abr_reimport(area); ospf6_abr_reimport(area);
} else { } else {
PREFIX_LIST_OUT(area) = plist; PREFIX_LIST_OUT(area) = plist;
if (PREFIX_NAME_OUT(area)) XFREE(MTYPE_OSPF6_PLISTNAME, PREFIX_NAME_OUT(area));
free(PREFIX_NAME_OUT(area)); PREFIX_NAME_OUT(area) = XSTRDUP(MTYPE_OSPF6_PLISTNAME,
plistname);
PREFIX_NAME_OUT(area) = strdup(plistname);
ospf6_abr_enable_area(area); ospf6_abr_enable_area(area);
} }
@ -622,27 +622,34 @@ DEFUN (no_area_filter_list,
return CMD_SUCCESS; return CMD_SUCCESS;
PREFIX_LIST_IN(area) = NULL; PREFIX_LIST_IN(area) = NULL;
if (PREFIX_NAME_IN(area)) XFREE(MTYPE_OSPF6_PLISTNAME, PREFIX_NAME_IN(area));
free(PREFIX_NAME_IN(area));
PREFIX_NAME_IN(area) = NULL;
ospf6_abr_reimport(area); ospf6_abr_reimport(area);
} else { } else {
if (PREFIX_NAME_OUT(area)) if (PREFIX_NAME_OUT(area))
if (!strmatch(PREFIX_NAME_OUT(area), plistname)) if (!strmatch(PREFIX_NAME_OUT(area), plistname))
return CMD_SUCCESS; return CMD_SUCCESS;
PREFIX_LIST_OUT(area) = NULL; XFREE(MTYPE_OSPF6_PLISTNAME, PREFIX_NAME_OUT(area));
if (PREFIX_NAME_OUT(area))
free(PREFIX_NAME_OUT(area));
PREFIX_NAME_OUT(area) = NULL;
ospf6_abr_enable_area(area); ospf6_abr_enable_area(area);
} }
return CMD_SUCCESS; return CMD_SUCCESS;
} }
void ospf6_area_plist_update(struct prefix_list *plist, int add)
{
struct ospf6_area *oa;
struct listnode *n;
const char *name = prefix_list_name(plist);
for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, n, oa)) {
if (!strcmp(PREFIX_NAME_IN(oa), name))
PREFIX_LIST_IN(oa) = add ? plist : NULL;
if (!strcmp(PREFIX_NAME_OUT(oa), name))
PREFIX_LIST_OUT(oa) = add ? plist : NULL;
}
}
DEFUN (area_import_list, DEFUN (area_import_list,
area_import_list_cmd, area_import_list_cmd,
"area A.B.C.D import-list NAME", "area A.B.C.D import-list NAME",

View File

@ -122,6 +122,7 @@ extern void ospf6_area_disable(struct ospf6_area *);
extern void ospf6_area_show(struct vty *, struct ospf6_area *); extern void ospf6_area_show(struct vty *, struct ospf6_area *);
extern void ospf6_area_plist_update(struct prefix_list *plist, int add);
extern void ospf6_area_config_write(struct vty *vty); extern void ospf6_area_config_write(struct vty *vty);
extern void ospf6_area_init(void); extern void ospf6_area_init(void);

View File

@ -1171,8 +1171,7 @@ DEFUN (ipv6_ospf6_cost,
IP6_STR IP6_STR
OSPF6_STR OSPF6_STR
"Interface cost\n" "Interface cost\n"
"Outgoing metric of this interface\n" "Outgoing metric of this interface\n")
)
{ {
VTY_DECLVAR_CONTEXT(interface, ifp); VTY_DECLVAR_CONTEXT(interface, ifp);
int idx_number = 3; int idx_number = 3;
@ -1206,12 +1205,12 @@ DEFUN (ipv6_ospf6_cost,
DEFUN (no_ipv6_ospf6_cost, DEFUN (no_ipv6_ospf6_cost,
no_ipv6_ospf6_cost_cmd, no_ipv6_ospf6_cost_cmd,
"no ipv6 ospf6 cost", "no ipv6 ospf6 cost [(1-65535)]",
NO_STR NO_STR
IP6_STR IP6_STR
OSPF6_STR OSPF6_STR
"Calculate interface cost from bandwidth\n" "Calculate interface cost from bandwidth\n"
) "Outgoing metric of this interface\n")
{ {
VTY_DECLVAR_CONTEXT(interface, ifp); VTY_DECLVAR_CONTEXT(interface, ifp);
struct ospf6_interface *oi; struct ospf6_interface *oi;
@ -1292,8 +1291,7 @@ DEFUN (ipv6_ospf6_hellointerval,
IP6_STR IP6_STR
OSPF6_STR OSPF6_STR
"Time between HELLO packets\n" "Time between HELLO packets\n"
SECONDS_STR SECONDS_STR)
)
{ {
VTY_DECLVAR_CONTEXT(interface, ifp); VTY_DECLVAR_CONTEXT(interface, ifp);
int idx_number = 3; int idx_number = 3;
@ -1305,10 +1303,21 @@ DEFUN (ipv6_ospf6_hellointerval,
oi = ospf6_interface_create(ifp); oi = ospf6_interface_create(ifp);
assert(oi); assert(oi);
oi->hello_interval = strtol(argv[idx_number]->arg, NULL, 10); oi->hello_interval = strmatch(argv[0]->text, "no")
? OSPF_HELLO_INTERVAL_DEFAULT
: strtoul(argv[idx_number]->arg, NULL, 10);
return CMD_SUCCESS; return CMD_SUCCESS;
} }
ALIAS (ipv6_ospf6_hellointerval,
no_ipv6_ospf6_hellointerval_cmd,
"no ipv6 ospf6 hello-interval [(1-65535)]",
NO_STR
IP6_STR
OSPF6_STR
"Time between HELLO packets\n"
SECONDS_STR)
/* interface variable set command */ /* interface variable set command */
DEFUN (ipv6_ospf6_deadinterval, DEFUN (ipv6_ospf6_deadinterval,
ipv6_ospf6_deadinterval_cmd, ipv6_ospf6_deadinterval_cmd,
@ -1316,8 +1325,7 @@ DEFUN (ipv6_ospf6_deadinterval,
IP6_STR IP6_STR
OSPF6_STR OSPF6_STR
"Interval time after which a neighbor is declared down\n" "Interval time after which a neighbor is declared down\n"
SECONDS_STR SECONDS_STR)
)
{ {
VTY_DECLVAR_CONTEXT(interface, ifp); VTY_DECLVAR_CONTEXT(interface, ifp);
int idx_number = 3; int idx_number = 3;
@ -1329,10 +1337,21 @@ DEFUN (ipv6_ospf6_deadinterval,
oi = ospf6_interface_create(ifp); oi = ospf6_interface_create(ifp);
assert(oi); assert(oi);
oi->dead_interval = strtol(argv[idx_number]->arg, NULL, 10); oi->dead_interval = strmatch(argv[0]->arg, "no")
? OSPF_ROUTER_DEAD_INTERVAL_DEFAULT
: strtoul(argv[idx_number]->arg, NULL, 10);
return CMD_SUCCESS; return CMD_SUCCESS;
} }
ALIAS (ipv6_ospf6_deadinterval,
no_ipv6_ospf6_deadinterval_cmd,
"no ipv6 ospf6 dead-interval [(1-65535)]",
NO_STR
IP6_STR
OSPF6_STR
"Interval time after which a neighbor is declared down\n"
SECONDS_STR)
/* interface variable set command */ /* interface variable set command */
DEFUN (ipv6_ospf6_transmitdelay, DEFUN (ipv6_ospf6_transmitdelay,
ipv6_ospf6_transmitdelay_cmd, ipv6_ospf6_transmitdelay_cmd,
@ -1352,10 +1371,21 @@ DEFUN (ipv6_ospf6_transmitdelay,
oi = ospf6_interface_create(ifp); oi = ospf6_interface_create(ifp);
assert(oi); assert(oi);
oi->transdelay = strtol(argv[idx_number]->arg, NULL, 10); oi->transdelay = strmatch(argv[0]->text, "no")
? OSPF6_INTERFACE_TRANSDELAY
: strtoul(argv[idx_number]->arg, NULL, 10);
return CMD_SUCCESS; return CMD_SUCCESS;
} }
ALIAS (ipv6_ospf6_transmitdelay,
no_ipv6_ospf6_transmitdelay_cmd,
"no ipv6 ospf6 transmit-delay [(1-3600)]",
NO_STR
IP6_STR
OSPF6_STR
"Link state transmit delay\n"
SECONDS_STR)
/* interface variable set command */ /* interface variable set command */
DEFUN (ipv6_ospf6_retransmitinterval, DEFUN (ipv6_ospf6_retransmitinterval,
ipv6_ospf6_retransmitinterval_cmd, ipv6_ospf6_retransmitinterval_cmd,
@ -1363,8 +1393,7 @@ DEFUN (ipv6_ospf6_retransmitinterval,
IP6_STR IP6_STR
OSPF6_STR OSPF6_STR
"Time between retransmitting lost link state advertisements\n" "Time between retransmitting lost link state advertisements\n"
SECONDS_STR SECONDS_STR)
)
{ {
VTY_DECLVAR_CONTEXT(interface, ifp); VTY_DECLVAR_CONTEXT(interface, ifp);
int idx_number = 3; int idx_number = 3;
@ -1376,10 +1405,21 @@ DEFUN (ipv6_ospf6_retransmitinterval,
oi = ospf6_interface_create(ifp); oi = ospf6_interface_create(ifp);
assert(oi); assert(oi);
oi->rxmt_interval = strtol(argv[idx_number]->arg, NULL, 10); oi->rxmt_interval = strmatch(argv[0]->text, "no")
? OSPF_RETRANSMIT_INTERVAL_DEFAULT
: strtoul(argv[idx_number]->arg, NULL, 10);
return CMD_SUCCESS; return CMD_SUCCESS;
} }
ALIAS (ipv6_ospf6_retransmitinterval,
no_ipv6_ospf6_retransmitinterval_cmd,
"no ipv6 ospf6 retransmit-interval [(1-65535)]",
NO_STR
IP6_STR
OSPF6_STR
"Time between retransmitting lost link state advertisements\n"
SECONDS_STR)
/* interface variable set command */ /* interface variable set command */
DEFUN (ipv6_ospf6_priority, DEFUN (ipv6_ospf6_priority,
ipv6_ospf6_priority_cmd, ipv6_ospf6_priority_cmd,
@ -1387,8 +1427,7 @@ DEFUN (ipv6_ospf6_priority,
IP6_STR IP6_STR
OSPF6_STR OSPF6_STR
"Router priority\n" "Router priority\n"
"Priority value\n" "Priority value\n")
)
{ {
VTY_DECLVAR_CONTEXT(interface, ifp); VTY_DECLVAR_CONTEXT(interface, ifp);
int idx_number = 3; int idx_number = 3;
@ -1400,7 +1439,9 @@ DEFUN (ipv6_ospf6_priority,
oi = ospf6_interface_create(ifp); oi = ospf6_interface_create(ifp);
assert(oi); assert(oi);
oi->priority = strtol(argv[idx_number]->arg, NULL, 10); oi->priority = strmatch(argv[0]->text, "no")
? OSPF6_INTERFACE_PRIORITY
: strtoul(argv[idx_number]->arg, NULL, 10);
if (oi->area && (oi->state == OSPF6_INTERFACE_DROTHER if (oi->area && (oi->state == OSPF6_INTERFACE_DROTHER
|| oi->state == OSPF6_INTERFACE_BDR || oi->state == OSPF6_INTERFACE_BDR
@ -1410,14 +1451,22 @@ DEFUN (ipv6_ospf6_priority,
return CMD_SUCCESS; return CMD_SUCCESS;
} }
ALIAS (ipv6_ospf6_priority,
no_ipv6_ospf6_priority_cmd,
"no ipv6 ospf6 priority [(0-255)]",
NO_STR
IP6_STR
OSPF6_STR
"Router priority\n"
"Priority value\n")
DEFUN (ipv6_ospf6_instance, DEFUN (ipv6_ospf6_instance,
ipv6_ospf6_instance_cmd, ipv6_ospf6_instance_cmd,
"ipv6 ospf6 instance-id (0-255)", "ipv6 ospf6 instance-id (0-255)",
IP6_STR IP6_STR
OSPF6_STR OSPF6_STR
"Instance ID for this interface\n" "Instance ID for this interface\n"
"Instance ID value\n" "Instance ID value\n")
)
{ {
VTY_DECLVAR_CONTEXT(interface, ifp); VTY_DECLVAR_CONTEXT(interface, ifp);
int idx_number = 3; int idx_number = 3;
@ -1429,10 +1478,21 @@ DEFUN (ipv6_ospf6_instance,
oi = ospf6_interface_create(ifp); oi = ospf6_interface_create(ifp);
assert(oi); assert(oi);
oi->instance_id = strtol(argv[idx_number]->arg, NULL, 10); oi->instance_id = strmatch(argv[0]->text, "no")
? OSPF6_INTERFACE_INSTANCE_ID
: strtoul(argv[idx_number]->arg, NULL, 10);
return CMD_SUCCESS; return CMD_SUCCESS;
} }
ALIAS (ipv6_ospf6_instance,
no_ipv6_ospf6_instance_cmd,
"no ipv6 ospf6 instance-id [(0-255)]",
NO_STR
IP6_STR
OSPF6_STR
"Instance ID for this interface\n"
"Instance ID value\n")
DEFUN (ipv6_ospf6_passive, DEFUN (ipv6_ospf6_passive,
ipv6_ospf6_passive_cmd, ipv6_ospf6_passive_cmd,
"ipv6 ospf6 passive", "ipv6 ospf6 passive",
@ -1576,13 +1636,13 @@ DEFUN (ipv6_ospf6_advertise_prefix_list,
DEFUN (no_ipv6_ospf6_advertise_prefix_list, DEFUN (no_ipv6_ospf6_advertise_prefix_list,
no_ipv6_ospf6_advertise_prefix_list_cmd, no_ipv6_ospf6_advertise_prefix_list_cmd,
"no ipv6 ospf6 advertise prefix-list", "no ipv6 ospf6 advertise prefix-list [WORD]",
NO_STR NO_STR
IP6_STR IP6_STR
OSPF6_STR OSPF6_STR
"Advertising options\n" "Advertising options\n"
"Filter prefix using prefix-list\n" "Filter prefix using prefix-list\n"
) "Prefix list name\n")
{ {
VTY_DECLVAR_CONTEXT(interface, ifp); VTY_DECLVAR_CONTEXT(interface, ifp);
struct ospf6_interface *oi; struct ospf6_interface *oi;
@ -1593,10 +1653,8 @@ DEFUN (no_ipv6_ospf6_advertise_prefix_list,
oi = ospf6_interface_create(ifp); oi = ospf6_interface_create(ifp);
assert(oi); assert(oi);
if (oi->plist_name) { if (oi->plist_name)
XFREE(MTYPE_CFG_PLIST_NAME, oi->plist_name); XFREE(MTYPE_CFG_PLIST_NAME, oi->plist_name);
oi->plist_name = NULL;
}
ospf6_interface_connected_route_update(oi->interface); ospf6_interface_connected_route_update(oi->interface);
@ -1654,11 +1712,13 @@ DEFUN (ipv6_ospf6_network,
DEFUN (no_ipv6_ospf6_network, DEFUN (no_ipv6_ospf6_network,
no_ipv6_ospf6_network_cmd, no_ipv6_ospf6_network_cmd,
"no ipv6 ospf6 network", "no ipv6 ospf6 network [<broadcast|point-to-point>]",
NO_STR NO_STR
IP6_STR IP6_STR
OSPF6_STR OSPF6_STR
"Set default network type\n") "Set default network type\n"
"Specify OSPF6 broadcast network\n"
"Specify OSPF6 point-to-point network\n")
{ {
VTY_DECLVAR_CONTEXT(interface, ifp); VTY_DECLVAR_CONTEXT(interface, ifp);
struct ospf6_interface *oi; struct ospf6_interface *oi;
@ -1772,12 +1832,19 @@ void ospf6_interface_init(void)
install_element(INTERFACE_NODE, &no_ipv6_ospf6_cost_cmd); install_element(INTERFACE_NODE, &no_ipv6_ospf6_cost_cmd);
install_element(INTERFACE_NODE, &ipv6_ospf6_ifmtu_cmd); install_element(INTERFACE_NODE, &ipv6_ospf6_ifmtu_cmd);
install_element(INTERFACE_NODE, &no_ipv6_ospf6_ifmtu_cmd); install_element(INTERFACE_NODE, &no_ipv6_ospf6_ifmtu_cmd);
install_element(INTERFACE_NODE, &ipv6_ospf6_deadinterval_cmd); install_element(INTERFACE_NODE, &ipv6_ospf6_deadinterval_cmd);
install_element(INTERFACE_NODE, &ipv6_ospf6_hellointerval_cmd); install_element(INTERFACE_NODE, &ipv6_ospf6_hellointerval_cmd);
install_element(INTERFACE_NODE, &ipv6_ospf6_priority_cmd); install_element(INTERFACE_NODE, &ipv6_ospf6_priority_cmd);
install_element(INTERFACE_NODE, &ipv6_ospf6_retransmitinterval_cmd); install_element(INTERFACE_NODE, &ipv6_ospf6_retransmitinterval_cmd);
install_element(INTERFACE_NODE, &ipv6_ospf6_transmitdelay_cmd); install_element(INTERFACE_NODE, &ipv6_ospf6_transmitdelay_cmd);
install_element(INTERFACE_NODE, &ipv6_ospf6_instance_cmd); install_element(INTERFACE_NODE, &ipv6_ospf6_instance_cmd);
install_element(INTERFACE_NODE, &no_ipv6_ospf6_deadinterval_cmd);
install_element(INTERFACE_NODE, &no_ipv6_ospf6_hellointerval_cmd);
install_element(INTERFACE_NODE, &no_ipv6_ospf6_priority_cmd);
install_element(INTERFACE_NODE, &no_ipv6_ospf6_retransmitinterval_cmd);
install_element(INTERFACE_NODE, &no_ipv6_ospf6_transmitdelay_cmd);
install_element(INTERFACE_NODE, &no_ipv6_ospf6_instance_cmd);
install_element(INTERFACE_NODE, &ipv6_ospf6_passive_cmd); install_element(INTERFACE_NODE, &ipv6_ospf6_passive_cmd);
install_element(INTERFACE_NODE, &no_ipv6_ospf6_passive_cmd); install_element(INTERFACE_NODE, &no_ipv6_ospf6_passive_cmd);

View File

@ -285,8 +285,7 @@ void ospf6_add_nexthop(struct list *nh_list, int ifindex, struct in6_addr *addr)
} }
void ospf6_route_zebra_copy_nexthops(struct ospf6_route *route, void ospf6_route_zebra_copy_nexthops(struct ospf6_route *route,
ifindex_t *ifindexes, struct zapi_nexthop nexthops[],
struct in6_addr **nexthop_addr,
int entries) int entries)
{ {
struct ospf6_nexthop *nh; struct ospf6_nexthop *nh;
@ -306,13 +305,16 @@ void ospf6_route_zebra_copy_nexthops(struct ospf6_route *route,
zlog_debug(" nexthop: %s%%%.*s(%d)", buf, zlog_debug(" nexthop: %s%%%.*s(%d)", buf,
IFNAMSIZ, ifname, nh->ifindex); IFNAMSIZ, ifname, nh->ifindex);
} }
if (i < entries) { if (i >= entries)
nexthop_addr[i] = &nh->address;
ifindexes[i] = nh->ifindex;
i++;
} else {
return; return;
}
nexthops[i].ifindex = nh->ifindex;
if (!IN6_IS_ADDR_UNSPECIFIED(&nh->address)) {
nexthops[i].gate.ipv6 = nh->address;
nexthops[i].type = NEXTHOP_TYPE_IPV6_IFINDEX;
} else
nexthops[i].type = NEXTHOP_TYPE_IFINDEX;
i++;
} }
} }
} }

View File

@ -22,6 +22,7 @@
#define OSPF6_ROUTE_H #define OSPF6_ROUTE_H
#include "command.h" #include "command.h"
#include "zclient.h"
#define OSPF6_MULTI_PATH_LIMIT 4 #define OSPF6_MULTI_PATH_LIMIT 4
@ -266,8 +267,7 @@ extern int ospf6_num_nexthops(struct list *nh_list);
extern int ospf6_route_cmp_nexthops(struct ospf6_route *a, extern int ospf6_route_cmp_nexthops(struct ospf6_route *a,
struct ospf6_route *b); struct ospf6_route *b);
extern void ospf6_route_zebra_copy_nexthops(struct ospf6_route *route, extern void ospf6_route_zebra_copy_nexthops(struct ospf6_route *route,
ifindex_t *ifindices, struct zapi_nexthop nexthops[],
struct in6_addr **addr,
int entries); int entries);
extern int ospf6_route_get_first_nh_index(struct ospf6_route *route); extern int ospf6_route_get_first_nh_index(struct ospf6_route *route);

View File

@ -207,75 +207,30 @@ static int ospf6_zebra_if_address_update_delete(int command,
return 0; return 0;
} }
static int ospf6_zebra_read_ipv6(int command, struct zclient *zclient, static int ospf6_zebra_read_route(int command, struct zclient *zclient,
zebra_size_t length, vrf_id_t vrf_id) zebra_size_t length, vrf_id_t vrf_id)
{ {
struct stream *s; struct zapi_route api;
struct zapi_ipv6 api;
unsigned long ifindex; unsigned long ifindex;
struct prefix p, src_p;
struct in6_addr *nexthop; struct in6_addr *nexthop;
if (ospf6 == NULL) if (ospf6 == NULL)
return 0; return 0;
s = zclient->ibuf; if (zapi_route_decode(zclient->ibuf, &api) < 0)
ifindex = 0; return -1;
nexthop = NULL;
memset(&api, 0, sizeof(api));
/* Type, flags, message. */ /* we completely ignore srcdest routes for now. */
api.type = stream_getc(s); if (CHECK_FLAG(api.message, ZAPI_MESSAGE_SRCPFX))
api.instance = stream_getw(s);
api.flags = stream_getl(s);
api.message = stream_getc(s);
/* IPv6 prefix. */
memset(&p, 0, sizeof(struct prefix));
p.family = AF_INET6;
p.prefixlen = MIN(IPV6_MAX_PREFIXLEN, stream_getc(s));
stream_get(&p.u.prefix6, s, PSIZE(p.prefixlen));
memset(&src_p, 0, sizeof(struct prefix));
src_p.family = AF_INET6;
if (CHECK_FLAG(api.message, ZAPI_MESSAGE_SRCPFX)) {
src_p.prefixlen = stream_getc(s);
stream_get(&src_p.u.prefix6, s, PSIZE(src_p.prefixlen));
}
if (src_p.prefixlen)
/* we completely ignore srcdest routes for now. */
return 0; return 0;
/* Nexthop, ifindex, distance, metric. */ ifindex = api.nexthops[0].ifindex;
if (CHECK_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP)) { nexthop = &api.nexthops[0].gate.ipv6;
api.nexthop_num = stream_getc(s);
nexthop = (struct in6_addr *)malloc(api.nexthop_num
* sizeof(struct in6_addr));
stream_get(nexthop, s,
api.nexthop_num * sizeof(struct in6_addr));
}
if (CHECK_FLAG(api.message, ZAPI_MESSAGE_IFINDEX)) {
api.ifindex_num = stream_getc(s);
ifindex = stream_getl(s);
}
if (CHECK_FLAG(api.message, ZAPI_MESSAGE_DISTANCE))
api.distance = stream_getc(s);
else
api.distance = 0;
if (CHECK_FLAG(api.message, ZAPI_MESSAGE_METRIC))
api.metric = stream_getl(s);
else
api.metric = 0;
if (CHECK_FLAG(api.message, ZAPI_MESSAGE_TAG))
api.tag = stream_getl(s);
else
api.tag = 0;
if (IS_OSPF6_DEBUG_ZEBRA(RECV)) { if (IS_OSPF6_DEBUG_ZEBRA(RECV)) {
char prefixstr[PREFIX2STR_BUFFER], nexthopstr[128]; char prefixstr[PREFIX2STR_BUFFER], nexthopstr[128];
prefix2str((struct prefix *)&p, prefixstr, sizeof(prefixstr)); prefix2str((struct prefix *)&api.prefix, prefixstr,
sizeof(prefixstr));
if (nexthop) if (nexthop)
inet_ntop(AF_INET6, nexthop, nexthopstr, inet_ntop(AF_INET6, nexthop, nexthopstr,
sizeof(nexthopstr)); sizeof(nexthopstr));
@ -284,20 +239,17 @@ static int ospf6_zebra_read_ipv6(int command, struct zclient *zclient,
zlog_debug( zlog_debug(
"Zebra Receive route %s: %s %s nexthop %s ifindex %ld tag %" ROUTE_TAG_PRI, "Zebra Receive route %s: %s %s nexthop %s ifindex %ld tag %" ROUTE_TAG_PRI,
(command == ZEBRA_REDISTRIBUTE_IPV6_ADD ? "add" (command == ZEBRA_REDISTRIBUTE_ROUTE_ADD ? "add"
: "delete"), : "delete"),
zebra_route_string(api.type), prefixstr, nexthopstr, zebra_route_string(api.type), prefixstr, nexthopstr,
ifindex, api.tag); ifindex, api.tag);
} }
if (command == ZEBRA_REDISTRIBUTE_IPV6_ADD) if (command == ZEBRA_REDISTRIBUTE_ROUTE_ADD)
ospf6_asbr_redistribute_add(api.type, ifindex, &p, ospf6_asbr_redistribute_add(api.type, ifindex, &api.prefix,
api.nexthop_num, nexthop, api.tag); api.nexthop_num, nexthop, api.tag);
else else
ospf6_asbr_redistribute_remove(api.type, ifindex, &p); ospf6_asbr_redistribute_remove(api.type, ifindex, &api.prefix);
if (CHECK_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP))
free(nexthop);
return 0; return 0;
} }
@ -317,7 +269,7 @@ DEFUN (show_zebra,
} }
vty_out(vty, "Zebra Infomation\n"); vty_out(vty, "Zebra Infomation\n");
vty_out(vty, " enable: %d fail: %d\n", zclient->enable, zclient->fail); vty_out(vty, " fail: %d\n", zclient->fail);
vty_out(vty, " redistribute default: %d\n", vty_out(vty, " redistribute default: %d\n",
vrf_bitmap_check(zclient->default_information, VRF_DEFAULT)); vrf_bitmap_check(zclient->default_information, VRF_DEFAULT));
vty_out(vty, " redistribute:"); vty_out(vty, " redistribute:");
@ -329,38 +281,15 @@ DEFUN (show_zebra,
return CMD_SUCCESS; return CMD_SUCCESS;
} }
/* Zebra configuration write function. */
static int config_write_ospf6_zebra(struct vty *vty)
{
if (!zclient->enable) {
vty_out(vty, "no router zebra\n");
vty_out(vty, "!\n");
} else if (!vrf_bitmap_check(
zclient->redist[AFI_IP6][ZEBRA_ROUTE_OSPF6],
VRF_DEFAULT)) {
vty_out(vty, "router zebra\n");
vty_out(vty, " no redistribute ospf6\n");
vty_out(vty, "!\n");
}
return 0;
}
/* Zebra node structure. */
static struct cmd_node zebra_node = {
ZEBRA_NODE, "%s(config-zebra)# ",
};
#define ADD 0 #define ADD 0
#define REM 1 #define REM 1
static void ospf6_zebra_route_update(int type, struct ospf6_route *request) static void ospf6_zebra_route_update(int type, struct ospf6_route *request)
{ {
struct zapi_ipv6 api; struct zapi_route api;
char buf[PREFIX2STR_BUFFER]; char buf[PREFIX2STR_BUFFER];
int nhcount; int nhcount;
struct in6_addr **nexthops;
ifindex_t *ifindexes;
int ret = 0; int ret = 0;
struct prefix_ipv6 *dest; struct prefix *dest;
if (IS_OSPF6_DEBUG_ZEBRA(SEND)) { if (IS_OSPF6_DEBUG_ZEBRA(SEND)) {
prefix2str(&request->prefix, buf, sizeof(buf)); prefix2str(&request->prefix, buf, sizeof(buf));
@ -408,36 +337,16 @@ static void ospf6_zebra_route_update(int type, struct ospf6_route *request)
return; return;
} }
/* allocate memory for nexthop_list */ dest = &request->prefix;
nexthops =
XCALLOC(MTYPE_OSPF6_OTHER, nhcount * sizeof(struct in6_addr *));
if (nexthops == NULL) {
zlog_warn("Can't send route to zebra: malloc failed");
return;
}
/* allocate memory for ifindex_list */
ifindexes = XCALLOC(MTYPE_OSPF6_OTHER, nhcount * sizeof(ifindex_t));
if (ifindexes == NULL) {
zlog_warn("Can't send route to zebra: malloc failed");
XFREE(MTYPE_OSPF6_OTHER, nexthops);
return;
}
ospf6_route_zebra_copy_nexthops(request, ifindexes, nexthops, nhcount);
memset(&api, 0, sizeof(api));
api.vrf_id = VRF_DEFAULT; api.vrf_id = VRF_DEFAULT;
api.type = ZEBRA_ROUTE_OSPF6; api.type = ZEBRA_ROUTE_OSPF6;
api.instance = 0;
api.flags = 0;
api.message = 0;
api.safi = SAFI_UNICAST; api.safi = SAFI_UNICAST;
api.prefix = *dest;
SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP); SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
api.nexthop_num = nhcount; api.nexthop_num = nhcount;
api.nexthop = nexthops; ospf6_route_zebra_copy_nexthops(request, api.nexthops, nhcount);
SET_FLAG(api.message, ZAPI_MESSAGE_IFINDEX);
api.ifindex_num = nhcount;
api.ifindex = ifindexes;
SET_FLAG(api.message, ZAPI_MESSAGE_METRIC); SET_FLAG(api.message, ZAPI_MESSAGE_METRIC);
api.metric = (request->path.metric_type == 2 ? request->path.u.cost_e2 api.metric = (request->path.metric_type == 2 ? request->path.u.cost_e2
: request->path.cost); : request->path.cost);
@ -446,195 +355,99 @@ static void ospf6_zebra_route_update(int type, struct ospf6_route *request)
api.tag = request->path.tag; api.tag = request->path.tag;
} }
dest = (struct prefix_ipv6 *)&request->prefix;
SET_FLAG(api.message, ZAPI_MESSAGE_DISTANCE); SET_FLAG(api.message, ZAPI_MESSAGE_DISTANCE);
api.distance = ospf6_distance_apply(dest, request); api.distance =
ospf6_distance_apply((struct prefix_ipv6 *)dest, request);
if (type == REM) if (type == REM)
ret = zapi_ipv6_route(ZEBRA_IPV6_ROUTE_DELETE, zclient, dest, ret = zclient_route_send(ZEBRA_ROUTE_DELETE, zclient, &api);
NULL, &api);
else else
ret = zapi_ipv6_route(ZEBRA_IPV6_ROUTE_ADD, zclient, dest, NULL, ret = zclient_route_send(ZEBRA_ROUTE_ADD, zclient, &api);
&api);
if (ret < 0) if (ret < 0)
zlog_err("zapi_ipv6_route() %s failed: %s", zlog_err("zclient_route_send() %s failed: %s",
(type == REM ? "delete" : "add"), (type == REM ? "delete" : "add"),
safe_strerror(errno)); safe_strerror(errno));
XFREE(MTYPE_OSPF6_OTHER, nexthops);
XFREE(MTYPE_OSPF6_OTHER, ifindexes);
return; return;
} }
void ospf6_zebra_route_update_add(struct ospf6_route *request) void ospf6_zebra_route_update_add(struct ospf6_route *request)
{ {
if (!vrf_bitmap_check(zclient->redist[AFI_IP6][ZEBRA_ROUTE_OSPF6],
VRF_DEFAULT)) {
ospf6->route_table->hook_add = NULL;
ospf6->route_table->hook_remove = NULL;
return;
}
ospf6_zebra_route_update(ADD, request); ospf6_zebra_route_update(ADD, request);
} }
void ospf6_zebra_route_update_remove(struct ospf6_route *request) void ospf6_zebra_route_update_remove(struct ospf6_route *request)
{ {
if (!vrf_bitmap_check(zclient->redist[AFI_IP6][ZEBRA_ROUTE_OSPF6],
VRF_DEFAULT)) {
ospf6->route_table->hook_add = NULL;
ospf6->route_table->hook_remove = NULL;
return;
}
ospf6_zebra_route_update(REM, request); ospf6_zebra_route_update(REM, request);
} }
void ospf6_zebra_add_discard(struct ospf6_route *request) void ospf6_zebra_add_discard(struct ospf6_route *request)
{ {
struct zapi_ipv6 api; struct zapi_route api;
char buf[INET6_ADDRSTRLEN]; char buf[INET6_ADDRSTRLEN];
struct prefix_ipv6 *dest; struct prefix *dest = &request->prefix;
if (vrf_bitmap_check(zclient->redist[AFI_IP6][ZEBRA_ROUTE_OSPF6], if (!CHECK_FLAG(request->flag, OSPF6_ROUTE_BLACKHOLE_ADDED)) {
VRF_DEFAULT)) { memset(&api, 0, sizeof(api));
if (!CHECK_FLAG(request->flag, OSPF6_ROUTE_BLACKHOLE_ADDED)) { api.vrf_id = VRF_DEFAULT;
api.vrf_id = VRF_DEFAULT; api.type = ZEBRA_ROUTE_OSPF6;
api.type = ZEBRA_ROUTE_OSPF6; api.flags = ZEBRA_FLAG_BLACKHOLE;
api.flags = ZEBRA_FLAG_BLACKHOLE; api.safi = SAFI_UNICAST;
api.instance = 0; api.prefix = *dest;
api.message = 0;
api.safi = SAFI_UNICAST;
SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
api.nexthop_num = 0;
api.ifindex_num = 0;
dest = (struct prefix_ipv6 *)&request->prefix; zclient_route_send(ZEBRA_ROUTE_ADD, zclient, &api);
zapi_ipv6_route(ZEBRA_IPV6_ROUTE_ADD, zclient, dest, if (IS_OSPF6_DEBUG_ZEBRA(SEND))
NULL, &api); zlog_debug("Zebra: Route add discard %s/%d",
inet_ntop(AF_INET6, &dest->u.prefix6, buf,
INET6_ADDRSTRLEN),
dest->prefixlen);
if (IS_OSPF6_DEBUG_ZEBRA(SEND)) SET_FLAG(request->flag, OSPF6_ROUTE_BLACKHOLE_ADDED);
zlog_debug("Zebra: Route add discard %s/%d", } else {
inet_ntop(AF_INET6, &dest->prefix, if (IS_OSPF6_DEBUG_ZEBRA(SEND))
buf, INET6_ADDRSTRLEN), zlog_debug(
dest->prefixlen); "Zebra: Blackhole route present already %s/%d",
SET_FLAG(request->flag, OSPF6_ROUTE_BLACKHOLE_ADDED); inet_ntop(AF_INET6, &dest->u.prefix6, buf,
} else { INET6_ADDRSTRLEN),
dest = (struct prefix_ipv6 *)&request->prefix; dest->prefixlen);
if (IS_OSPF6_DEBUG_ZEBRA(SEND))
zlog_debug(
"Zebra: Blackhole route present already %s/%d",
inet_ntop(AF_INET6, &dest->prefix, buf,
INET6_ADDRSTRLEN),
dest->prefixlen);
}
} }
} }
void ospf6_zebra_delete_discard(struct ospf6_route *request) void ospf6_zebra_delete_discard(struct ospf6_route *request)
{ {
struct zapi_ipv6 api; struct zapi_route api;
char buf[INET6_ADDRSTRLEN]; char buf[INET6_ADDRSTRLEN];
struct prefix_ipv6 *dest; struct prefix *dest = &request->prefix;
if (vrf_bitmap_check(zclient->redist[AFI_IP6][ZEBRA_ROUTE_OSPF6], if (CHECK_FLAG(request->flag, OSPF6_ROUTE_BLACKHOLE_ADDED)) {
VRF_DEFAULT)) { memset(&api, 0, sizeof(api));
if (CHECK_FLAG(request->flag, OSPF6_ROUTE_BLACKHOLE_ADDED)) { api.vrf_id = VRF_DEFAULT;
api.vrf_id = VRF_DEFAULT; api.type = ZEBRA_ROUTE_OSPF6;
api.type = ZEBRA_ROUTE_OSPF6; api.flags = ZEBRA_FLAG_BLACKHOLE;
api.flags = ZEBRA_FLAG_BLACKHOLE; api.safi = SAFI_UNICAST;
api.instance = 0; api.prefix = *dest;
api.message = 0;
api.safi = SAFI_UNICAST;
SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
api.nexthop_num = 0;
api.ifindex_num = 0;
dest = (struct prefix_ipv6 *)&request->prefix; zclient_route_send(ZEBRA_ROUTE_DELETE, zclient, &api);
zapi_ipv6_route(ZEBRA_IPV6_ROUTE_DELETE, zclient, dest, if (IS_OSPF6_DEBUG_ZEBRA(SEND))
NULL, &api); zlog_debug("Zebra: Route delete discard %s/%d",
inet_ntop(AF_INET6, &dest->u.prefix6, buf,
INET6_ADDRSTRLEN),
dest->prefixlen);
if (IS_OSPF6_DEBUG_ZEBRA(SEND)) UNSET_FLAG(request->flag, OSPF6_ROUTE_BLACKHOLE_ADDED);
zlog_debug("Zebra: Route delete discard %s/%d", } else {
inet_ntop(AF_INET6, &dest->prefix, if (IS_OSPF6_DEBUG_ZEBRA(SEND))
buf, INET6_ADDRSTRLEN), zlog_debug(
dest->prefixlen); "Zebra: Blackhole route already deleted %s/%d",
UNSET_FLAG(request->flag, OSPF6_ROUTE_BLACKHOLE_ADDED); inet_ntop(AF_INET6, &dest->u.prefix6, buf,
} else { INET6_ADDRSTRLEN),
dest = (struct prefix_ipv6 *)&request->prefix; dest->prefixlen);
if (IS_OSPF6_DEBUG_ZEBRA(SEND))
zlog_debug(
"Zebra: Blackhole route already deleted %s/%d",
inet_ntop(AF_INET6, &dest->prefix, buf,
INET6_ADDRSTRLEN),
dest->prefixlen);
}
} }
} }
DEFUN (redistribute_ospf6,
redistribute_ospf6_cmd,
"redistribute ospf6",
"Redistribute control\n"
"OSPF6 route\n")
{
struct ospf6_route *route;
if (vrf_bitmap_check(zclient->redist[AFI_IP6][ZEBRA_ROUTE_OSPF6],
VRF_DEFAULT))
return CMD_SUCCESS;
vrf_bitmap_set(zclient->redist[AFI_IP6][ZEBRA_ROUTE_OSPF6],
VRF_DEFAULT);
if (ospf6 == NULL)
return CMD_SUCCESS;
/* send ospf6 route to zebra route table */
for (route = ospf6_route_head(ospf6->route_table); route;
route = ospf6_route_next(route))
ospf6_zebra_route_update_add(route);
ospf6->route_table->hook_add = ospf6_zebra_route_update_add;
ospf6->route_table->hook_remove = ospf6_zebra_route_update_remove;
return CMD_SUCCESS;
}
DEFUN (no_redistribute_ospf6,
no_redistribute_ospf6_cmd,
"no redistribute ospf6",
NO_STR
"Redistribute control\n"
"OSPF6 route\n")
{
struct ospf6_route *route;
if (!vrf_bitmap_check(zclient->redist[AFI_IP6][ZEBRA_ROUTE_OSPF6],
VRF_DEFAULT))
return CMD_SUCCESS;
vrf_bitmap_unset(zclient->redist[AFI_IP6][ZEBRA_ROUTE_OSPF6],
VRF_DEFAULT);
if (ospf6 == NULL)
return CMD_SUCCESS;
ospf6->route_table->hook_add = NULL;
ospf6->route_table->hook_remove = NULL;
/* withdraw ospf6 route from zebra route table */
for (route = ospf6_route_head(ospf6->route_table); route;
route = ospf6_route_next(route))
ospf6_zebra_route_update_remove(route);
return CMD_SUCCESS;
}
static struct ospf6_distance *ospf6_distance_new(void) static struct ospf6_distance *ospf6_distance_new(void)
{ {
return XCALLOC(MTYPE_OSPF6_DISTANCE, sizeof(struct ospf6_distance)); return XCALLOC(MTYPE_OSPF6_DISTANCE, sizeof(struct ospf6_distance));
@ -785,24 +598,11 @@ void ospf6_zebra_init(struct thread_master *master)
zclient->interface_address_add = ospf6_zebra_if_address_update_add; zclient->interface_address_add = ospf6_zebra_if_address_update_add;
zclient->interface_address_delete = zclient->interface_address_delete =
ospf6_zebra_if_address_update_delete; ospf6_zebra_if_address_update_delete;
zclient->redistribute_route_ipv4_add = NULL; zclient->redistribute_route_add = ospf6_zebra_read_route;
zclient->redistribute_route_ipv4_del = NULL; zclient->redistribute_route_del = ospf6_zebra_read_route;
zclient->redistribute_route_ipv6_add = ospf6_zebra_read_ipv6;
zclient->redistribute_route_ipv6_del = ospf6_zebra_read_ipv6;
/* redistribute connected route by default */
/* ospf6_zebra_redistribute (ZEBRA_ROUTE_CONNECT); */
/* Install zebra node. */
install_node(&zebra_node, config_write_ospf6_zebra);
/* Install command element for zebra node. */ /* Install command element for zebra node. */
install_element(VIEW_NODE, &show_ospf6_zebra_cmd); install_element(VIEW_NODE, &show_ospf6_zebra_cmd);
install_default(ZEBRA_NODE);
install_element(ZEBRA_NODE, &redistribute_ospf6_cmd);
install_element(ZEBRA_NODE, &no_redistribute_ospf6_cmd);
return;
} }
/* Debug */ /* Debug */

View File

@ -24,6 +24,7 @@
#include "linklist.h" #include "linklist.h"
#include "vty.h" #include "vty.h"
#include "command.h" #include "command.h"
#include "plist.h"
#include "ospf6_proto.h" #include "ospf6_proto.h"
#include "ospf6_network.h" #include "ospf6_network.h"
@ -1139,6 +1140,20 @@ DEFUN (show_ipv6_ospf6_linkstate_detail,
return CMD_SUCCESS; return CMD_SUCCESS;
} }
static void ospf6_plist_add(struct prefix_list *plist)
{
if (prefix_list_afi(plist) != AFI_IP6)
return;
ospf6_area_plist_update(plist, 1);
}
static void ospf6_plist_del(struct prefix_list *plist)
{
if (prefix_list_afi(plist) != AFI_IP6)
return;
ospf6_area_plist_update(plist, 0);
}
/* Install ospf related commands. */ /* Install ospf related commands. */
void ospf6_init(void) void ospf6_init(void)
{ {
@ -1154,6 +1169,9 @@ void ospf6_init(void)
ospf6_asbr_init(); ospf6_asbr_init();
ospf6_abr_init(); ospf6_abr_init();
prefix_list_add_hook(ospf6_plist_add);
prefix_list_delete_hook(ospf6_plist_del);
ospf6_bfd_init(); ospf6_bfd_init();
install_node(&debug_node, config_write_ospf6_debug); install_node(&debug_node, config_write_ospf6_debug);

View File

@ -1897,7 +1897,8 @@ DEFUN (no_ospf_area_filter_list,
DEFUN (ospf_area_authentication_message_digest, DEFUN (ospf_area_authentication_message_digest,
ospf_area_authentication_message_digest_cmd, ospf_area_authentication_message_digest_cmd,
"area <A.B.C.D|(0-4294967295)> authentication message-digest", "[no] area <A.B.C.D|(0-4294967295)> authentication message-digest",
NO_STR
"OSPF area parameters\n" "OSPF area parameters\n"
"OSPF area ID in IP address format\n" "OSPF area ID in IP address format\n"
"OSPF area ID as a decimal value\n" "OSPF area ID as a decimal value\n"
@ -1914,7 +1915,7 @@ DEFUN (ospf_area_authentication_message_digest,
area = ospf_area_get(ospf, area_id); area = ospf_area_get(ospf, area_id);
ospf_area_display_format_set(ospf, area, format); ospf_area_display_format_set(ospf, area, format);
area->auth_type = OSPF_AUTH_CRYPTOGRAPHIC; area->auth_type = strmatch(argv[0]->text, "no") ? OSPF_AUTH_NULL : OSPF_AUTH_CRYPTOGRAPHIC;
return CMD_SUCCESS; return CMD_SUCCESS;
} }
@ -6887,10 +6888,12 @@ DEFUN (no_ip_ospf_transmit_delay,
DEFUN_HIDDEN (no_ospf_transmit_delay, DEFUN_HIDDEN (no_ospf_transmit_delay,
no_ospf_transmit_delay_cmd, no_ospf_transmit_delay_cmd,
"no ospf transmit-delay", "no ospf transmit-delay [(1-65535) [A.B.C.D]]",
NO_STR NO_STR
"OSPF interface commands\n" "OSPF interface commands\n"
"Link state transmit delay\n") "Link state transmit delay\n"
"Seconds\n"
"Address of interface")
{ {
return no_ip_ospf_transmit_delay(self, vty, argc, argv); return no_ip_ospf_transmit_delay(self, vty, argc, argv);
} }

View File

@ -333,272 +333,144 @@ static int ospf_interface_link_params(int command, struct zclient *zclient,
void ospf_zebra_add(struct prefix_ipv4 *p, struct ospf_route * or) void ospf_zebra_add(struct prefix_ipv4 *p, struct ospf_route * or)
{ {
u_char message; struct zapi_route api;
struct zapi_nexthop *api_nh;
u_char distance; u_char distance;
u_int32_t flags;
int psize;
struct stream *s;
struct ospf_path *path; struct ospf_path *path;
struct listnode *node; struct listnode *node;
struct ospf *ospf = ospf_lookup(); struct ospf *ospf = ospf_lookup();
int count = 0;
if ((ospf->instance memset(&api, 0, sizeof(api));
&& redist_check_instance( api.vrf_id = VRF_DEFAULT;
&zclient->mi_redist[AFI_IP][ZEBRA_ROUTE_OSPF], api.type = ZEBRA_ROUTE_OSPF;
ospf->instance)) api.instance = ospf->instance;
|| vrf_bitmap_check(zclient->redist[AFI_IP][ZEBRA_ROUTE_OSPF], api.safi = SAFI_UNICAST;
VRF_DEFAULT)) {
message = 0;
flags = 0;
/* OSPF pass nexthop and metric */ memcpy(&api.prefix, p, sizeof(*p));
SET_FLAG(message, ZAPI_MESSAGE_NEXTHOP); SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
SET_FLAG(message, ZAPI_MESSAGE_METRIC); api.nexthop_num = or->paths->count;
/* Distance value. */ /* Metric value. */
distance = ospf_distance_apply(p, or); SET_FLAG(api.message, ZAPI_MESSAGE_METRIC);
if (distance) if (or->path_type == OSPF_PATH_TYPE1_EXTERNAL)
SET_FLAG(message, ZAPI_MESSAGE_DISTANCE); api.metric = or->cost + or->u.ext.type2_cost;
else if (or->path_type == OSPF_PATH_TYPE2_EXTERNAL)
api.metric = or->u.ext.type2_cost;
else
api.metric = or->cost;
/* Check if path type is ASE */ /* Check if path type is ASE */
if (((or->path_type == OSPF_PATH_TYPE1_EXTERNAL) if (((or->path_type == OSPF_PATH_TYPE1_EXTERNAL)
|| (or->path_type == OSPF_PATH_TYPE2_EXTERNAL)) || (or->path_type == OSPF_PATH_TYPE2_EXTERNAL))
&& (or->u.ext.tag > 0) && (or->u.ext.tag <= ROUTE_TAG_MAX)) && (or->u.ext.tag > 0) && (or->u.ext.tag <= ROUTE_TAG_MAX)) {
SET_FLAG(message, ZAPI_MESSAGE_TAG); SET_FLAG(api.message, ZAPI_MESSAGE_TAG);
api.tag = or->u.ext.tag;
/* Make packet. */
s = zclient->obuf;
stream_reset(s);
/* Put command, type, flags, message. */
zclient_create_header(s, ZEBRA_IPV4_ROUTE_ADD, VRF_DEFAULT);
stream_putc(s, ZEBRA_ROUTE_OSPF);
stream_putw(s, ospf->instance);
stream_putl(s, flags);
stream_putc(s, message);
stream_putw(s, SAFI_UNICAST);
/* Put prefix information. */
psize = PSIZE(p->prefixlen);
stream_putc(s, p->prefixlen);
stream_write(s, (u_char *)&p->prefix, psize);
/* Nexthop count. */
stream_putc(s, or->paths->count);
/* Nexthop, ifindex, distance and metric information. */
for (ALL_LIST_ELEMENTS_RO(or->paths, node, path)) {
#ifdef HAVE_NETLINK
if (path->unnumbered
|| (path->nexthop.s_addr != INADDR_ANY
&& path->ifindex != 0)) {
stream_putc(s, NEXTHOP_TYPE_IPV4_IFINDEX);
stream_put_in_addr(s, &path->nexthop);
stream_putl(s, path->ifindex);
} else if (path->nexthop.s_addr != INADDR_ANY) {
stream_putc(s, NEXTHOP_TYPE_IPV4);
stream_put_in_addr(s, &path->nexthop);
} else {
stream_putc(s, NEXTHOP_TYPE_IFINDEX);
if (path->ifindex)
stream_putl(s, path->ifindex);
else
stream_putl(s, 0);
}
#else /* HAVE_NETLINK */
if (path->nexthop.s_addr != INADDR_ANY
&& path->ifindex != 0) {
stream_putc(s, NEXTHOP_TYPE_IPV4_IFINDEX);
stream_put_in_addr(s, &path->nexthop);
stream_putl(s, path->ifindex);
} else if (path->nexthop.s_addr != INADDR_ANY) {
stream_putc(s, NEXTHOP_TYPE_IPV4);
stream_put_in_addr(s, &path->nexthop);
} else {
stream_putc(s, NEXTHOP_TYPE_IFINDEX);
if (path->ifindex)
stream_putl(s, path->ifindex);
else
stream_putl(s, 0);
}
#endif /* HAVE_NETLINK */
if (IS_DEBUG_OSPF(zebra, ZEBRA_REDISTRIBUTE)) {
char buf[2][INET_ADDRSTRLEN];
zlog_debug(
"Zebra: Route add %s/%d nexthop %s, ifindex=%d",
inet_ntop(AF_INET, &p->prefix, buf[0],
sizeof(buf[0])),
p->prefixlen,
inet_ntop(AF_INET, &path->nexthop,
buf[1], sizeof(buf[1])),
path->ifindex);
}
}
if (CHECK_FLAG(message, ZAPI_MESSAGE_DISTANCE))
stream_putc(s, distance);
if (CHECK_FLAG(message, ZAPI_MESSAGE_METRIC)) {
if (or->path_type == OSPF_PATH_TYPE1_EXTERNAL)
stream_putl(s, or->cost + or->u.ext.type2_cost);
else if (or->path_type == OSPF_PATH_TYPE2_EXTERNAL)
stream_putl(s, or->u.ext.type2_cost);
else
stream_putl(s, or->cost);
}
if (CHECK_FLAG(message, ZAPI_MESSAGE_TAG))
stream_putl(s, or->u.ext.tag);
stream_putw_at(s, 0, stream_get_endp(s));
zclient_send_message(zclient);
} }
/* Distance value. */
distance = ospf_distance_apply(p, or);
if (distance) {
SET_FLAG(api.message, ZAPI_MESSAGE_DISTANCE);
api.distance = distance;
}
/* Nexthop, ifindex, distance and metric information. */
for (ALL_LIST_ELEMENTS_RO(or->paths, node, path)) {
api_nh = &api.nexthops[count];
#ifdef HAVE_NETLINK
if (path->unnumbered || (path->nexthop.s_addr != INADDR_ANY
&& path->ifindex != 0)) {
#else /* HAVE_NETLINK */
if (path->nexthop.s_addr != INADDR_ANY && path->ifindex != 0) {
#endif /* HAVE_NETLINK */
api_nh->gate.ipv4 = path->nexthop;
api_nh->ifindex = path->ifindex;
api_nh->type = NEXTHOP_TYPE_IPV4_IFINDEX;
} else if (path->nexthop.s_addr != INADDR_ANY) {
api_nh->gate.ipv4 = path->nexthop;
api_nh->type = NEXTHOP_TYPE_IPV4;
} else {
api_nh->ifindex = path->ifindex;
api_nh->type = NEXTHOP_TYPE_IFINDEX;
}
count++;
if (IS_DEBUG_OSPF(zebra, ZEBRA_REDISTRIBUTE)) {
char buf[2][INET_ADDRSTRLEN];
zlog_debug(
"Zebra: Route add %s/%d nexthop %s, ifindex=%d",
inet_ntop(AF_INET, &p->prefix, buf[0],
sizeof(buf[0])),
p->prefixlen, inet_ntop(AF_INET, &path->nexthop,
buf[1], sizeof(buf[1])),
path->ifindex);
}
}
zclient_route_send(ZEBRA_ROUTE_ADD, zclient, &api);
} }
void ospf_zebra_delete(struct prefix_ipv4 *p, struct ospf_route * or) void ospf_zebra_delete(struct prefix_ipv4 *p, struct ospf_route * or)
{ {
u_char message; struct zapi_route api;
u_char distance;
u_int32_t flags;
int psize;
struct stream *s;
struct ospf_path *path;
struct listnode *node;
struct ospf *ospf = ospf_lookup(); struct ospf *ospf = ospf_lookup();
if ((ospf->instance memset(&api, 0, sizeof(api));
&& redist_check_instance( api.vrf_id = VRF_DEFAULT;
&zclient->mi_redist[AFI_IP][ZEBRA_ROUTE_OSPF], api.type = ZEBRA_ROUTE_OSPF;
ospf->instance)) api.instance = ospf->instance;
|| vrf_bitmap_check(zclient->redist[AFI_IP][ZEBRA_ROUTE_OSPF], api.safi = SAFI_UNICAST;
VRF_DEFAULT)) { memcpy(&api.prefix, p, sizeof(*p));
message = 0;
flags = 0;
/* Distance value. */
distance = ospf_distance_apply(p, or);
/* Make packet. */
s = zclient->obuf;
stream_reset(s);
/* Put command, type, flags, message. */ if (IS_DEBUG_OSPF(zebra, ZEBRA_REDISTRIBUTE)) {
zclient_create_header(s, ZEBRA_IPV4_ROUTE_DELETE, VRF_DEFAULT); char buf[INET_ADDRSTRLEN];
stream_putc(s, ZEBRA_ROUTE_OSPF); zlog_debug("Zebra: Route delete %s/%d",
stream_putw(s, ospf->instance); inet_ntop(AF_INET, &p->prefix, buf, sizeof(buf[0])),
stream_putl(s, flags); p->prefixlen);
stream_putc(s, message);
stream_putw(s, SAFI_UNICAST);
/* Put prefix information. */
psize = PSIZE(p->prefixlen);
stream_putc(s, p->prefixlen);
stream_write(s, (u_char *)&p->prefix, psize);
/* Nexthop count. */
stream_putc(s, or->paths->count);
/* Nexthop, ifindex, distance and metric information. */
for (ALL_LIST_ELEMENTS_RO(or->paths, node, path)) {
if (path->nexthop.s_addr != INADDR_ANY
&& path->ifindex != 0) {
stream_putc(s, NEXTHOP_TYPE_IPV4_IFINDEX);
stream_put_in_addr(s, &path->nexthop);
stream_putl(s, path->ifindex);
} else if (path->nexthop.s_addr != INADDR_ANY) {
stream_putc(s, NEXTHOP_TYPE_IPV4);
stream_put_in_addr(s, &path->nexthop);
} else {
stream_putc(s, NEXTHOP_TYPE_IFINDEX);
stream_putl(s, path->ifindex);
}
if (IS_DEBUG_OSPF(zebra, ZEBRA_REDISTRIBUTE)) {
char buf[2][INET_ADDRSTRLEN];
zlog_debug(
"Zebra: Route delete %s/%d nexthop %s",
inet_ntop(AF_INET, &p->prefix, buf[0],
sizeof(buf[0])),
p->prefixlen,
inet_ntop(AF_INET, &path->nexthop,
buf[1], sizeof(buf[1])));
}
}
if (CHECK_FLAG(message, ZAPI_MESSAGE_DISTANCE))
stream_putc(s, distance);
if (CHECK_FLAG(message, ZAPI_MESSAGE_METRIC)) {
if (or->path_type == OSPF_PATH_TYPE1_EXTERNAL)
stream_putl(s, or->cost + or->u.ext.type2_cost);
else if (or->path_type == OSPF_PATH_TYPE2_EXTERNAL)
stream_putl(s, or->u.ext.type2_cost);
else
stream_putl(s, or->cost);
}
stream_putw_at(s, 0, stream_get_endp(s));
zclient_send_message(zclient);
} }
zclient_route_send(ZEBRA_ROUTE_DELETE, zclient, &api);
} }
void ospf_zebra_add_discard(struct prefix_ipv4 *p) void ospf_zebra_add_discard(struct prefix_ipv4 *p)
{ {
struct zapi_ipv4 api; struct zapi_route api;
struct ospf *ospf = ospf_lookup(); struct ospf *ospf = ospf_lookup();
if ((ospf->instance memset(&api, 0, sizeof(api));
&& redist_check_instance( api.vrf_id = VRF_DEFAULT;
&zclient->mi_redist[AFI_IP][ZEBRA_ROUTE_OSPF], api.type = ZEBRA_ROUTE_OSPF;
ospf->instance)) api.instance = ospf->instance;
|| vrf_bitmap_check(zclient->redist[AFI_IP][ZEBRA_ROUTE_OSPF], api.flags = ZEBRA_FLAG_BLACKHOLE;
VRF_DEFAULT)) { api.safi = SAFI_UNICAST;
api.vrf_id = VRF_DEFAULT; memcpy(&api.prefix, p, sizeof(*p));
api.type = ZEBRA_ROUTE_OSPF;
api.instance = ospf->instance;
api.flags = ZEBRA_FLAG_BLACKHOLE;
api.message = 0;
api.safi = SAFI_UNICAST;
SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
api.nexthop_num = 0;
api.ifindex_num = 0;
api.tag = 0;
zapi_ipv4_route(ZEBRA_IPV4_ROUTE_ADD, zclient, p, &api); zclient_route_send(ZEBRA_ROUTE_ADD, zclient, &api);
if (IS_DEBUG_OSPF(zebra, ZEBRA_REDISTRIBUTE)) if (IS_DEBUG_OSPF(zebra, ZEBRA_REDISTRIBUTE))
zlog_debug("Zebra: Route add discard %s/%d", zlog_debug("Zebra: Route add discard %s/%d",
inet_ntoa(p->prefix), p->prefixlen); inet_ntoa(p->prefix), p->prefixlen);
}
} }
void ospf_zebra_delete_discard(struct prefix_ipv4 *p) void ospf_zebra_delete_discard(struct prefix_ipv4 *p)
{ {
struct zapi_ipv4 api; struct zapi_route api;
struct ospf *ospf = ospf_lookup(); struct ospf *ospf = ospf_lookup();
if ((ospf->instance memset(&api, 0, sizeof(api));
&& redist_check_instance( api.vrf_id = VRF_DEFAULT;
&zclient->mi_redist[AFI_IP][ZEBRA_ROUTE_OSPF], api.type = ZEBRA_ROUTE_OSPF;
ospf->instance)) api.instance = ospf->instance;
|| vrf_bitmap_check(zclient->redist[AFI_IP][ZEBRA_ROUTE_OSPF], api.flags = ZEBRA_FLAG_BLACKHOLE;
VRF_DEFAULT)) { api.safi = SAFI_UNICAST;
api.vrf_id = VRF_DEFAULT; memcpy(&api.prefix, p, sizeof(*p));
api.type = ZEBRA_ROUTE_OSPF;
api.instance = ospf->instance;
api.flags = ZEBRA_FLAG_BLACKHOLE;
api.message = 0;
api.safi = SAFI_UNICAST;
SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
api.nexthop_num = 0;
api.ifindex_num = 0;
api.tag = 0;
zapi_ipv4_route(ZEBRA_IPV4_ROUTE_DELETE, zclient, p, &api); zclient_route_send(ZEBRA_ROUTE_DELETE, zclient, &api);
if (IS_DEBUG_OSPF(zebra, ZEBRA_REDISTRIBUTE)) if (IS_DEBUG_OSPF(zebra, ZEBRA_REDISTRIBUTE))
zlog_debug("Zebra: Route delete discard %s/%d", zlog_debug("Zebra: Route delete discard %s/%d",
inet_ntoa(p->prefix), p->prefixlen); inet_ntoa(p->prefix), p->prefixlen);
}
} }
struct ospf_external *ospf_external_lookup(u_char type, u_short instance) struct ospf_external *ospf_external_lookup(u_char type, u_short instance)
@ -1001,61 +873,32 @@ void ospf_routemap_unset(struct ospf_redist *red)
} }
/* Zebra route add and delete treatment. */ /* Zebra route add and delete treatment. */
static int ospf_zebra_read_ipv4(int command, struct zclient *zclient, static int ospf_zebra_read_route(int command, struct zclient *zclient,
zebra_size_t length, vrf_id_t vrf_id) zebra_size_t length, vrf_id_t vrf_id)
{ {
struct stream *s; struct zapi_route api;
struct zapi_ipv4 api; struct prefix_ipv4 p;
unsigned long ifindex; unsigned long ifindex;
struct in_addr nexthop; struct in_addr nexthop;
struct prefix_ipv4 p;
struct external_info *ei; struct external_info *ei;
struct ospf *ospf; struct ospf *ospf;
int i; int i;
s = zclient->ibuf;
ifindex = 0;
nexthop.s_addr = 0;
/* Type, flags, message. */
api.type = stream_getc(s);
api.instance = stream_getw(s);
api.flags = stream_getl(s);
api.message = stream_getc(s);
/* IPv4 prefix. */
memset(&p, 0, sizeof(struct prefix_ipv4));
p.family = AF_INET;
p.prefixlen = MIN(IPV4_MAX_PREFIXLEN, stream_getc(s));
stream_get(&p.prefix, s, PSIZE(p.prefixlen));
if (IPV4_NET127(ntohl(p.prefix.s_addr)))
return 0;
/* Nexthop, ifindex, distance, metric. */
if (CHECK_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP)) {
api.nexthop_num = stream_getc(s);
nexthop.s_addr = stream_get_ipv4(s);
}
if (CHECK_FLAG(api.message, ZAPI_MESSAGE_IFINDEX)) {
api.ifindex_num = stream_getc(s);
/* XXX assert(api.ifindex_num == 1); */
ifindex = stream_getl(s);
}
if (CHECK_FLAG(api.message, ZAPI_MESSAGE_DISTANCE))
api.distance = stream_getc(s);
if (CHECK_FLAG(api.message, ZAPI_MESSAGE_METRIC))
api.metric = stream_getl(s);
if (CHECK_FLAG(api.message, ZAPI_MESSAGE_TAG))
api.tag = stream_getl(s);
else
api.tag = 0;
ospf = ospf_lookup(); ospf = ospf_lookup();
if (ospf == NULL) if (ospf == NULL)
return 0; return 0;
if (command == ZEBRA_REDISTRIBUTE_IPV4_ADD) { if (zapi_route_decode(zclient->ibuf, &api) < 0)
return -1;
ifindex = api.nexthops[0].ifindex;
nexthop = api.nexthops[0].gate.ipv4;
memcpy(&p, &api.prefix, sizeof(p));
if (IPV4_NET127(ntohl(p.prefix.s_addr)))
return 0;
if (command == ZEBRA_REDISTRIBUTE_ROUTE_ADD) {
/* XXX|HACK|TODO|FIXME: /* XXX|HACK|TODO|FIXME:
* Maybe we should ignore reject/blackhole routes? Testing shows * Maybe we should ignore reject/blackhole routes? Testing shows
* that * that
@ -1070,7 +913,7 @@ static int ospf_zebra_read_ipv4(int command, struct zclient *zclient,
* return 0; * return 0;
*/ */
/* Protocol tag overwrites all other tag value send by zebra */ /* Protocol tag overwrites all other tag value sent by zebra */
if (ospf->dtag[api.type] > 0) if (ospf->dtag[api.type] > 0)
api.tag = ospf->dtag[api.type]; api.tag = ospf->dtag[api.type];
@ -1112,7 +955,7 @@ static int ospf_zebra_read_ipv4(int command, struct zclient *zclient,
zebra, zebra,
ZEBRA_REDISTRIBUTE)) ZEBRA_REDISTRIBUTE))
zlog_debug( zlog_debug(
"ospf_zebra_read_ipv4() : %s refreshing LSA", "ospf_zebra_read_route() : %s refreshing LSA",
inet_ntoa( inet_ntoa(
p.prefix)); p.prefix));
ospf_external_lsa_refresh( ospf_external_lsa_refresh(
@ -1122,7 +965,7 @@ static int ospf_zebra_read_ipv4(int command, struct zclient *zclient,
} }
} }
} }
} else /* if (command == ZEBRA_REDISTRIBUTE_IPV4_DEL) */ } else /* if (command == ZEBRA_REDISTRIBUTE_ROUTE_DEL) */
{ {
ospf_external_info_delete(api.type, api.instance, p); ospf_external_info_delete(api.type, api.instance, p);
if (is_prefix_default(&p)) if (is_prefix_default(&p))
@ -1538,8 +1381,8 @@ void ospf_zebra_init(struct thread_master *master, u_short instance)
zclient->interface_address_delete = ospf_interface_address_delete; zclient->interface_address_delete = ospf_interface_address_delete;
zclient->interface_link_params = ospf_interface_link_params; zclient->interface_link_params = ospf_interface_link_params;
zclient->redistribute_route_ipv4_add = ospf_zebra_read_ipv4; zclient->redistribute_route_add = ospf_zebra_read_route;
zclient->redistribute_route_ipv4_del = ospf_zebra_read_ipv4; zclient->redistribute_route_del = ospf_zebra_read_route;
access_list_add_hook(ospf_filter_update); access_list_add_hook(ospf_filter_update);
access_list_delete_hook(ospf_filter_update); access_list_delete_hook(ospf_filter_update);

View File

@ -1666,7 +1666,7 @@ static void pim_show_join_helper(struct vty *vty,
json_row); json_row);
} else { } else {
vty_out(vty, vty_out(vty,
"%-9s %-15s %-15s %-15s %-6s %8s %-6s %5s\n", "%-9s %-15s %-15s %-15s %-10s %8s %-6s %5s\n",
ch->interface->name, inet_ntoa(ifaddr), ch->interface->name, inet_ntoa(ifaddr),
ch_src_str, ch_grp_str, ch_src_str, ch_grp_str,
pim_ifchannel_ifjoin_name(ch->ifjoin_state, pim_ifchannel_ifjoin_name(ch->ifjoin_state,
@ -1690,7 +1690,7 @@ static void pim_show_join(struct pim_instance *pim, struct vty *vty, u_char uj)
json = json_object_new_object(); json = json_object_new_object();
else else
vty_out(vty, vty_out(vty,
"Interface Address Source Group State Uptime Expire Prune\n"); "Interface Address Source Group State Uptime Expire Prune\n");
for (ALL_LIST_ELEMENTS_RO(vrf_iflist(pim->vrf_id), if_node, ifp)) { for (ALL_LIST_ELEMENTS_RO(vrf_iflist(pim->vrf_id), if_node, ifp)) {
pim_ifp = ifp->info; pim_ifp = ifp->info;

View File

@ -42,6 +42,7 @@
#include "pim_oil.h" #include "pim_oil.h"
#include "pim_upstream.h" #include "pim_upstream.h"
#include "pim_ssm.h" #include "pim_ssm.h"
#include "pim_rp.h"
RB_GENERATE(pim_ifchannel_rb, pim_ifchannel, RB_GENERATE(pim_ifchannel_rb, pim_ifchannel,
pim_ifp_rb, pim_ifchannel_compare); pim_ifp_rb, pim_ifchannel_compare);
@ -348,7 +349,7 @@ const char *pim_ifchannel_ifjoin_name(enum pim_ifjoin_state ifjoin_state,
switch (ifjoin_state) { switch (ifjoin_state) {
case PIM_IFJOIN_NOINFO: case PIM_IFJOIN_NOINFO:
if (PIM_IF_FLAG_TEST_S_G_RPT(flags)) if (PIM_IF_FLAG_TEST_S_G_RPT(flags))
return "SGRpt"; return "SGRpt(NI)";
else else
return "NOINFO"; return "NOINFO";
break; break;
@ -356,16 +357,28 @@ const char *pim_ifchannel_ifjoin_name(enum pim_ifjoin_state ifjoin_state,
return "JOIN"; return "JOIN";
break; break;
case PIM_IFJOIN_PRUNE: case PIM_IFJOIN_PRUNE:
return "PRUNE"; if (PIM_IF_FLAG_TEST_S_G_RPT(flags))
return "SGRpt(P)";
else
return "PRUNE";
break; break;
case PIM_IFJOIN_PRUNE_PENDING: case PIM_IFJOIN_PRUNE_PENDING:
return "PRUNEP"; if (PIM_IF_FLAG_TEST_S_G_RPT(flags))
return "SGRpt(PP)";
else
return "PRUNEP";
break; break;
case PIM_IFJOIN_PRUNE_TMP: case PIM_IFJOIN_PRUNE_TMP:
return "PRUNET"; if (PIM_IF_FLAG_TEST_S_G_RPT(flags))
return "SGRpt(P')";
else
return "PRUNET";
break; break;
case PIM_IFJOIN_PRUNE_PENDING_TMP: case PIM_IFJOIN_PRUNE_PENDING_TMP:
return "PRUNEPT"; if (PIM_IF_FLAG_TEST_S_G_RPT(flags))
return "SGRpt(PP')";
else
return "PRUNEPT";
break; break;
} }
@ -628,33 +641,34 @@ static int on_ifjoin_prune_pending_timer(struct thread *t)
ch = THREAD_ARG(t); ch = THREAD_ARG(t);
if (ch->ifjoin_state == PIM_IFJOIN_PRUNE_PENDING) { if (ch->ifjoin_state == PIM_IFJOIN_PRUNE_PENDING) {
/* Send PruneEcho(S,G) ? */
ifp = ch->interface; ifp = ch->interface;
pim_ifp = ifp->info; pim_ifp = ifp->info;
send_prune_echo = (listcount(pim_ifp->pim_neighbor_list) > 1); if (!PIM_IF_FLAG_TEST_S_G_RPT(ch->flags)) {
/* Send PruneEcho(S,G) ? */
send_prune_echo =
(listcount(pim_ifp->pim_neighbor_list) > 1);
if (send_prune_echo) { if (send_prune_echo) {
struct pim_rpf rpf; struct pim_rpf rpf;
rpf.source_nexthop.interface = ifp; rpf.source_nexthop.interface = ifp;
rpf.rpf_addr.u.prefix4 = pim_ifp->primary_address; rpf.rpf_addr.u.prefix4 =
pim_jp_agg_single_upstream_send(&rpf, ch->upstream, 0); pim_ifp->primary_address;
} pim_jp_agg_single_upstream_send(&rpf,
/* If SGRpt flag is set on ifchannel, Trigger SGRpt ch->upstream,
message on RP path upon prune timer expiry. 0);
*/ }
if (PIM_IF_FLAG_TEST_S_G_RPT(ch->flags)) {
ifjoin_to_noinfo(ch, true);
} else {
/* If SGRpt flag is set on ifchannel, Trigger SGRpt
* message on RP path upon prune timer expiry.
*/
ch->ifjoin_state = PIM_IFJOIN_PRUNE;
if (ch->upstream) if (ch->upstream)
pim_upstream_update_join_desired(pim_ifp->pim, pim_upstream_update_join_desired(pim_ifp->pim,
ch->upstream); ch->upstream);
/* }
ch->ifjoin_state transition to NOINFO state
ch_del is set to 0 for not deleteing from here.
Holdtime expiry (ch_del set to 1) delete the entry.
*/
ifjoin_to_noinfo(ch, false);
} else
ifjoin_to_noinfo(ch, true);
/* from here ch may have been deleted */ /* from here ch may have been deleted */
} else { } else {
zlog_warn( zlog_warn(
@ -1104,7 +1118,6 @@ void pim_ifchannel_local_membership_del(struct interface *ifp,
orig = ch = pim_ifchannel_find(ifp, sg); orig = ch = pim_ifchannel_find(ifp, sg);
if (!ch) if (!ch)
return; return;
ifmembership_set(ch, PIM_IFMEMBERSHIP_NOINFO); ifmembership_set(ch, PIM_IFMEMBERSHIP_NOINFO);
if (sg->src.s_addr == INADDR_ANY) { if (sg->src.s_addr == INADDR_ANY) {
@ -1311,11 +1324,12 @@ void pim_ifchannel_scan_forward_start(struct interface *new_ifp)
* we get End of Message * we get End of Message
*/ */
void pim_ifchannel_set_star_g_join_state(struct pim_ifchannel *ch, int eom, void pim_ifchannel_set_star_g_join_state(struct pim_ifchannel *ch, int eom,
uint8_t source_flags, uint8_t join, uint8_t join)
uint8_t starg_alone)
{ {
struct pim_ifchannel *child; struct pim_ifchannel *child;
struct listnode *ch_node; struct listnode *ch_node;
struct pim_instance *pim =
((struct pim_interface *)ch->interface->info)->pim;
if (PIM_DEBUG_PIM_TRACE) if (PIM_DEBUG_PIM_TRACE)
zlog_debug( zlog_debug(
@ -1326,33 +1340,6 @@ void pim_ifchannel_set_star_g_join_state(struct pim_ifchannel *ch, int eom,
return; return;
for (ALL_LIST_ELEMENTS_RO(ch->sources, ch_node, child)) { for (ALL_LIST_ELEMENTS_RO(ch->sources, ch_node, child)) {
/* Only *,G Join received and no (SG-RPT) prune.
eom = 1, only (W,G) join_alone is true, WC and RPT are set.
Scan all S,G associated to G and if any SG-RPT
remove the SG-RPT flag.
*/
if (eom && starg_alone && (source_flags & PIM_RPT_BIT_MASK)
&& (source_flags & PIM_WILDCARD_BIT_MASK)) {
if (PIM_IF_FLAG_TEST_S_G_RPT(child->flags)) {
struct pim_upstream *up = child->upstream;
PIM_IF_FLAG_UNSET_S_G_RPT(child->flags);
if (up) {
if (PIM_DEBUG_TRACE)
zlog_debug(
"%s: SGRpt flag is cleared, add inherit oif to up %s",
__PRETTY_FUNCTION__,
up->sg_str);
pim_channel_add_oif(
up->channel_oil, ch->interface,
PIM_OIF_FLAG_PROTO_STAR);
pim_ifchannel_ifjoin_switch(
__PRETTY_FUNCTION__, child,
PIM_IFJOIN_JOIN);
}
}
}
if (!PIM_IF_FLAG_TEST_S_G_RPT(child->flags)) if (!PIM_IF_FLAG_TEST_S_G_RPT(child->flags))
continue; continue;
@ -1371,8 +1358,30 @@ void pim_ifchannel_set_star_g_join_state(struct pim_ifchannel *ch, int eom,
break; break;
case PIM_IFJOIN_PRUNE_TMP: case PIM_IFJOIN_PRUNE_TMP:
case PIM_IFJOIN_PRUNE_PENDING_TMP: case PIM_IFJOIN_PRUNE_PENDING_TMP:
if (eom) if (eom) {
struct pim_upstream *parent =
child->upstream->parent;
PIM_IF_FLAG_UNSET_S_G_RPT(child->flags);
child->ifjoin_state = PIM_IFJOIN_NOINFO; child->ifjoin_state = PIM_IFJOIN_NOINFO;
if (I_am_RP(pim, child->sg.grp)) {
pim_channel_add_oif(
child->upstream->channel_oil,
ch->interface,
PIM_OIF_FLAG_PROTO_STAR);
pim_upstream_switch(
pim, child->upstream,
PIM_UPSTREAM_JOINED);
pim_jp_agg_single_upstream_send(
&child->upstream->rpf,
child->upstream, true);
}
if (parent)
pim_jp_agg_single_upstream_send(
&parent->rpf,
parent, true);
}
break; break;
} }
} }

View File

@ -151,8 +151,7 @@ void pim_ifchannel_update_assert_tracking_desired(struct pim_ifchannel *ch);
void pim_ifchannel_scan_forward_start(struct interface *new_ifp); void pim_ifchannel_scan_forward_start(struct interface *new_ifp);
void pim_ifchannel_set_star_g_join_state(struct pim_ifchannel *ch, int eom, void pim_ifchannel_set_star_g_join_state(struct pim_ifchannel *ch, int eom,
uint8_t source_flags, uint8_t join, uint8_t join);
uint8_t starg_alone);
int pim_ifchannel_compare(const struct pim_ifchannel *ch1, int pim_ifchannel_compare(const struct pim_ifchannel *ch1,
const struct pim_ifchannel *ch2); const struct pim_ifchannel *ch2);

View File

@ -231,7 +231,6 @@ int pim_joinprune_recv(struct interface *ifp, struct pim_neighbor *neigh,
uint16_t msg_num_pruned_sources; uint16_t msg_num_pruned_sources;
int source; int source;
struct pim_ifchannel *starg_ch = NULL, *sg_ch = NULL; struct pim_ifchannel *starg_ch = NULL, *sg_ch = NULL;
uint8_t starg_alone = 0;
memset(&sg, 0, sizeof(struct prefix_sg)); memset(&sg, 0, sizeof(struct prefix_sg));
addr_offset = pim_parse_addr_group(&sg, buf, pastend - buf); addr_offset = pim_parse_addr_group(&sg, buf, pastend - buf);
@ -289,12 +288,10 @@ int pim_joinprune_recv(struct interface *ifp, struct pim_neighbor *neigh,
msg_source_flags); msg_source_flags);
if (sg.src.s_addr == INADDR_ANY) { if (sg.src.s_addr == INADDR_ANY) {
starg_alone = 1;
starg_ch = pim_ifchannel_find(ifp, &sg); starg_ch = pim_ifchannel_find(ifp, &sg);
if (starg_ch) if (starg_ch)
pim_ifchannel_set_star_g_join_state( pim_ifchannel_set_star_g_join_state(
starg_ch, 0, msg_source_flags, starg_ch, 0, 1);
1, starg_alone);
} }
} }
@ -307,7 +304,6 @@ int pim_joinprune_recv(struct interface *ifp, struct pim_neighbor *neigh,
} }
buf += addr_offset; buf += addr_offset;
starg_alone = 0;
recv_prune(ifp, neigh, msg_holdtime, recv_prune(ifp, neigh, msg_holdtime,
msg_upstream_addr.u.prefix4, &sg, msg_upstream_addr.u.prefix4, &sg,
msg_source_flags); msg_source_flags);
@ -340,8 +336,7 @@ int pim_joinprune_recv(struct interface *ifp, struct pim_neighbor *neigh,
} }
} }
if (starg_ch) if (starg_ch)
pim_ifchannel_set_star_g_join_state( pim_ifchannel_set_star_g_join_state(starg_ch, 1, 0);
starg_ch, 1, msg_source_flags, 0, starg_alone);
starg_ch = NULL; starg_ch = NULL;
} /* scan groups */ } /* scan groups */
@ -419,7 +414,7 @@ int pim_joinprune_send(struct pim_rpf *rpf, struct list *groups)
struct pim_jp_agg_group *group; struct pim_jp_agg_group *group;
struct pim_interface *pim_ifp = NULL; struct pim_interface *pim_ifp = NULL;
struct pim_jp_groups *grp = NULL; struct pim_jp_groups *grp = NULL;
struct pim_jp *msg; struct pim_jp *msg = NULL;
struct listnode *node, *nnode; struct listnode *node, *nnode;
uint8_t pim_msg[10000]; uint8_t pim_msg[10000];
uint8_t *curr_ptr = pim_msg; uint8_t *curr_ptr = pim_msg;

View File

@ -1624,8 +1624,9 @@ static void pim_upstream_sg_running(void *arg)
// No packet can have arrived here if this is the case // No packet can have arrived here if this is the case
if (!up->channel_oil->installed) { if (!up->channel_oil->installed) {
if (PIM_DEBUG_TRACE) if (PIM_DEBUG_TRACE)
zlog_debug("%s: %s is not installed in mroute", zlog_debug("%s: %s[%s] is not installed in mroute",
__PRETTY_FUNCTION__, up->sg_str); __PRETTY_FUNCTION__,
up->sg_str, pim->vrf->name);
return; return;
} }

View File

@ -36,12 +36,14 @@ class RenderHandler(object):
deref = '' deref = ''
drop_str = False drop_str = False
canfail = True
class StringHandler(RenderHandler): class StringHandler(RenderHandler):
argtype = 'const char *' argtype = 'const char *'
decl = Template('const char *$varname = NULL;') decl = Template('const char *$varname = NULL;')
code = Template('$varname = argv[_i]->arg;') code = Template('$varname = argv[_i]->arg;')
drop_str = True drop_str = True
canfail = False
class LongHandler(RenderHandler): class LongHandler(RenderHandler):
argtype = 'long' argtype = 'long'
@ -130,6 +132,10 @@ handlers = {
} }
# core template invoked for each occurence of DEFPY. # core template invoked for each occurence of DEFPY.
#
# the "#if $..." bits are there to keep this template unified into one
# common form, without requiring a more advanced template engine (e.g.
# jinja2)
templ = Template('''/* $fnname => "$cmddef" */ templ = Template('''/* $fnname => "$cmddef" */
DEFUN_CMD_FUNC_DECL($fnname) DEFUN_CMD_FUNC_DECL($fnname)
#define funcdecl_$fnname static int ${fnname}_magic(\\ #define funcdecl_$fnname static int ${fnname}_magic(\\
@ -140,20 +146,31 @@ DEFUN_CMD_FUNC_DECL($fnname)
funcdecl_$fnname; funcdecl_$fnname;
DEFUN_CMD_FUNC_TEXT($fnname) DEFUN_CMD_FUNC_TEXT($fnname)
{ {
#if $nonempty /* anything to parse? */
int _i; int _i;
#if $canfail /* anything that can fail? */
unsigned _fail = 0, _failcnt = 0; unsigned _fail = 0, _failcnt = 0;
#endif
$argdecls $argdecls
for (_i = 0; _i < argc; _i++) { for (_i = 0; _i < argc; _i++) {
if (!argv[_i]->varname) if (!argv[_i]->varname)
continue; continue;
_fail = 0;$argblocks #if $canfail /* anything that can fail? */
_fail = 0;
#endif
$argblocks
#if $canfail /* anything that can fail? */
if (_fail) if (_fail)
vty_out (vty, "%% invalid input for %s: %s\\n", vty_out (vty, "%% invalid input for %s: %s\\n",
argv[_i]->varname, argv[_i]->arg); argv[_i]->varname, argv[_i]->arg);
_failcnt += _fail; _failcnt += _fail;
#endif
} }
#if $canfail /* anything that can fail? */
if (_failcnt) if (_failcnt)
return CMD_WARNING; return CMD_WARNING;
#endif
#endif
return ${fnname}_magic(self, vty, argc, argv$arglist); return ${fnname}_magic(self, vty, argc, argv$arglist);
} }
@ -196,6 +213,7 @@ def process_file(fn, ofd, dumpfd, all_defun):
arglist = [] arglist = []
argblocks = [] argblocks = []
doc = [] doc = []
canfail = 0
def do_add(handler, varname, attr = ''): def do_add(handler, varname, attr = ''):
argdefs.append(',\\\n\t%s %s%s' % (handler.argtype, varname, attr)) argdefs.append(',\\\n\t%s %s%s' % (handler.argtype, varname, attr))
@ -213,6 +231,8 @@ def process_file(fn, ofd, dumpfd, all_defun):
if handler is None: continue if handler is None: continue
do_add(handler, varname) do_add(handler, varname)
code = handler.code.substitute({'varname': varname}).replace('\n', '\n\t\t\t') code = handler.code.substitute({'varname': varname}).replace('\n', '\n\t\t\t')
if handler.canfail:
canfail = 1
strblock = '' strblock = ''
if not handler.drop_str: if not handler.drop_str:
do_add(StringHandler(None), '%s_str' % (varname), ' __attribute__ ((unused))') do_add(StringHandler(None), '%s_str' % (varname), ' __attribute__ ((unused))')
@ -229,6 +249,8 @@ def process_file(fn, ofd, dumpfd, all_defun):
params['argdecls'] = ''.join(argdecls) params['argdecls'] = ''.join(argdecls)
params['arglist'] = ''.join(arglist) params['arglist'] = ''.join(arglist)
params['argblocks'] = ''.join(argblocks) params['argblocks'] = ''.join(argblocks)
params['canfail'] = canfail
params['nonempty'] = len(argblocks)
ofd.write(templ.substitute(params)) ofd.write(templ.substitute(params))
if __name__ == '__main__': if __name__ == '__main__':
@ -257,4 +279,4 @@ if __name__ == '__main__':
process_file(args.cfile, ofd, dumpfd, args.all_defun) process_file(args.cfile, ofd, dumpfd, args.all_defun)
if args.o is not None: if args.o is not None:
clippy.wrdiff(args.o, ofd) clippy.wrdiff(args.o, ofd, [args.cfile, os.path.realpath(__file__)])

View File

@ -16,6 +16,7 @@
# with this program; see the file COPYING; if not, write to the Free Software # 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 # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
import os, stat
import _clippy import _clippy
from _clippy import parse, Graph, GraphNode from _clippy import parse, Graph, GraphNode
@ -47,7 +48,7 @@ def dump(graph):
for i, depth in graph_iterate(graph): for i, depth in graph_iterate(graph):
print('\t%s%s %r' % (' ' * (depth * 2), i.type, i.text)) print('\t%s%s %r' % (' ' * (depth * 2), i.type, i.text))
def wrdiff(filename, buf): def wrdiff(filename, buf, reffiles = []):
'''write buffer to file if contents changed''' '''write buffer to file if contents changed'''
expl = '' expl = ''
@ -57,8 +58,16 @@ def wrdiff(filename, buf):
try: old = open(filename, 'r').read() try: old = open(filename, 'r').read()
except: pass except: pass
if old == buf: if old == buf:
for reffile in reffiles:
# ensure output timestamp is newer than inputs, for make
reftime = os.stat(reffile)[stat.ST_MTIME]
outtime = os.stat(filename)[stat.ST_MTIME]
if outtime <= reftime:
os.utime(filename, (reftime + 1, reftime + 1))
# sys.stderr.write('%s unchanged, not written\n' % (filename)) # sys.stderr.write('%s unchanged, not written\n' % (filename))
return return
with open('.new.' + filename, 'w') as out:
newname = '%s.new-%d' % (filename, os.getpid())
with open(newname, 'w') as out:
out.write(buf) out.write(buf)
os.rename('.new.' + filename, filename) os.rename(newname, filename)

View File

@ -39,155 +39,107 @@ struct zclient *zclient = NULL;
/* Send ECMP routes to zebra. */ /* Send ECMP routes to zebra. */
static void rip_zebra_ipv4_send(struct route_node *rp, u_char cmd) static void rip_zebra_ipv4_send(struct route_node *rp, u_char cmd)
{ {
static struct in_addr **nexthops = NULL;
static unsigned int nexthops_len = 0;
struct list *list = (struct list *)rp->info; struct list *list = (struct list *)rp->info;
struct zapi_ipv4 api; struct zapi_route api;
struct zapi_nexthop *api_nh;
struct listnode *listnode = NULL; struct listnode *listnode = NULL;
struct rip_info *rinfo = NULL; struct rip_info *rinfo = NULL;
int count = 0; int count = 0;
if (vrf_bitmap_check(zclient->redist[AFI_IP][ZEBRA_ROUTE_RIP], memset(&api, 0, sizeof(api));
VRF_DEFAULT)) { api.vrf_id = VRF_DEFAULT;
api.vrf_id = VRF_DEFAULT; api.type = ZEBRA_ROUTE_RIP;
api.type = ZEBRA_ROUTE_RIP; api.safi = SAFI_UNICAST;
api.instance = 0;
api.flags = 0;
api.message = 0;
api.safi = SAFI_UNICAST;
if (nexthops_len < listcount(list)) { SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
nexthops_len = listcount(list); for (ALL_LIST_ELEMENTS_RO(list, listnode, rinfo)) {
nexthops = XREALLOC(MTYPE_TMP, nexthops, api_nh = &api.nexthops[count];
nexthops_len api_nh->gate.ipv4 = rinfo->nexthop;
* sizeof(struct in_addr *)); api_nh->type = NEXTHOP_TYPE_IPV4;
} if (cmd == ZEBRA_ROUTE_ADD)
SET_FLAG(rinfo->flags, RIP_RTF_FIB);
SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP); else
for (ALL_LIST_ELEMENTS_RO(list, listnode, rinfo)) { UNSET_FLAG(rinfo->flags, RIP_RTF_FIB);
nexthops[count++] = &rinfo->nexthop; count++;
if (cmd == ZEBRA_IPV4_ROUTE_ADD)
SET_FLAG(rinfo->flags, RIP_RTF_FIB);
else
UNSET_FLAG(rinfo->flags, RIP_RTF_FIB);
}
api.nexthop = nexthops;
api.nexthop_num = count;
api.ifindex_num = 0;
rinfo = listgetdata(listhead(list));
SET_FLAG(api.message, ZAPI_MESSAGE_METRIC);
api.metric = rinfo->metric;
if (rinfo->distance
&& rinfo->distance != ZEBRA_RIP_DISTANCE_DEFAULT) {
SET_FLAG(api.message, ZAPI_MESSAGE_DISTANCE);
api.distance = rinfo->distance;
}
if (rinfo->tag) {
SET_FLAG(api.message, ZAPI_MESSAGE_TAG);
api.tag = rinfo->tag;
}
zapi_ipv4_route(cmd, zclient, (struct prefix_ipv4 *)&rp->p,
&api);
if (IS_RIP_DEBUG_ZEBRA) {
if (rip->ecmp)
zlog_debug("%s: %s/%d nexthops %d",
(cmd == ZEBRA_IPV4_ROUTE_ADD)
? "Install into zebra"
: "Delete from zebra",
inet_ntoa(rp->p.u.prefix4),
rp->p.prefixlen, count);
else
zlog_debug("%s: %s/%d",
(cmd == ZEBRA_IPV4_ROUTE_ADD)
? "Install into zebra"
: "Delete from zebra",
inet_ntoa(rp->p.u.prefix4),
rp->p.prefixlen);
}
rip_global_route_changes++;
} }
api.prefix = rp->p;
api.nexthop_num = count;
rinfo = listgetdata(listhead(list));
SET_FLAG(api.message, ZAPI_MESSAGE_METRIC);
api.metric = rinfo->metric;
if (rinfo->distance && rinfo->distance != ZEBRA_RIP_DISTANCE_DEFAULT) {
SET_FLAG(api.message, ZAPI_MESSAGE_DISTANCE);
api.distance = rinfo->distance;
}
if (rinfo->tag) {
SET_FLAG(api.message, ZAPI_MESSAGE_TAG);
api.tag = rinfo->tag;
}
zclient_route_send(cmd, zclient, &api);
if (IS_RIP_DEBUG_ZEBRA) {
if (rip->ecmp)
zlog_debug("%s: %s/%d nexthops %d",
(cmd == ZEBRA_ROUTE_ADD)
? "Install into zebra"
: "Delete from zebra",
inet_ntoa(rp->p.u.prefix4), rp->p.prefixlen,
count);
else
zlog_debug("%s: %s/%d",
(cmd == ZEBRA_ROUTE_ADD)
? "Install into zebra"
: "Delete from zebra",
inet_ntoa(rp->p.u.prefix4), rp->p.prefixlen);
}
rip_global_route_changes++;
} }
/* Add/update ECMP routes to zebra. */ /* Add/update ECMP routes to zebra. */
void rip_zebra_ipv4_add(struct route_node *rp) void rip_zebra_ipv4_add(struct route_node *rp)
{ {
rip_zebra_ipv4_send(rp, ZEBRA_IPV4_ROUTE_ADD); rip_zebra_ipv4_send(rp, ZEBRA_ROUTE_ADD);
} }
/* Delete ECMP routes from zebra. */ /* Delete ECMP routes from zebra. */
void rip_zebra_ipv4_delete(struct route_node *rp) void rip_zebra_ipv4_delete(struct route_node *rp)
{ {
rip_zebra_ipv4_send(rp, ZEBRA_IPV4_ROUTE_DELETE); rip_zebra_ipv4_send(rp, ZEBRA_ROUTE_DELETE);
} }
/* Zebra route add and delete treatment. */ /* Zebra route add and delete treatment. */
static int rip_zebra_read_ipv4(int command, struct zclient *zclient, static int rip_zebra_read_route(int command, struct zclient *zclient,
zebra_size_t length, vrf_id_t vrf_id) zebra_size_t length, vrf_id_t vrf_id)
{ {
struct stream *s; struct zapi_route api;
struct zapi_ipv4 api;
unsigned long ifindex;
struct in_addr nexthop; struct in_addr nexthop;
struct prefix_ipv4 p; unsigned long ifindex;
if (!rip) if (!rip)
return 0; return 0;
s = zclient->ibuf; if (zapi_route_decode(zclient->ibuf, &api) < 0)
ifindex = 0; return -1;
nexthop.s_addr = 0;
/* Type, flags, message. */ nexthop = api.nexthops[0].gate.ipv4;
api.type = stream_getc(s); ifindex = api.nexthops[0].ifindex;
api.instance = stream_getw(s);
api.flags = stream_getl(s);
api.message = stream_getc(s);
/* IPv4 prefix. */
memset(&p, 0, sizeof(struct prefix_ipv4));
p.family = AF_INET;
p.prefixlen = MIN(IPV4_MAX_PREFIXLEN, stream_getc(s));
stream_get(&p.prefix, s, PSIZE(p.prefixlen));
/* Nexthop, ifindex, distance, metric. */
if (CHECK_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP)) {
api.nexthop_num = stream_getc(s);
nexthop.s_addr = stream_get_ipv4(s);
}
if (CHECK_FLAG(api.message, ZAPI_MESSAGE_IFINDEX)) {
api.ifindex_num = stream_getc(s);
ifindex = stream_getl(s);
}
if (CHECK_FLAG(api.message, ZAPI_MESSAGE_DISTANCE))
api.distance = stream_getc(s);
else
api.distance = 255;
if (CHECK_FLAG(api.message, ZAPI_MESSAGE_METRIC))
api.metric = stream_getl(s);
else
api.metric = 0;
if (CHECK_FLAG(api.message, ZAPI_MESSAGE_TAG))
api.tag = stream_getl(s);
else
api.tag = 0;
/* Then fetch IPv4 prefixes. */ /* Then fetch IPv4 prefixes. */
if (command == ZEBRA_REDISTRIBUTE_IPV4_ADD) if (command == ZEBRA_REDISTRIBUTE_ROUTE_ADD)
rip_redistribute_add(api.type, RIP_ROUTE_REDISTRIBUTE, &p, rip_redistribute_add(api.type, RIP_ROUTE_REDISTRIBUTE,
ifindex, &nexthop, api.metric, (struct prefix_ipv4 *)&api.prefix, ifindex,
api.distance, api.tag); &nexthop, api.metric, api.distance,
else if (command == ZEBRA_REDISTRIBUTE_IPV4_DEL) api.tag);
rip_redistribute_delete(api.type, RIP_ROUTE_REDISTRIBUTE, &p, else if (command == ZEBRA_REDISTRIBUTE_ROUTE_DEL)
rip_redistribute_delete(api.type, RIP_ROUTE_REDISTRIBUTE,
(struct prefix_ipv4 *)&api.prefix,
ifindex); ifindex);
return 0; return 0;
@ -298,27 +250,6 @@ void rip_redistribute_clean(void)
} }
} }
DEFUN (rip_redistribute_rip,
rip_redistribute_rip_cmd,
"redistribute rip",
"Redistribute information from another routing protocol\n"
"Routing Information Protocol (RIP)\n")
{
vrf_bitmap_set(zclient->redist[AFI_IP][ZEBRA_ROUTE_RIP], VRF_DEFAULT);
return CMD_SUCCESS;
}
DEFUN (no_rip_redistribute_rip,
no_rip_redistribute_rip_cmd,
"no redistribute rip",
NO_STR
"Redistribute information from another routing protocol\n"
"Routing Information Protocol (RIP)\n")
{
vrf_bitmap_unset(zclient->redist[AFI_IP][ZEBRA_ROUTE_RIP], VRF_DEFAULT);
return CMD_SUCCESS;
}
DEFUN (rip_redistribute_type, DEFUN (rip_redistribute_type,
rip_redistribute_type_cmd, rip_redistribute_type_cmd,
"redistribute " FRR_REDIST_STR_RIPD, "redistribute " FRR_REDIST_STR_RIPD,
@ -604,66 +535,46 @@ DEFUN (no_rip_default_information_originate,
return CMD_SUCCESS; return CMD_SUCCESS;
} }
/* RIP configuration write function. */
static int config_write_zebra(struct vty *vty)
{
if (!zclient->enable) {
vty_out(vty, "no router zebra\n");
return 1;
} else if (!vrf_bitmap_check(zclient->redist[AFI_IP][ZEBRA_ROUTE_RIP],
VRF_DEFAULT)) {
vty_out(vty, "router zebra\n");
vty_out(vty, " no redistribute rip\n");
return 1;
}
return 0;
}
int config_write_rip_redistribute(struct vty *vty, int config_mode) int config_write_rip_redistribute(struct vty *vty, int config_mode)
{ {
int i; int i;
for (i = 0; i < ZEBRA_ROUTE_MAX; i++) for (i = 0; i < ZEBRA_ROUTE_MAX; i++) {
if (i != zclient->redist_default if (i == zclient->redist_default
&& vrf_bitmap_check(zclient->redist[AFI_IP][i], || !vrf_bitmap_check(zclient->redist[AFI_IP][i],
VRF_DEFAULT)) { VRF_DEFAULT))
if (config_mode) { continue;
if (rip->route_map[i].metric_config) {
if (rip->route_map[i].name) if (!config_mode) {
vty_out(vty, vty_out(vty, " %s", zebra_route_string(i));
" redistribute %s metric %d route-map %s\n", continue;
zebra_route_string(i),
rip->route_map[i]
.metric,
rip->route_map[i].name);
else
vty_out(vty,
" redistribute %s metric %d\n",
zebra_route_string(i),
rip->route_map[i]
.metric);
} else {
if (rip->route_map[i].name)
vty_out(vty,
" redistribute %s route-map %s\n",
zebra_route_string(i),
rip->route_map[i].name);
else
vty_out(vty,
" redistribute %s\n",
zebra_route_string(i));
}
} else
vty_out(vty, " %s", zebra_route_string(i));
} }
if (rip->route_map[i].metric_config) {
if (rip->route_map[i].name)
vty_out(vty,
" redistribute %s metric %d route-map %s\n",
zebra_route_string(i),
rip->route_map[i].metric,
rip->route_map[i].name);
else
vty_out(vty, " redistribute %s metric %d\n",
zebra_route_string(i),
rip->route_map[i].metric);
} else {
if (rip->route_map[i].name)
vty_out(vty, " redistribute %s route-map %s\n",
zebra_route_string(i),
rip->route_map[i].name);
else
vty_out(vty, " redistribute %s\n",
zebra_route_string(i));
}
}
return 0; return 0;
} }
/* Zebra node structure. */
static struct cmd_node zebra_node = {
ZEBRA_NODE, "%s(config-router)# ",
};
static void rip_zebra_connected(struct zclient *zclient) static void rip_zebra_connected(struct zclient *zclient)
{ {
zclient_send_reg_requests(zclient, VRF_DEFAULT); zclient_send_reg_requests(zclient, VRF_DEFAULT);
@ -681,16 +592,8 @@ void rip_zclient_init(struct thread_master *master)
zclient->interface_address_delete = rip_interface_address_delete; zclient->interface_address_delete = rip_interface_address_delete;
zclient->interface_up = rip_interface_up; zclient->interface_up = rip_interface_up;
zclient->interface_down = rip_interface_down; zclient->interface_down = rip_interface_down;
zclient->redistribute_route_ipv4_add = rip_zebra_read_ipv4; zclient->redistribute_route_add = rip_zebra_read_route;
zclient->redistribute_route_ipv4_del = rip_zebra_read_ipv4; zclient->redistribute_route_del = rip_zebra_read_route;
/* Install zebra node. */
install_node(&zebra_node, config_write_zebra);
/* Install command elements to zebra node. */
install_default(ZEBRA_NODE);
install_element(ZEBRA_NODE, &rip_redistribute_rip_cmd);
install_element(ZEBRA_NODE, &no_rip_redistribute_rip_cmd);
/* Install command elements to rip node. */ /* Install command elements to rip node. */
install_element(RIP_NODE, &rip_redistribute_type_cmd); install_element(RIP_NODE, &rip_redistribute_type_cmd);

View File

@ -39,162 +39,101 @@ struct zclient *zclient = NULL;
/* Send ECMP routes to zebra. */ /* Send ECMP routes to zebra. */
static void ripng_zebra_ipv6_send(struct route_node *rp, u_char cmd) static void ripng_zebra_ipv6_send(struct route_node *rp, u_char cmd)
{ {
static struct in6_addr **nexthops = NULL;
static ifindex_t *ifindexes = NULL;
static unsigned int nexthops_len = 0;
struct list *list = (struct list *)rp->info; struct list *list = (struct list *)rp->info;
struct zapi_ipv6 api; struct zapi_route api;
struct zapi_nexthop *api_nh;
struct listnode *listnode = NULL; struct listnode *listnode = NULL;
struct ripng_info *rinfo = NULL; struct ripng_info *rinfo = NULL;
int count = 0; int count = 0;
if (vrf_bitmap_check(zclient->redist[AFI_IP6][ZEBRA_ROUTE_RIPNG], memset(&api, 0, sizeof(api));
VRF_DEFAULT)) { api.vrf_id = VRF_DEFAULT;
api.vrf_id = VRF_DEFAULT; api.type = ZEBRA_ROUTE_RIPNG;
api.type = ZEBRA_ROUTE_RIPNG; api.safi = SAFI_UNICAST;
api.instance = 0; api.prefix = rp->p;
api.flags = 0;
api.message = 0;
api.safi = SAFI_UNICAST;
if (nexthops_len < listcount(list)) { SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
nexthops_len = listcount(list); for (ALL_LIST_ELEMENTS_RO(list, listnode, rinfo)) {
nexthops = XREALLOC( api_nh = &api.nexthops[count];
MTYPE_TMP, nexthops, api_nh->gate.ipv6 = rinfo->nexthop;
nexthops_len * sizeof(struct in6_addr *)); api_nh->ifindex = rinfo->ifindex;
ifindexes = api_nh->type = NEXTHOP_TYPE_IPV6_IFINDEX;
XREALLOC(MTYPE_TMP, ifindexes, count++;
nexthops_len * sizeof(unsigned int)); if (cmd == ZEBRA_ROUTE_ADD)
} SET_FLAG(rinfo->flags, RIPNG_RTF_FIB);
else
UNSET_FLAG(rinfo->flags, RIPNG_RTF_FIB);
}
SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP); api.nexthop_num = count;
SET_FLAG(api.message, ZAPI_MESSAGE_IFINDEX);
for (ALL_LIST_ELEMENTS_RO(list, listnode, rinfo)) {
nexthops[count] = &rinfo->nexthop;
ifindexes[count] = rinfo->ifindex;
count++;
if (cmd == ZEBRA_IPV6_ROUTE_ADD)
SET_FLAG(rinfo->flags, RIPNG_RTF_FIB);
else
UNSET_FLAG(rinfo->flags, RIPNG_RTF_FIB);
}
api.nexthop = nexthops; rinfo = listgetdata(listhead(list));
api.nexthop_num = count;
api.ifindex = ifindexes;
api.ifindex_num = count;
rinfo = listgetdata(listhead(list)); SET_FLAG(api.message, ZAPI_MESSAGE_METRIC);
api.metric = rinfo->metric;
SET_FLAG(api.message, ZAPI_MESSAGE_METRIC); if (rinfo->tag) {
api.metric = rinfo->metric; SET_FLAG(api.message, ZAPI_MESSAGE_TAG);
api.tag = rinfo->tag;
}
if (rinfo->tag) { zclient_route_send(cmd, zclient, &api);
SET_FLAG(api.message, ZAPI_MESSAGE_TAG);
api.tag = rinfo->tag;
}
zapi_ipv6_route(cmd, zclient, (struct prefix_ipv6 *)&rp->p, if (IS_RIPNG_DEBUG_ZEBRA) {
NULL, &api); if (ripng->ecmp)
zlog_debug("%s: %s/%d nexthops %d",
if (IS_RIPNG_DEBUG_ZEBRA) { (cmd == ZEBRA_ROUTE_ADD)
if (ripng->ecmp) ? "Install into zebra"
zlog_debug("%s: %s/%d nexthops %d", : "Delete from zebra",
(cmd == ZEBRA_IPV6_ROUTE_ADD) inet6_ntoa(rp->p.u.prefix6), rp->p.prefixlen,
? "Install into zebra" count);
: "Delete from zebra", else
inet6_ntoa(rp->p.u.prefix6), zlog_debug(
rp->p.prefixlen, count); "%s: %s/%d",
else (cmd == ZEBRA_ROUTE_ADD) ? "Install into zebra"
zlog_debug("%s: %s/%d", : "Delete from zebra",
(cmd == ZEBRA_IPV6_ROUTE_ADD) inet6_ntoa(rp->p.u.prefix6), rp->p.prefixlen);
? "Install into zebra"
: "Delete from zebra",
inet6_ntoa(rp->p.u.prefix6),
rp->p.prefixlen);
}
} }
} }
/* Add/update ECMP routes to zebra. */ /* Add/update ECMP routes to zebra. */
void ripng_zebra_ipv6_add(struct route_node *rp) void ripng_zebra_ipv6_add(struct route_node *rp)
{ {
ripng_zebra_ipv6_send(rp, ZEBRA_IPV6_ROUTE_ADD); ripng_zebra_ipv6_send(rp, ZEBRA_ROUTE_ADD);
} }
/* Delete ECMP routes from zebra. */ /* Delete ECMP routes from zebra. */
void ripng_zebra_ipv6_delete(struct route_node *rp) void ripng_zebra_ipv6_delete(struct route_node *rp)
{ {
ripng_zebra_ipv6_send(rp, ZEBRA_IPV6_ROUTE_DELETE); ripng_zebra_ipv6_send(rp, ZEBRA_ROUTE_DELETE);
} }
/* Zebra route add and delete treatment. */ /* Zebra route add and delete treatment. */
static int ripng_zebra_read_ipv6(int command, struct zclient *zclient, static int ripng_zebra_read_route(int command, struct zclient *zclient,
zebra_size_t length, vrf_id_t vrf_id) zebra_size_t length, vrf_id_t vrf_id)
{ {
struct stream *s; struct zapi_route api;
struct zapi_ipv6 api;
unsigned long ifindex;
struct in6_addr nexthop; struct in6_addr nexthop;
struct prefix_ipv6 p, src_p; unsigned long ifindex;
s = zclient->ibuf; if (zapi_route_decode(zclient->ibuf, &api) < 0)
ifindex = 0; return -1;
memset(&nexthop, 0, sizeof(struct in6_addr));
/* Type, flags, message. */ /* we completely ignore srcdest routes for now. */
api.type = stream_getc(s); if (CHECK_FLAG(api.message, ZAPI_MESSAGE_SRCPFX))
api.instance = stream_getw(s);
api.flags = stream_getl(s);
api.message = stream_getc(s);
/* IPv6 prefix. */
memset(&p, 0, sizeof(struct prefix_ipv6));
p.family = AF_INET6;
p.prefixlen = MIN(IPV6_MAX_PREFIXLEN, stream_getc(s));
stream_get(&p.prefix, s, PSIZE(p.prefixlen));
memset(&src_p, 0, sizeof(struct prefix_ipv6));
src_p.family = AF_INET6;
if (CHECK_FLAG(api.message, ZAPI_MESSAGE_SRCPFX)) {
src_p.prefixlen = stream_getc(s);
stream_get(&src_p.prefix, s, PSIZE(src_p.prefixlen));
}
if (src_p.prefixlen)
/* we completely ignore srcdest routes for now. */
return 0; return 0;
/* Nexthop, ifindex, distance, metric. */ nexthop = api.nexthops[0].gate.ipv6;
if (CHECK_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP)) { ifindex = api.nexthops[0].ifindex;
api.nexthop_num = stream_getc(s);
stream_get(&nexthop, s, 16);
}
if (CHECK_FLAG(api.message, ZAPI_MESSAGE_IFINDEX)) {
api.ifindex_num = stream_getc(s);
ifindex = stream_getl(s);
}
if (CHECK_FLAG(api.message, ZAPI_MESSAGE_DISTANCE))
api.distance = stream_getc(s);
else
api.distance = 0;
if (CHECK_FLAG(api.message, ZAPI_MESSAGE_METRIC))
api.metric = stream_getl(s);
else
api.metric = 0;
if (CHECK_FLAG(api.message, ZAPI_MESSAGE_TAG)) if (command == ZEBRA_REDISTRIBUTE_ROUTE_ADD)
api.tag = stream_getl(s); ripng_redistribute_add(api.type, RIPNG_ROUTE_REDISTRIBUTE,
else (struct prefix_ipv6 *)&api.prefix,
api.tag = 0;
if (command == ZEBRA_REDISTRIBUTE_IPV6_ADD)
ripng_redistribute_add(api.type, RIPNG_ROUTE_REDISTRIBUTE, &p,
ifindex, &nexthop, api.tag); ifindex, &nexthop, api.tag);
else else
ripng_redistribute_delete(api.type, RIPNG_ROUTE_REDISTRIBUTE, ripng_redistribute_delete(api.type, RIPNG_ROUTE_REDISTRIBUTE,
&p, ifindex); (struct prefix_ipv6 *)&api.prefix,
ifindex);
return 0; return 0;
} }
@ -294,29 +233,6 @@ void ripng_redistribute_clean()
} }
} }
DEFUN (ripng_redistribute_ripng,
ripng_redistribute_ripng_cmd,
"redistribute ripng",
"Redistribute information from another routing protocol\n"
"RIPng route\n")
{
vrf_bitmap_set(zclient->redist[AFI_IP6][ZEBRA_ROUTE_RIPNG],
VRF_DEFAULT);
return CMD_SUCCESS;
}
DEFUN (no_ripng_redistribute_ripng,
no_ripng_redistribute_ripng_cmd,
"no redistribute ripng",
NO_STR
"Redistribute information from another routing protocol\n"
"RIPng route\n")
{
vrf_bitmap_unset(zclient->redist[AFI_IP6][ZEBRA_ROUTE_RIPNG],
VRF_DEFAULT);
return CMD_SUCCESS;
}
DEFUN (ripng_redistribute_type, DEFUN (ripng_redistribute_type,
ripng_redistribute_type_cmd, ripng_redistribute_type_cmd,
"redistribute " FRR_REDIST_STR_RIPNGD, "redistribute " FRR_REDIST_STR_RIPNGD,
@ -452,64 +368,40 @@ void ripng_redistribute_write(struct vty *vty, int config_mode)
{ {
int i; int i;
for (i = 0; i < ZEBRA_ROUTE_MAX; i++) for (i = 0; i < ZEBRA_ROUTE_MAX; i++) {
if (i != zclient->redist_default if (i == zclient->redist_default
&& vrf_bitmap_check(zclient->redist[AFI_IP6][i], || !vrf_bitmap_check(zclient->redist[AFI_IP6][i],
VRF_DEFAULT)) { VRF_DEFAULT))
if (config_mode) { continue;
if (ripng->route_map[i].metric_config) {
if (ripng->route_map[i].name) if (!config_mode) {
vty_out(vty, vty_out(vty, " %s", zebra_route_string(i));
" redistribute %s metric %d route-map %s\n", continue;
zebra_route_string(i),
ripng->route_map[i]
.metric,
ripng->route_map[i]
.name);
else
vty_out(vty,
" redistribute %s metric %d\n",
zebra_route_string(i),
ripng->route_map[i]
.metric);
} else {
if (ripng->route_map[i].name)
vty_out(vty,
" redistribute %s route-map %s\n",
zebra_route_string(i),
ripng->route_map[i]
.name);
else
vty_out(vty,
" redistribute %s\n",
zebra_route_string(i));
}
} else
vty_out(vty, " %s", zebra_route_string(i));
} }
}
/* RIPng configuration write function. */ if (ripng->route_map[i].metric_config) {
static int zebra_config_write(struct vty *vty) if (ripng->route_map[i].name)
{ vty_out(vty,
if (!zclient->enable) { " redistribute %s metric %d route-map %s\n",
vty_out(vty, "no router zebra\n"); zebra_route_string(i),
return 1; ripng->route_map[i].metric,
} else if (!vrf_bitmap_check( ripng->route_map[i].name);
zclient->redist[AFI_IP6][ZEBRA_ROUTE_RIPNG], else
VRF_DEFAULT)) { vty_out(vty, " redistribute %s metric %d\n",
vty_out(vty, "router zebra\n"); zebra_route_string(i),
vty_out(vty, " no redistribute ripng\n"); ripng->route_map[i].metric);
return 1; } else {
if (ripng->route_map[i].name)
vty_out(vty, " redistribute %s route-map %s\n",
zebra_route_string(i),
ripng->route_map[i].name);
else
vty_out(vty, " redistribute %s\n",
zebra_route_string(i));
}
} }
return 0;
} }
/* Zebra node structure. */
static struct cmd_node zebra_node = {
ZEBRA_NODE, "%s(config-router)# ",
};
static void ripng_zebra_connected(struct zclient *zclient) static void ripng_zebra_connected(struct zclient *zclient)
{ {
zclient_send_reg_requests(zclient, VRF_DEFAULT); zclient_send_reg_requests(zclient, VRF_DEFAULT);
@ -529,16 +421,8 @@ void zebra_init(struct thread_master *master)
zclient->interface_delete = ripng_interface_delete; zclient->interface_delete = ripng_interface_delete;
zclient->interface_address_add = ripng_interface_address_add; zclient->interface_address_add = ripng_interface_address_add;
zclient->interface_address_delete = ripng_interface_address_delete; zclient->interface_address_delete = ripng_interface_address_delete;
zclient->redistribute_route_ipv6_add = ripng_zebra_read_ipv6; zclient->redistribute_route_add = ripng_zebra_read_route;
zclient->redistribute_route_ipv6_del = ripng_zebra_read_ipv6; zclient->redistribute_route_del = ripng_zebra_read_route;
/* Install zebra node. */
install_node(&zebra_node, zebra_config_write);
/* Install command element for zebra node. */
install_default(ZEBRA_NODE);
install_element(ZEBRA_NODE, &ripng_redistribute_ripng_cmd);
install_element(ZEBRA_NODE, &no_ripng_redistribute_ripng_cmd);
/* Install command elements to ripng node */ /* Install command elements to ripng node */
install_element(RIPNG_NODE, &ripng_redistribute_type_cmd); install_element(RIPNG_NODE, &ripng_redistribute_type_cmd);

View File

@ -23,7 +23,7 @@ static bool atexit_registered;
static void show_meminfo_at_exit(void) static void show_meminfo_at_exit(void)
{ {
log_memstats_stderr("isis fuzztest"); log_memstats(stderr, "isis fuzztest");
} }
static int comp_line(const void *p1, const void *p2) static int comp_line(const void *p1, const void *p2)

View File

@ -53,7 +53,7 @@ static void vty_do_exit(int isexit)
thread_master_free(master); thread_master_free(master);
closezlog(); closezlog();
log_memstats_stderr("testcli"); log_memstats(stderr, "testcli");
if (!isexit) if (!isexit)
exit(0); exit(0);
} }

View File

@ -88,13 +88,10 @@ extern struct zebra_privs_t zserv_privs;
#if !defined(ROUNDUP) #if !defined(ROUNDUP)
/* /*
* It's a bug for a platform not to define rounding/alignment for * If you're porting to a platform that changed RT_ROUNDUP but doesn't
* sockaddrs on the routing socket. This warning really is * have it in its headers, this will break rather obviously and you'll
* intentional, to provoke filing bug reports with operating systems * have to fix it here.
* that don't define RT_ROUNDUP or equivalent.
*/ */
#warning \
"net/route.h does not define RT_ROUNDUP; making unwarranted assumptions!"
/* OS X (Xcode as of 2014-12) is known not to define RT_ROUNDUP */ /* OS X (Xcode as of 2014-12) is known not to define RT_ROUNDUP */
#ifdef __APPLE__ #ifdef __APPLE__

View File

@ -95,8 +95,8 @@ static void zebra_redistribute_default(struct zserv *client, vrf_id_t vrf_id)
RNODE_FOREACH_RE(rn, newre) RNODE_FOREACH_RE(rn, newre)
if (CHECK_FLAG(newre->flags, ZEBRA_FLAG_SELECTED) if (CHECK_FLAG(newre->flags, ZEBRA_FLAG_SELECTED)
&& newre->distance != DISTANCE_INFINITY) && newre->distance != DISTANCE_INFINITY)
zsend_redistribute_route(1, client, &rn->p, NULL, zsend_redistribute_route(ZEBRA_REDISTRIBUTE_ROUTE_ADD,
newre); client, &rn->p, NULL, newre);
route_unlock_node(rn); route_unlock_node(rn);
} }
@ -114,7 +114,7 @@ static void zebra_redistribute(struct zserv *client, int type, u_short instance,
if (!table) if (!table)
return; return;
for (rn = route_top(table); rn; rn = route_next(rn)) for (rn = route_top(table); rn; rn = srcdest_route_next(rn))
RNODE_FOREACH_RE(rn, newre) RNODE_FOREACH_RE(rn, newre)
{ {
struct prefix *dst_p, *src_p; struct prefix *dst_p, *src_p;
@ -141,8 +141,8 @@ static void zebra_redistribute(struct zserv *client, int type, u_short instance,
if (!zebra_check_addr(dst_p)) if (!zebra_check_addr(dst_p))
continue; continue;
zsend_redistribute_route(1, client, dst_p, src_p, zsend_redistribute_route(ZEBRA_REDISTRIBUTE_ROUTE_ADD,
newre); client, dst_p, src_p, newre);
} }
} }
@ -191,7 +191,8 @@ void redistribute_update(struct prefix *p, struct prefix *src_p,
send_redistribute = 1; send_redistribute = 1;
if (send_redistribute) { if (send_redistribute) {
zsend_redistribute_route(1, client, p, src_p, re); zsend_redistribute_route(ZEBRA_REDISTRIBUTE_ROUTE_ADD,
client, p, src_p, re);
} else if (prev_re } else if (prev_re
&& ((re->instance && ((re->instance
&& redist_check_instance( && redist_check_instance(
@ -201,7 +202,8 @@ void redistribute_update(struct prefix *p, struct prefix *src_p,
|| vrf_bitmap_check( || vrf_bitmap_check(
client->redist[afi][prev_re->type], client->redist[afi][prev_re->type],
re->vrf_id))) { re->vrf_id))) {
zsend_redistribute_route(0, client, p, src_p, prev_re); zsend_redistribute_route(ZEBRA_REDISTRIBUTE_ROUTE_DEL,
client, p, src_p, prev_re);
} }
} }
} }
@ -242,7 +244,8 @@ void redistribute_delete(struct prefix *p, struct prefix *src_p,
re->instance)) re->instance))
|| vrf_bitmap_check(client->redist[afi][re->type], || vrf_bitmap_check(client->redist[afi][re->type],
re->vrf_id)) { re->vrf_id)) {
zsend_redistribute_route(0, client, p, src_p, re); zsend_redistribute_route(ZEBRA_REDISTRIBUTE_ROUTE_DEL,
client, p, src_p, re);
} }
} }
} }

View File

@ -71,6 +71,27 @@ static int sin_masklen(struct in_addr mask)
} }
#endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */ #endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */
#ifdef __OpenBSD__
static int kernel_rtm_add_labels(struct nexthop_label *nh_label,
struct sockaddr_mpls *smpls)
{
if (nh_label->num_labels > 1) {
zlog_warn(
"%s: can't push %u labels at "
"once (maximum is 1)",
__func__, nh_label->num_labels);
return -1;
}
memset(smpls, 0, sizeof(*smpls));
smpls->smpls_len = sizeof(*smpls);
smpls->smpls_family = AF_MPLS;
smpls->smpls_label = htonl(nh_label->label[0] << MPLS_LABEL_OFFSET);
return 0;
}
#endif
/* Interface between zebra message and rtm message. */ /* Interface between zebra message and rtm message. */
static int kernel_rtm_ipv4(int cmd, struct prefix *p, struct route_entry *re) static int kernel_rtm_ipv4(int cmd, struct prefix *p, struct route_entry *re)
@ -150,15 +171,11 @@ static int kernel_rtm_ipv4(int cmd, struct prefix *p, struct route_entry *re)
} }
#ifdef __OpenBSD__ #ifdef __OpenBSD__
if (nexthop->nh_label) { if (nexthop->nh_label
memset(&smpls, 0, sizeof(smpls)); && !kernel_rtm_add_labels(nexthop->nh_label,
smpls.smpls_len = sizeof(smpls); &smpls))
smpls.smpls_family = AF_MPLS; continue;
smpls.smpls_label = smplsp = (union sockunion *)&smpls;
htonl(nexthop->nh_label->label[0]
<< MPLS_LABEL_OFFSET);
smplsp = (union sockunion *)&smpls;
}
#endif #endif
error = rtm_write( error = rtm_write(
@ -266,6 +283,10 @@ static int kernel_rtm_ipv6(int cmd, struct prefix *p, struct route_entry *re)
{ {
struct sockaddr_in6 *mask; struct sockaddr_in6 *mask;
struct sockaddr_in6 sin_dest, sin_mask, sin_gate; struct sockaddr_in6 sin_dest, sin_mask, sin_gate;
#ifdef __OpenBSD__
struct sockaddr_mpls smpls;
#endif
union sockunion *smplsp = NULL;
struct nexthop *nexthop; struct nexthop *nexthop;
int nexthop_num = 0; int nexthop_num = 0;
ifindex_t ifindex = 0; ifindex_t ifindex = 0;
@ -338,10 +359,17 @@ static int kernel_rtm_ipv6(int cmd, struct prefix *p, struct route_entry *re)
mask = &sin_mask; mask = &sin_mask;
} }
#ifdef __OpenBSD__
if (nexthop->nh_label
&& !kernel_rtm_add_labels(nexthop->nh_label, &smpls))
continue;
smplsp = (union sockunion *)&smpls;
#endif
error = rtm_write(cmd, (union sockunion *)&sin_dest, error = rtm_write(cmd, (union sockunion *)&sin_dest,
(union sockunion *)mask, (union sockunion *)mask,
gate ? (union sockunion *)&sin_gate : NULL, gate ? (union sockunion *)&sin_gate : NULL,
NULL, ifindex, re->flags, re->metric); smplsp, ifindex, re->flags, re->metric);
#if 0 #if 0
if (error) if (error)

View File

@ -1589,8 +1589,10 @@ static int fpm_remote_srv_write(struct vty *vty)
in.s_addr = zfpm_g->fpm_server; in.s_addr = zfpm_g->fpm_server;
if (zfpm_g->fpm_server != FPM_DEFAULT_IP if ((zfpm_g->fpm_server != FPM_DEFAULT_IP
|| zfpm_g->fpm_port != FPM_DEFAULT_PORT) && zfpm_g->fpm_server != INADDR_ANY)
|| (zfpm_g->fpm_port != FPM_DEFAULT_PORT
&& zfpm_g->fpm_port != 0))
vty_out(vty, "fpm connection ip %s port %d\n", inet_ntoa(in), vty_out(vty, "fpm connection ip %s port %d\n", inet_ntoa(in),
zfpm_g->fpm_port); zfpm_g->fpm_port);

View File

@ -1671,27 +1671,20 @@ int mpls_str2label(const char *label_str, u_int8_t *num_labels,
char *mpls_label2str(u_int8_t num_labels, mpls_label_t *labels, char *buf, char *mpls_label2str(u_int8_t num_labels, mpls_label_t *labels, char *buf,
int len, int pretty) int len, int pretty)
{ {
char *buf_ptr = buf; char label_buf[BUFSIZ];
int i;
buf[0] = '\0'; buf[0] = '\0';
for (i = 0; i < num_labels; i++) {
if (pretty) { if (i != 0)
if (num_labels == 1) { strlcat(buf, "/", len);
label2str(labels[0], buf, len); if (pretty)
} else if (num_labels == 2) { label2str(labels[i], label_buf, sizeof(label_buf));
label2str(labels[0], buf, len); else
buf_ptr += strlen(buf); snprintf(label_buf, sizeof(label_buf), "%u", labels[i]);
strlcat(buf, label_buf, len);
snprintf(buf_ptr, len, "/");
buf_ptr++;
label2str(labels[1], buf_ptr, len);
}
} else {
if (num_labels == 1)
snprintf(buf, len, "%u", labels[0]);
else if (num_labels == 2)
snprintf(buf, len, "%u/%u", labels[0], labels[1]);
} }
return buf; return buf;
} }

View File

@ -37,8 +37,6 @@
/* Definitions and macros. */ /* Definitions and macros. */
#define MPLS_MAX_LABELS 2 /* Maximum # labels that can be pushed. */
#define NHLFE_FAMILY(nhlfe) \ #define NHLFE_FAMILY(nhlfe) \
(((nhlfe)->nexthop->type == NEXTHOP_TYPE_IPV6 \ (((nhlfe)->nexthop->type == NEXTHOP_TYPE_IPV6 \
|| (nhlfe)->nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX) \ || (nhlfe)->nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX) \

View File

@ -256,6 +256,15 @@ static int kernel_lsp_cmd(int action, zebra_lsp_t *lsp)
|| (action == RTM_DELETE || (action == RTM_DELETE
&& (CHECK_FLAG(nhlfe->flags, NHLFE_FLAG_INSTALLED) && (CHECK_FLAG(nhlfe->flags, NHLFE_FLAG_INSTALLED)
&& CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB)))) { && CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB)))) {
if (nhlfe->nexthop->nh_label->num_labels > 1) {
zlog_warn(
"%s: can't push %u labels at once "
"(maximum is 1)",
__func__,
nhlfe->nexthop->nh_label->num_labels);
continue;
}
nexthop_num++; nexthop_num++;
switch (NHLFE_FAMILY(nhlfe)) { switch (NHLFE_FAMILY(nhlfe)) {

View File

@ -22,11 +22,13 @@
#ifndef __ZEBRA_STATIC_H__ #ifndef __ZEBRA_STATIC_H__
#define __ZEBRA_STATIC_H__ #define __ZEBRA_STATIC_H__
#include "zebra/zebra_mpls.h"
/* Static route label information */ /* Static route label information */
struct static_nh_label { struct static_nh_label {
u_int8_t num_labels; u_int8_t num_labels;
u_int8_t reserved[3]; u_int8_t reserved[3];
mpls_label_t label[2]; mpls_label_t label[MPLS_MAX_LABELS];
}; };
typedef enum { typedef enum {

View File

@ -1705,16 +1705,14 @@ static int static_config(struct vty *vty, afi_t afi, safi_t safi,
inet_ntop(AF_INET, inet_ntop(AF_INET,
&si->addr.ipv4, buf, &si->addr.ipv4, buf,
sizeof buf), sizeof buf),
ifindex2ifname(si->ifindex, si->ifname);
si->vrf_id));
break; break;
case STATIC_IPV6_GATEWAY_IFNAME: case STATIC_IPV6_GATEWAY_IFNAME:
vty_out(vty, " %s %s", vty_out(vty, " %s %s",
inet_ntop(AF_INET6, inet_ntop(AF_INET6,
&si->addr.ipv6, buf, &si->addr.ipv6, buf,
sizeof buf), sizeof buf),
ifindex2ifname(si->ifindex, si->ifname);
si->vrf_id));
break; break;
} }

View File

@ -592,193 +592,76 @@ int zsend_interface_update(int cmd, struct zserv *client, struct interface *ifp)
return zebra_server_send_message(client); return zebra_server_send_message(client);
} }
/* int zsend_redistribute_route(int cmd, struct zserv *client, struct prefix *p,
* This is the new function to announce and withdraw redistributed routes, used
* by Zebra. This is the old zsend_route_multipath() function. That function
* was duplicating code to send a lot of information that was essentially thrown
* away or ignored by the receiver. This is the leaner function that is not a
* duplicate of the zapi_ipv4_route_add/del.
*
* The primary difference is that this function merely sends a single NH instead
* of
* all the nexthops.
*/
int zsend_redistribute_route(int add, struct zserv *client, struct prefix *p,
struct prefix *src_p, struct route_entry *re) struct prefix *src_p, struct route_entry *re)
{ {
afi_t afi; struct zapi_route api;
int cmd; struct zapi_nexthop *api_nh;
int psize;
struct stream *s;
struct nexthop *nexthop; struct nexthop *nexthop;
unsigned long nhnummark = 0, messmark = 0; int count = 0;
int nhnum = 0;
u_char zapi_flags = 0;
struct nexthop dummy_nh;
afi = family2afi(p->family); memset(&api, 0, sizeof(api));
if (add) { api.vrf_id = VRF_DEFAULT;
switch (afi) { api.type = re->type;
case AFI_IP: api.instance = re->instance;
cmd = ZEBRA_REDISTRIBUTE_IPV4_ADD; api.flags = re->flags;
client->redist_v4_add_cnt++;
break;
case AFI_IP6:
cmd = ZEBRA_REDISTRIBUTE_IPV6_ADD;
client->redist_v6_add_cnt++;
break;
default:
return -1;
}
} else {
switch (afi) {
case AFI_IP:
cmd = ZEBRA_REDISTRIBUTE_IPV4_DEL;
client->redist_v4_del_cnt++;
break;
case AFI_IP6:
cmd = ZEBRA_REDISTRIBUTE_IPV6_DEL;
client->redist_v6_del_cnt++;
break;
default:
return -1;
}
}
s = client->obuf;
stream_reset(s);
memset(&dummy_nh, 0, sizeof(struct nexthop));
zserv_create_header(s, cmd, re->vrf_id);
/* Put type and nexthop. */
stream_putc(s, re->type);
stream_putw(s, re->instance);
stream_putl(s, re->flags);
/* marker for message flags field */
messmark = stream_get_endp(s);
stream_putc(s, 0);
/* Prefix. */ /* Prefix. */
psize = PSIZE(p->prefixlen); api.prefix = *p;
stream_putc(s, p->prefixlen);
stream_write(s, (u_char *)&p->u.prefix, psize);
if (src_p) { if (src_p) {
SET_FLAG(zapi_flags, ZAPI_MESSAGE_SRCPFX); SET_FLAG(api.message, ZAPI_MESSAGE_SRCPFX);
psize = PSIZE(src_p->prefixlen); memcpy(&api.src_prefix, src_p, sizeof(api.src_prefix));
stream_putc(s, src_p->prefixlen);
stream_write(s, (u_char *)&src_p->u.prefix, psize);
} }
/* Nexthops. */
if (re->nexthop_active_num) {
SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
api.nexthop_num = re->nexthop_active_num;
}
for (nexthop = re->nexthop; nexthop; nexthop = nexthop->next) { for (nexthop = re->nexthop; nexthop; nexthop = nexthop->next) {
/* We don't send any nexthops when there's a multipath */ if (!CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE))
if (re->nexthop_active_num > 1 continue;
&& client->proto != ZEBRA_ROUTE_LDP) {
SET_FLAG(zapi_flags, ZAPI_MESSAGE_NEXTHOP);
SET_FLAG(zapi_flags, ZAPI_MESSAGE_IFINDEX);
stream_putc(s, 1); api_nh = &api.nexthops[count];
if (p->family == AF_INET) { api_nh->type = nexthop->type;
stream_put_in_addr(s, &dummy_nh.gate.ipv4); switch (nexthop->type) {
} else if (p->family == AF_INET6) { case NEXTHOP_TYPE_BLACKHOLE:
stream_write(s, (u_char *)&dummy_nh.gate.ipv6,
16);
} else {
/* We don't handle anything else now, abort */
zlog_err(
"%s: Unable to redistribute route of unknown family, %d\n",
__func__, p->family);
return -1;
}
stream_putc(s, 1);
stream_putl(s, 0); /* dummy ifindex */
break; break;
case NEXTHOP_TYPE_IPV4:
api_nh->gate.ipv4 = nexthop->gate.ipv4;
break;
case NEXTHOP_TYPE_IPV4_IFINDEX:
api_nh->gate.ipv4 = nexthop->gate.ipv4;
api_nh->ifindex = nexthop->ifindex;
break;
case NEXTHOP_TYPE_IFINDEX:
api_nh->ifindex = nexthop->ifindex;
break;
case NEXTHOP_TYPE_IPV6:
api_nh->gate.ipv6 = nexthop->gate.ipv6;
break;
case NEXTHOP_TYPE_IPV6_IFINDEX:
api_nh->gate.ipv6 = nexthop->gate.ipv6;
api_nh->ifindex = nexthop->ifindex;
} }
count++;
if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE)) {
SET_FLAG(zapi_flags, ZAPI_MESSAGE_NEXTHOP);
SET_FLAG(zapi_flags, ZAPI_MESSAGE_IFINDEX);
if (nhnummark == 0) {
nhnummark = stream_get_endp(s);
stream_putc(s, 1); /* placeholder */
}
nhnum++;
switch (nexthop->type) {
case NEXTHOP_TYPE_IPV4:
case NEXTHOP_TYPE_IPV4_IFINDEX:
stream_put_in_addr(s, &nexthop->gate.ipv4);
break;
case NEXTHOP_TYPE_IPV6:
case NEXTHOP_TYPE_IPV6_IFINDEX:
/* Only BGP supports IPv4 prefix with IPv6 NH,
* so kill this */
if (p->family == AF_INET)
stream_put_in_addr(s,
&dummy_nh.gate.ipv4);
else
stream_write(
s,
(u_char *)&nexthop->gate.ipv6,
16);
break;
default:
if (cmd == ZEBRA_REDISTRIBUTE_IPV4_ADD
|| cmd == ZEBRA_REDISTRIBUTE_IPV4_DEL) {
struct in_addr empty;
memset(&empty, 0,
sizeof(struct in_addr));
stream_write(s, (u_char *)&empty,
IPV4_MAX_BYTELEN);
} else {
struct in6_addr empty;
memset(&empty, 0,
sizeof(struct in6_addr));
stream_write(s, (u_char *)&empty,
IPV6_MAX_BYTELEN);
}
}
/* Interface index. */
stream_putc(s, 1);
stream_putl(s, nexthop->ifindex);
/* ldpd needs all nexthops */
if (client->proto != ZEBRA_ROUTE_LDP)
break;
}
} }
/* Distance */ /* Attributes. */
SET_FLAG(zapi_flags, ZAPI_MESSAGE_DISTANCE); SET_FLAG(api.message, ZAPI_MESSAGE_DISTANCE);
stream_putc(s, re->distance); api.distance = re->distance;
SET_FLAG(api.message, ZAPI_MESSAGE_METRIC);
/* Metric */ api.metric = re->metric;
SET_FLAG(zapi_flags, ZAPI_MESSAGE_METRIC);
stream_putl(s, re->metric);
/* Tag */
if (re->tag) { if (re->tag) {
SET_FLAG(zapi_flags, ZAPI_MESSAGE_TAG); SET_FLAG(api.message, ZAPI_MESSAGE_TAG);
stream_putl(s, re->tag); api.tag = re->tag;
} }
SET_FLAG(api.message, ZAPI_MESSAGE_MTU);
api.mtu = re->mtu;
/* MTU */ /* Encode route and send. */
SET_FLAG(zapi_flags, ZAPI_MESSAGE_MTU); if (zapi_route_encode(cmd, client->obuf, &api) < 0)
stream_putl(s, re->mtu); return -1;
/* write real message flags value */
stream_putc_at(s, messmark, zapi_flags);
/* Write next-hop number */
if (nhnummark)
stream_putc_at(s, nhnummark, nhnum);
/* Write packet size. */
stream_putw_at(s, 0, stream_get_endp(s));
return zebra_server_send_message(client); return zebra_server_send_message(client);
} }
@ -1157,6 +1040,145 @@ 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)
{
struct stream *s;
struct zapi_route api;
struct zapi_nexthop *api_nh;
afi_t afi;
struct prefix_ipv6 *src_p = NULL;
struct route_entry *re;
struct nexthop *nexthop = NULL;
int i, ret;
s = client->ibuf;
if (zapi_route_decode(s, &api) < 0)
return -1;
/* Allocate new route. */
re = XCALLOC(MTYPE_RE, sizeof(struct route_entry));
re->type = api.type;
re->instance = api.instance;
re->flags = api.flags;
re->uptime = time(NULL);
re->vrf_id = zvrf_id(zvrf);
re->table = zvrf->table_id;
if (CHECK_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP)) {
for (i = 0; i < api.nexthop_num; i++) {
api_nh = &api.nexthops[i];
switch (api_nh->type) {
case NEXTHOP_TYPE_IFINDEX:
route_entry_nexthop_ifindex_add(
re, api_nh->ifindex);
break;
case NEXTHOP_TYPE_IPV4:
nexthop = route_entry_nexthop_ipv4_add(
re, &api_nh->gate.ipv4, NULL);
break;
case NEXTHOP_TYPE_IPV4_IFINDEX:
nexthop = route_entry_nexthop_ipv4_ifindex_add(
re, &api_nh->gate.ipv4, NULL,
api_nh->ifindex);
break;
case NEXTHOP_TYPE_IPV6:
nexthop = route_entry_nexthop_ipv6_add(
re, &api_nh->gate.ipv6);
break;
case NEXTHOP_TYPE_IPV6_IFINDEX:
nexthop = route_entry_nexthop_ipv6_ifindex_add(
re, &api_nh->gate.ipv6,
api_nh->ifindex);
break;
case NEXTHOP_TYPE_BLACKHOLE:
route_entry_nexthop_blackhole_add(re);
break;
}
/* MPLS labels for BGP-LU or Segment Routing */
if (CHECK_FLAG(api.message, ZAPI_MESSAGE_LABEL)
&& api_nh->type != NEXTHOP_TYPE_IFINDEX
&& api_nh->type != NEXTHOP_TYPE_BLACKHOLE) {
enum lsp_types_t label_type;
label_type =
lsp_type_from_re_type(client->proto);
nexthop_add_labels(nexthop, label_type,
api_nh->label_num,
&api_nh->labels[0]);
}
}
}
if (CHECK_FLAG(api.message, ZAPI_MESSAGE_DISTANCE))
re->distance = api.distance;
if (CHECK_FLAG(api.message, ZAPI_MESSAGE_METRIC))
re->metric = api.metric;
if (CHECK_FLAG(api.message, ZAPI_MESSAGE_TAG))
re->tag = api.tag;
if (CHECK_FLAG(api.message, ZAPI_MESSAGE_MTU))
re->mtu = api.mtu;
afi = family2afi(api.prefix.family);
if (CHECK_FLAG(api.message, ZAPI_MESSAGE_SRCPFX))
src_p = &api.src_prefix;
ret = rib_add_multipath(afi, api.safi, &api.prefix, src_p, re);
/* Stats */
switch (api.prefix.family) {
case AF_INET:
if (ret > 0)
client->v4_route_add_cnt++;
else if (ret < 0)
client->v4_route_upd8_cnt++;
break;
case AF_INET6:
if (ret > 0)
client->v6_route_add_cnt++;
else if (ret < 0)
client->v6_route_upd8_cnt++;
break;
}
return 0;
}
static int zread_route_del(struct zserv *client, u_short length,
struct zebra_vrf *zvrf)
{
struct stream *s;
struct zapi_route api;
afi_t afi;
struct prefix_ipv6 *src_p = NULL;
s = client->ibuf;
if (zapi_route_decode(s, &api) < 0)
return -1;
afi = family2afi(api.prefix.family);
if (CHECK_FLAG(api.message, ZAPI_MESSAGE_SRCPFX))
src_p = &api.src_prefix;
rib_delete(afi, api.safi, zvrf_id(zvrf), api.type, api.instance,
api.flags, &api.prefix, src_p, NULL, 0, zvrf->table_id,
api.metric);
/* Stats */
switch (api.prefix.family) {
case AF_INET:
client->v4_route_del_cnt++;
break;
case AF_INET6:
client->v6_route_del_cnt++;
break;
}
return 0;
}
/* This function support multiple nexthop. */ /* This function support multiple nexthop. */
/* /*
* Parse the ZEBRA_IPV4_ROUTE_ADD sent from client. Update re and * Parse the ZEBRA_IPV4_ROUTE_ADD sent from client. Update re and
@ -1176,6 +1198,7 @@ static int zread_ipv4_add(struct zserv *client, u_short length,
ifindex_t ifindex; ifindex_t ifindex;
safi_t safi; safi_t safi;
int ret; int ret;
enum lsp_types_t label_type = ZEBRA_LSP_NONE;
mpls_label_t label; mpls_label_t label;
struct nexthop *nexthop; struct nexthop *nexthop;
@ -1208,6 +1231,9 @@ static int zread_ipv4_add(struct zserv *client, u_short length,
zserv_nexthop_num_warn(__func__, (const struct prefix *)&p, zserv_nexthop_num_warn(__func__, (const struct prefix *)&p,
nexthop_num); nexthop_num);
if (CHECK_FLAG(message, ZAPI_MESSAGE_LABEL))
label_type = lsp_type_from_re_type(client->proto);
for (i = 0; i < nexthop_num; i++) { for (i = 0; i < nexthop_num; i++) {
nexthop_type = stream_getc(s); nexthop_type = stream_getc(s);
@ -1224,9 +1250,8 @@ static int zread_ipv4_add(struct zserv *client, u_short length,
* by label. */ * by label. */
if (CHECK_FLAG(message, ZAPI_MESSAGE_LABEL)) { if (CHECK_FLAG(message, ZAPI_MESSAGE_LABEL)) {
label = (mpls_label_t)stream_getl(s); label = (mpls_label_t)stream_getl(s);
nexthop_add_labels( nexthop_add_labels(nexthop, label_type,
nexthop, nexthop->nh_label_type, 1, &label);
1, &label);
} }
break; break;
case NEXTHOP_TYPE_IPV4_IFINDEX: case NEXTHOP_TYPE_IPV4_IFINDEX:
@ -1281,21 +1306,12 @@ static int zread_ipv4_add(struct zserv *client, u_short length,
static int zread_ipv4_delete(struct zserv *client, u_short length, static int zread_ipv4_delete(struct zserv *client, u_short length,
struct zebra_vrf *zvrf) struct zebra_vrf *zvrf)
{ {
int i;
struct stream *s; struct stream *s;
struct zapi_ipv4 api; struct zapi_ipv4 api;
struct in_addr nexthop;
union g_addr *nexthop_p;
unsigned long ifindex;
struct prefix p; struct prefix p;
u_char nexthop_num;
u_char nexthop_type;
u_int32_t table_id; u_int32_t table_id;
s = client->ibuf; s = client->ibuf;
ifindex = 0;
nexthop.s_addr = 0;
nexthop_p = NULL;
/* Type, flags, message. */ /* Type, flags, message. */
api.type = stream_getc(s); api.type = stream_getc(s);
@ -1310,63 +1326,10 @@ static int zread_ipv4_delete(struct zserv *client, u_short length,
p.prefixlen = stream_getc(s); p.prefixlen = stream_getc(s);
stream_get(&p.u.prefix4, s, PSIZE(p.prefixlen)); stream_get(&p.u.prefix4, s, PSIZE(p.prefixlen));
/* Nexthop, ifindex, distance, metric. */
if (CHECK_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP)) {
nexthop_num = stream_getc(s);
for (i = 0; i < nexthop_num; i++) {
nexthop_type = stream_getc(s);
switch (nexthop_type) {
case NEXTHOP_TYPE_IFINDEX:
ifindex = stream_getl(s);
break;
case NEXTHOP_TYPE_IPV4:
nexthop.s_addr = stream_get_ipv4(s);
/* For labeled-unicast, each nexthop is followed
* by label, but
* we don't care for delete.
*/
if (CHECK_FLAG(api.message, ZAPI_MESSAGE_LABEL))
stream_forward_getp(s,
sizeof(u_int32_t));
nexthop_p = (union g_addr *)&nexthop;
break;
case NEXTHOP_TYPE_IPV4_IFINDEX:
nexthop.s_addr = stream_get_ipv4(s);
nexthop_p = (union g_addr *)&nexthop;
ifindex = stream_getl(s);
break;
case NEXTHOP_TYPE_IPV6:
stream_forward_getp(s, IPV6_MAX_BYTELEN);
break;
}
}
}
/* Distance. */
if (CHECK_FLAG(api.message, ZAPI_MESSAGE_DISTANCE))
api.distance = stream_getc(s);
else
api.distance = 0;
/* Metric. */
if (CHECK_FLAG(api.message, ZAPI_MESSAGE_METRIC))
api.metric = stream_getl(s);
else
api.metric = 0;
/* tag */
if (CHECK_FLAG(api.message, ZAPI_MESSAGE_TAG))
api.tag = stream_getl(s);
else
api.tag = 0;
table_id = zvrf->table_id; table_id = zvrf->table_id;
rib_delete(AFI_IP, api.safi, zvrf_id(zvrf), api.type, api.instance, rib_delete(AFI_IP, api.safi, zvrf_id(zvrf), api.type, api.instance,
api.flags, &p, NULL, nexthop_p, ifindex, table_id, api.flags, &p, NULL, NULL, 0, table_id, 0);
api.metric);
client->v4_route_del_cnt++; client->v4_route_del_cnt++;
return 0; return 0;
} }
@ -1401,6 +1364,7 @@ static int zread_ipv4_route_ipv6_nexthop_add(struct zserv *client,
static unsigned int ifindices[MULTIPATH_NUM]; static unsigned int ifindices[MULTIPATH_NUM];
int ret; int ret;
static mpls_label_t labels[MULTIPATH_NUM]; static mpls_label_t labels[MULTIPATH_NUM];
enum lsp_types_t label_type = ZEBRA_LSP_NONE;
mpls_label_t label; mpls_label_t label;
struct nexthop *nexthop; struct nexthop *nexthop;
@ -1441,6 +1405,10 @@ static int zread_ipv4_route_ipv6_nexthop_add(struct zserv *client,
nexthop_num = stream_getc(s); nexthop_num = stream_getc(s);
zserv_nexthop_num_warn(__func__, (const struct prefix *)&p, zserv_nexthop_num_warn(__func__, (const struct prefix *)&p,
nexthop_num); nexthop_num);
if (CHECK_FLAG(message, ZAPI_MESSAGE_LABEL))
label_type = lsp_type_from_re_type(client->proto);
for (i = 0; i < nexthop_num; i++) { for (i = 0; i < nexthop_num; i++) {
nexthop_type = stream_getc(s); nexthop_type = stream_getc(s);
@ -1485,9 +1453,8 @@ static int zread_ipv4_route_ipv6_nexthop_add(struct zserv *client,
re, &nexthops[i]); re, &nexthops[i]);
if (CHECK_FLAG(message, ZAPI_MESSAGE_LABEL)) if (CHECK_FLAG(message, ZAPI_MESSAGE_LABEL))
nexthop_add_labels( nexthop_add_labels(nexthop, label_type,
nexthop, nexthop->nh_label_type, 1, &labels[i]);
1, &labels[i]);
} else { } else {
if ((i < if_count) && ifindices[i]) if ((i < if_count) && ifindices[i])
route_entry_nexthop_ifindex_add( route_entry_nexthop_ifindex_add(
@ -1534,6 +1501,7 @@ static int zread_ipv6_add(struct zserv *client, u_short length,
unsigned int i; unsigned int i;
struct stream *s; struct stream *s;
struct in6_addr nhop_addr; struct in6_addr nhop_addr;
ifindex_t ifindex;
struct route_entry *re; struct route_entry *re;
u_char message; u_char message;
u_char nexthop_num; u_char nexthop_num;
@ -1545,6 +1513,7 @@ static int zread_ipv6_add(struct zserv *client, u_short length,
static unsigned int ifindices[MULTIPATH_NUM]; static unsigned int ifindices[MULTIPATH_NUM];
int ret; int ret;
static mpls_label_t labels[MULTIPATH_NUM]; static mpls_label_t labels[MULTIPATH_NUM];
enum lsp_types_t label_type = ZEBRA_LSP_NONE;
mpls_label_t label; mpls_label_t label;
struct nexthop *nexthop; struct nexthop *nexthop;
@ -1591,6 +1560,10 @@ static int zread_ipv6_add(struct zserv *client, u_short length,
nexthop_num = stream_getc(s); nexthop_num = stream_getc(s);
zserv_nexthop_num_warn(__func__, (const struct prefix *)&p, zserv_nexthop_num_warn(__func__, (const struct prefix *)&p,
nexthop_num); nexthop_num);
if (CHECK_FLAG(message, ZAPI_MESSAGE_LABEL))
label_type = lsp_type_from_re_type(client->proto);
for (i = 0; i < nexthop_num; i++) { for (i = 0; i < nexthop_num; i++) {
nexthop_type = stream_getc(s); nexthop_type = stream_getc(s);
@ -1609,6 +1582,12 @@ static int zread_ipv6_add(struct zserv *client, u_short length,
nexthops[nh_count++] = nhop_addr; nexthops[nh_count++] = nhop_addr;
} }
break; break;
case NEXTHOP_TYPE_IPV6_IFINDEX:
stream_get(&nhop_addr, s, 16);
ifindex = stream_getl(s);
route_entry_nexthop_ipv6_ifindex_add(
re, &nhop_addr, ifindex);
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);
@ -1633,9 +1612,8 @@ static int zread_ipv6_add(struct zserv *client, u_short length,
nexthop = route_entry_nexthop_ipv6_add( nexthop = route_entry_nexthop_ipv6_add(
re, &nexthops[i]); re, &nexthops[i]);
if (CHECK_FLAG(message, ZAPI_MESSAGE_LABEL)) if (CHECK_FLAG(message, ZAPI_MESSAGE_LABEL))
nexthop_add_labels( nexthop_add_labels(nexthop, label_type,
nexthop, nexthop->nh_label_type, 1, &labels[i]);
1, &labels[i]);
} else { } else {
if ((i < if_count) && ifindices[i]) if ((i < if_count) && ifindices[i])
route_entry_nexthop_ifindex_add( route_entry_nexthop_ifindex_add(
@ -1681,18 +1659,12 @@ static int zread_ipv6_add(struct zserv *client, u_short length,
static int zread_ipv6_delete(struct zserv *client, u_short length, static int zread_ipv6_delete(struct zserv *client, u_short length,
struct zebra_vrf *zvrf) struct zebra_vrf *zvrf)
{ {
int i;
struct stream *s; struct stream *s;
struct zapi_ipv6 api; struct zapi_ipv6 api;
struct in6_addr nexthop;
union g_addr *pnexthop = NULL;
unsigned long ifindex;
struct prefix p; struct prefix p;
struct prefix_ipv6 src_p, *src_pp; struct prefix_ipv6 src_p, *src_pp;
s = client->ibuf; s = client->ibuf;
ifindex = 0;
memset(&nexthop, 0, sizeof(struct in6_addr));
/* Type, flags, message. */ /* Type, flags, message. */
api.type = stream_getc(s); api.type = stream_getc(s);
@ -1716,59 +1688,8 @@ static int zread_ipv6_delete(struct zserv *client, u_short length,
} else } else
src_pp = NULL; src_pp = NULL;
/* Nexthop, ifindex, distance, metric. */ rib_delete(AFI_IP6, api.safi, zvrf_id(zvrf), api.type, api.instance,
if (CHECK_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP)) { api.flags, &p, src_pp, NULL, 0, client->rtm_table, 0);
u_char nexthop_type;
api.nexthop_num = stream_getc(s);
for (i = 0; i < api.nexthop_num; i++) {
nexthop_type = stream_getc(s);
switch (nexthop_type) {
case NEXTHOP_TYPE_IPV6:
stream_get(&nexthop, s, 16);
/* For labeled-unicast, each nexthop is followed
* by label, but
* we don't care for delete.
*/
if (CHECK_FLAG(api.message, ZAPI_MESSAGE_LABEL))
stream_forward_getp(s,
sizeof(u_int32_t));
pnexthop = (union g_addr *)&nexthop;
break;
case NEXTHOP_TYPE_IFINDEX:
ifindex = stream_getl(s);
break;
}
}
}
/* Distance. */
if (CHECK_FLAG(api.message, ZAPI_MESSAGE_DISTANCE))
api.distance = stream_getc(s);
else
api.distance = 0;
/* Metric. */
if (CHECK_FLAG(api.message, ZAPI_MESSAGE_METRIC))
api.metric = stream_getl(s);
else
api.metric = 0;
/* tag */
if (CHECK_FLAG(api.message, ZAPI_MESSAGE_TAG))
api.tag = stream_getl(s);
else
api.tag = 0;
if (IN6_IS_ADDR_UNSPECIFIED(&nexthop))
rib_delete(AFI_IP6, api.safi, zvrf_id(zvrf), api.type,
api.instance, api.flags, &p, src_pp, NULL, ifindex,
client->rtm_table, api.metric);
else
rib_delete(AFI_IP6, api.safi, zvrf_id(zvrf), api.type,
api.instance, api.flags, &p, src_pp, pnexthop,
ifindex, client->rtm_table, api.metric);
client->v6_route_del_cnt++; client->v6_route_del_cnt++;
return 0; return 0;
@ -2435,6 +2356,12 @@ static int zebra_client_read(struct thread *thread)
case ZEBRA_INTERFACE_DELETE: case ZEBRA_INTERFACE_DELETE:
zread_interface_delete(client, length, zvrf); zread_interface_delete(client, length, zvrf);
break; 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: case ZEBRA_IPV4_ROUTE_ADD:
zread_ipv4_add(client, length, zvrf); zread_ipv4_add(client, length, zvrf);
break; break;
@ -2444,14 +2371,6 @@ static int zebra_client_read(struct thread *thread)
case ZEBRA_IPV4_ROUTE_IPV6_NEXTHOP_ADD: case ZEBRA_IPV4_ROUTE_IPV6_NEXTHOP_ADD:
zread_ipv4_route_ipv6_nexthop_add(client, length, zvrf); zread_ipv4_route_ipv6_nexthop_add(client, length, zvrf);
break; break;
case ZEBRA_IPV4_NEXTHOP_ADD:
zread_ipv4_add(client, length,
zvrf); /* LB: r1.0 merge - id was 1 */
break;
case ZEBRA_IPV4_NEXTHOP_DELETE:
zread_ipv4_delete(client, length,
zvrf); /* LB: r1.0 merge - id was 1 */
break;
case ZEBRA_IPV6_ROUTE_ADD: case ZEBRA_IPV6_ROUTE_ADD:
zread_ipv6_add(client, length, zvrf); zread_ipv6_add(client, length, zvrf);
break; break;