mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-14 14:05:31 +00:00
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:
commit
31d5efe2ea
10
Makefile.am
10
Makefile.am
@ -5,7 +5,7 @@ include common.am
|
||||
|
||||
AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/lib -I$(top_builddir) -I$(top_builddir)/lib
|
||||
AM_CFLAGS = $(WERROR)
|
||||
DEFS = @DEFS@ -DSYSCONFDIR=\"$(sysconfdir)/\"
|
||||
DEFS = @DEFS@ -DSYSCONFDIR=\"$(sysconfdir)/\" -DCONFDATE=$(CONFDATE)
|
||||
LIBCAP = @LIBCAP@
|
||||
|
||||
EXTRA_DIST =
|
||||
@ -25,6 +25,14 @@ pkginclude_HEADERS =
|
||||
nodist_pkginclude_HEADERS =
|
||||
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 zebra/subdir.am
|
||||
include qpb/subdir.am
|
||||
|
@ -37,7 +37,6 @@ void babelz_zebra_init(void);
|
||||
|
||||
/* we must use a pointer because of zclient.c's functions (new, free). */
|
||||
struct zclient *zclient;
|
||||
static int zebra_config_write (struct vty *vty);
|
||||
|
||||
/* Debug types */
|
||||
static struct {
|
||||
@ -55,118 +54,24 @@ static struct {
|
||||
{0, 0, NULL}
|
||||
};
|
||||
|
||||
/* Zebra node structure. */
|
||||
struct cmd_node zebra_node =
|
||||
{
|
||||
ZEBRA_NODE,
|
||||
"%s(config-router)# ",
|
||||
1 /* vtysh? yes */
|
||||
};
|
||||
|
||||
|
||||
/* Zebra route add and delete treatment (ipv6). */
|
||||
/* Zebra route add and delete treatment. */
|
||||
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)
|
||||
{
|
||||
struct stream *s;
|
||||
struct zapi_ipv6 api;
|
||||
unsigned long ifindex = -1;
|
||||
struct in6_addr nexthop;
|
||||
struct prefix_ipv6 prefix;
|
||||
struct zapi_route api;
|
||||
|
||||
s = zclient->ibuf;
|
||||
ifindex = 0;
|
||||
memset (&nexthop, 0, sizeof (struct in6_addr));
|
||||
memset (&api, 0, sizeof(struct zapi_ipv6));
|
||||
memset (&prefix, 0, sizeof (struct prefix_ipv6));
|
||||
|
||||
/* 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_INET6;
|
||||
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);
|
||||
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;
|
||||
}
|
||||
|
||||
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);
|
||||
if (command == ZEBRA_REDISTRIBUTE_ROUTE_ADD) {
|
||||
babel_route_add(&api);
|
||||
} else {
|
||||
babel_ipv4_route_delete(&api, &prefix, ifindex);
|
||||
babel_route_delete(&api);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -342,12 +247,9 @@ void babelz_zebra_init(void)
|
||||
zclient->interface_down = babel_interface_down;
|
||||
zclient->interface_address_add = babel_interface_address_add;
|
||||
zclient->interface_address_delete = babel_interface_address_delete;
|
||||
zclient->redistribute_route_ipv4_add = babel_zebra_read_ipv4;
|
||||
zclient->redistribute_route_ipv4_del = babel_zebra_read_ipv4;
|
||||
zclient->redistribute_route_ipv6_add = babel_zebra_read_ipv6;
|
||||
zclient->redistribute_route_ipv6_del = babel_zebra_read_ipv6;
|
||||
zclient->redistribute_route_add = babel_zebra_read_route;
|
||||
zclient->redistribute_route_del = babel_zebra_read_route;
|
||||
|
||||
install_node (&zebra_node, zebra_config_write);
|
||||
install_element(BABEL_NODE, &babel_redistribute_type_cmd);
|
||||
install_element(ENABLE_NODE, &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);
|
||||
}
|
||||
|
||||
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
|
||||
babel_zebra_close_connexion(void)
|
||||
{
|
||||
|
@ -331,8 +331,8 @@ babel_main_loop(struct thread *thread)
|
||||
/* if there is no timeout, we must wait. */
|
||||
if(timeval_compare(&tv, &babel_now) > 0) {
|
||||
timeval_minus(&tv, &tv, &babel_now);
|
||||
debugf(BABEL_DEBUG_TIMEOUT, "babel main loop : timeout: %ld msecs",
|
||||
tv.tv_sec * 1000 + tv.tv_usec / 1000);
|
||||
debugf(BABEL_DEBUG_TIMEOUT, "babel main loop : timeout: %lld msecs",
|
||||
(long long)tv.tv_sec * 1000 + tv.tv_usec / 1000);
|
||||
/* it happens often to have less than 1 ms, it's bad. */
|
||||
timeval_add_msec(&tv, &tv, 300);
|
||||
babel_set_timer(&tv);
|
||||
|
159
babeld/kernel.c
159
babeld/kernel.c
@ -51,13 +51,8 @@ THE SOFTWARE.
|
||||
|
||||
|
||||
static int
|
||||
kernel_route_v4(int add, const unsigned char *pref, unsigned short plen,
|
||||
const unsigned char *gate, int ifindex,
|
||||
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);
|
||||
zebra_route(int add, int familt, const unsigned char *pref, unsigned short plen,
|
||||
const unsigned char *gate, int ifindex, unsigned int metric);
|
||||
|
||||
int
|
||||
kernel_interface_operational(struct interface *interface)
|
||||
@ -84,7 +79,7 @@ kernel_route(int operation, const unsigned char *pref, unsigned short plen,
|
||||
unsigned int newmetric)
|
||||
{
|
||||
int rc;
|
||||
int ipv4;
|
||||
int family;
|
||||
|
||||
/* Check that the protocol family is consistent. */
|
||||
if(plen >= 96 && v4mapped(pref)) {
|
||||
@ -92,46 +87,37 @@ kernel_route(int operation, const unsigned char *pref, unsigned short plen,
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
ipv4 = 1;
|
||||
family = AF_INET;
|
||||
} else {
|
||||
if(v4mapped(gate)) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
ipv4 = 0;
|
||||
family = AF_INET6;
|
||||
}
|
||||
|
||||
switch (operation) {
|
||||
case ROUTE_ADD:
|
||||
return ipv4 ?
|
||||
kernel_route_v4(1, pref, plen, gate, ifindex, metric):
|
||||
kernel_route_v6(1, pref, plen, gate, ifindex, metric);
|
||||
return zebra_route(1, family, pref, plen, gate, ifindex, metric);
|
||||
break;
|
||||
case ROUTE_FLUSH:
|
||||
return ipv4 ?
|
||||
kernel_route_v4(0, pref, plen, gate, ifindex, metric):
|
||||
kernel_route_v6(0, pref, plen, gate, ifindex, metric);
|
||||
return zebra_route(0, family, pref, plen, gate, ifindex, metric);
|
||||
break;
|
||||
case ROUTE_MODIFY:
|
||||
if(newmetric == metric && memcmp(newgate, gate, 16) == 0 &&
|
||||
newifindex == ifindex)
|
||||
return 0;
|
||||
debugf(BABEL_DEBUG_ROUTE, "Modify route: delete old; add new.");
|
||||
rc = ipv4 ?
|
||||
kernel_route_v4(0, pref, plen, gate, ifindex, metric):
|
||||
kernel_route_v6(0, pref, plen, gate, ifindex, metric);
|
||||
|
||||
rc = zebra_route(0, family, pref, plen, gate, ifindex, metric);
|
||||
if (rc < 0)
|
||||
return -1;
|
||||
|
||||
rc = ipv4 ?
|
||||
kernel_route_v4(1, pref, plen, newgate, newifindex, newmetric):
|
||||
kernel_route_v6(1, pref, plen, newgate, newifindex, newmetric);
|
||||
|
||||
rc = zebra_route(1, family, pref, plen, newgate, newifindex,
|
||||
newmetric);
|
||||
return rc;
|
||||
break;
|
||||
default:
|
||||
zlog_err("this should never appens (false value - kernel_route)");
|
||||
zlog_err("this should never happen (false value - kernel_route)");
|
||||
assert(0);
|
||||
exit(1);
|
||||
break;
|
||||
@ -139,110 +125,81 @@ kernel_route(int operation, const unsigned char *pref, unsigned short plen,
|
||||
}
|
||||
|
||||
static int
|
||||
kernel_route_v4(int add,
|
||||
const unsigned char *pref, unsigned short plen,
|
||||
zebra_route(int add, int family, 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 in_addr babel_prefix_addr; /* babeld's prefix addr */
|
||||
struct nexthop nexthop; /* next router to go */
|
||||
struct nexthop *nexthop_pointer = &nexthop; /* it's an array! */
|
||||
union g_addr babel_prefix_addr; /* babeld's prefix addr */
|
||||
struct zapi_nexthop *api_nh; /* next router to go - no ECMP */
|
||||
|
||||
api_nh = &api.nexthops[0];
|
||||
|
||||
/* convert to be understandable by quagga */
|
||||
/* convert given addresses */
|
||||
uchar_to_inaddr(&babel_prefix_addr, pref);
|
||||
uchar_to_inaddr(&nexthop.gate.ipv4, gate);
|
||||
switch (family) {
|
||||
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 */
|
||||
memset (&quagga_prefix, 0, sizeof(quagga_prefix));
|
||||
quagga_prefix.family = AF_INET;
|
||||
IPV4_ADDR_COPY (&quagga_prefix.u.prefix4, &babel_prefix_addr);
|
||||
quagga_prefix.prefixlen = plen - 96; /* our plen is for v4mapped's addr */
|
||||
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;
|
||||
|
||||
SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
|
||||
if(metric >= KERNEL_INFINITY) {
|
||||
api.flags = ZEBRA_FLAG_REJECT;
|
||||
api.nexthop_num = 0;
|
||||
} else {
|
||||
api.nexthop_num = 1;
|
||||
api.nexthop = &nexthop_pointer;
|
||||
nexthop.ifindex = ifindex;
|
||||
if (IPV4_ADDR_SAME (&nexthop.gate.ipv4, &quagga_prefix.u.prefix4) &&
|
||||
quagga_prefix.prefixlen == 32) {
|
||||
nexthop.type = NEXTHOP_TYPE_IFINDEX;
|
||||
} else {
|
||||
nexthop.type = NEXTHOP_TYPE_IPV4_IFINDEX;
|
||||
}
|
||||
SET_FLAG(api.message, ZAPI_MESSAGE_METRIC);
|
||||
api.metric = metric;
|
||||
}
|
||||
|
||||
debugf(BABEL_DEBUG_ROUTE, "%s route (ipv4) to zebra",
|
||||
add ? "adding" : "removing" );
|
||||
return zapi_route (add ? ZEBRA_IPV4_ROUTE_ADD :
|
||||
ZEBRA_IPV4_ROUTE_DELETE,
|
||||
zclient, &quagga_prefix, NULL, &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.family = family;
|
||||
switch (family) {
|
||||
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);
|
||||
|
||||
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;
|
||||
api.prefix = quagga_prefix;
|
||||
|
||||
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;
|
||||
api_nh->ifindex = ifindex;
|
||||
|
||||
switch (family) {
|
||||
case AF_INET:
|
||||
uchar_to_inaddr(&api_nh->gate.ipv4, gate);
|
||||
if (IPV4_ADDR_SAME (&api_nh->gate.ipv4, &quagga_prefix.u.prefix4) &&
|
||||
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 */
|
||||
nexthop.type = NEXTHOP_TYPE_IPV6_IFINDEX;
|
||||
api_nh->type = NEXTHOP_TYPE_IPV6_IFINDEX;
|
||||
break;
|
||||
}
|
||||
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);
|
||||
debugf(BABEL_DEBUG_ROUTE, "%s route (%s) to zebra",
|
||||
add ? "adding" : "removing",
|
||||
(family == AF_INET) ? "ipv4" : "ipv6");
|
||||
return zclient_route_send (add ? ZEBRA_ROUTE_ADD : ZEBRA_ROUTE_DELETE,
|
||||
zclient, &api);
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -391,7 +391,7 @@ parse_packet(const unsigned char *from, struct interface *ifp,
|
||||
} else if(type == MESSAGE_HELLO) {
|
||||
unsigned short seqno, interval;
|
||||
int changed;
|
||||
unsigned int timestamp;
|
||||
unsigned int timestamp = 0;
|
||||
DO_NTOHS(seqno, message + 4);
|
||||
DO_NTOHS(interval, message + 6);
|
||||
debugf(BABEL_DEBUG_COMMON,"Received hello %d (%d) from %s on %s.",
|
||||
|
@ -43,63 +43,54 @@ static int numxroutes = 0, maxxroutes = 0;
|
||||
|
||||
/* Add redistributed route to Babel table. */
|
||||
int
|
||||
babel_ipv4_route_add (struct zapi_ipv4 *api, struct prefix_ipv4 *prefix,
|
||||
unsigned int ifindex, struct in_addr *nexthop)
|
||||
babel_route_add (struct zapi_route *api)
|
||||
{
|
||||
unsigned char uchar_prefix[16];
|
||||
|
||||
inaddr_to_uchar(uchar_prefix, &prefix->prefix);
|
||||
switch (api->prefix.family) {
|
||||
case AF_INET:
|
||||
inaddr_to_uchar(uchar_prefix, &api->prefix.u.prefix4);
|
||||
debugf(BABEL_DEBUG_ROUTE, "Adding new ipv4 route coming from Zebra.");
|
||||
xroute_add_new_route(uchar_prefix, prefix->prefixlen + 96,
|
||||
api->metric, ifindex, 0, 1);
|
||||
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;
|
||||
}
|
||||
|
||||
/* Remove redistributed route from Babel table. */
|
||||
int
|
||||
babel_ipv4_route_delete (struct zapi_ipv4 *api, struct prefix_ipv4 *prefix,
|
||||
unsigned int ifindex)
|
||||
babel_route_delete (struct zapi_route *api)
|
||||
{
|
||||
unsigned char uchar_prefix[16];
|
||||
struct xroute *xroute = NULL;
|
||||
|
||||
inaddr_to_uchar(uchar_prefix, &prefix->prefix);
|
||||
xroute = find_xroute(uchar_prefix, prefix->prefixlen + 96);
|
||||
switch (api->prefix.family) {
|
||||
case AF_INET:
|
||||
inaddr_to_uchar(uchar_prefix, &api->prefix.u.prefix4);
|
||||
xroute = find_xroute(uchar_prefix, api->prefix.prefixlen + 96);
|
||||
if (xroute != NULL) {
|
||||
debugf(BABEL_DEBUG_ROUTE, "Removing ipv4 route (from zebra).");
|
||||
flush_xroute(xroute);
|
||||
}
|
||||
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);
|
||||
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 route (from zebra).");
|
||||
debugf(BABEL_DEBUG_ROUTE, "Removing ipv6 route (from zebra).");
|
||||
flush_xroute(xroute);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -36,14 +36,8 @@ struct xroute_stream;
|
||||
|
||||
struct xroute *find_xroute(const unsigned char *prefix, unsigned char plen);
|
||||
void flush_xroute(struct xroute *xroute);
|
||||
int babel_ipv4_route_add (struct zapi_ipv4 *api, struct prefix_ipv4 *prefix,
|
||||
unsigned int ifindex, struct in_addr *nexthop);
|
||||
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 babel_route_add (struct zapi_route *api);
|
||||
int babel_route_delete (struct zapi_route *api);
|
||||
int xroutes_estimate(void);
|
||||
struct xroute_stream *xroute_stream(void);
|
||||
struct xroute *xroute_stream_next(struct xroute_stream *stream);
|
||||
|
@ -72,7 +72,7 @@ struct bgp_attr_encap_subtlv {
|
||||
unsigned long refcnt;
|
||||
uint16_t type;
|
||||
uint16_t length;
|
||||
uint8_t value[1]; /* will be extended */
|
||||
uint8_t value[0]; /* will be extended */
|
||||
};
|
||||
|
||||
#if ENABLE_BGP_VNC
|
||||
|
@ -219,9 +219,6 @@ static __attribute__((__noreturn__)) void bgp_exit(int status)
|
||||
memset(bm, 0, sizeof(*bm));
|
||||
|
||||
frr_fini();
|
||||
|
||||
if (bgp_debug_count())
|
||||
log_memstats_stderr("bgpd");
|
||||
exit(status);
|
||||
}
|
||||
|
||||
|
180
bgpd/bgp_route.c
180
bgpd/bgp_route.c
@ -20,6 +20,7 @@
|
||||
*/
|
||||
|
||||
#include <zebra.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "prefix.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
|
||||
* changes.
|
||||
*/
|
||||
if (safi == SAFI_UNICAST) {
|
||||
if (bgp->allocate_mpls_labels[afi][safi]) {
|
||||
if (new_select) {
|
||||
if (!old_select
|
||||
|| bgp_label_index_differs(new_select, old_select)
|
||||
@ -2108,7 +2109,10 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_node *rn,
|
||||
} else
|
||||
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);
|
||||
}
|
||||
} else if (CHECK_FLAG(rn->flags, BGP_NODE_REGISTERED_FOR_LABEL)) {
|
||||
bgp_unregister_for_label(rn);
|
||||
}
|
||||
|
||||
@ -6153,8 +6157,7 @@ DEFUN (no_ipv6_aggregate_address,
|
||||
|
||||
/* Redistribute route treatment. */
|
||||
void bgp_redistribute_add(struct bgp *bgp, struct prefix *p,
|
||||
const struct in_addr *nexthop,
|
||||
const struct in6_addr *nexthop6, unsigned int ifindex,
|
||||
const union g_addr *nexthop, unsigned int ifindex,
|
||||
u_int32_t metric, u_char type, u_short instance,
|
||||
route_tag_t tag)
|
||||
{
|
||||
@ -6170,14 +6173,17 @@ void bgp_redistribute_add(struct bgp *bgp, struct prefix *p,
|
||||
|
||||
/* Make default attribute. */
|
||||
bgp_attr_default_set(&attr, BGP_ORIGIN_INCOMPLETE);
|
||||
if (nexthop)
|
||||
attr.nexthop = *nexthop;
|
||||
attr.nh_ifindex = ifindex;
|
||||
|
||||
if (nexthop6) {
|
||||
attr.mp_nexthop_global = *nexthop6;
|
||||
if (nexthop) {
|
||||
switch (p->family) {
|
||||
case AF_INET:
|
||||
attr.nexthop = nexthop->ipv4;
|
||||
break;
|
||||
case AF_INET6:
|
||||
attr.mp_nexthop_global = nexthop->ipv6;
|
||||
attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
|
||||
}
|
||||
}
|
||||
attr.nh_ifindex = ifindex;
|
||||
|
||||
attr.med = metric;
|
||||
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,
|
||||
const char *prefix, afi_t afi, safi_t safi,
|
||||
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);
|
||||
static int bgp_show_community(struct vty *vty, struct bgp *bgp,
|
||||
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,
|
||||
safi_t safi);
|
||||
|
||||
/* BGP route print out function. */
|
||||
|
||||
/* BGP route print out function without JSON */
|
||||
DEFUN (show_ip_bgp,
|
||||
show_ip_bgp_cmd,
|
||||
"show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]]\
|
||||
[<\
|
||||
cidr-only\
|
||||
|dampening <flap-statistics|dampened-paths|parameters>\
|
||||
<dampening <parameters>\
|
||||
|route-map WORD\
|
||||
|prefix-list WORD\
|
||||
|filter-list WORD\
|
||||
|statistics\
|
||||
|community [<AA:NN|local-AS|no-advertise|no-export|graceful-shutdown> [exact-match]]\
|
||||
|community <AA:NN|local-AS|no-advertise|no-export|graceful-shutdown> [exact-match]\
|
||||
|community-list <(1-500)|WORD> [exact-match]\
|
||||
|A.B.C.D/M longer-prefixes\
|
||||
|X:X::X:X/M longer-prefixes>\
|
||||
] [json]",
|
||||
|X:X::X:X/M longer-prefixes\
|
||||
>",
|
||||
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 detail of configured dampening parameters\n"
|
||||
"Display routes matching the route-map\n"
|
||||
"A route-map to match on\n"
|
||||
@ -8953,13 +8956,11 @@ DEFUN (show_ip_bgp,
|
||||
"IPv4 prefix\n"
|
||||
"Display route and more specific routes\n"
|
||||
"IPv6 prefix\n"
|
||||
"Display route and more specific routes\n"
|
||||
JSON_STR)
|
||||
"Display route and more specific routes\n")
|
||||
{
|
||||
afi_t afi = AFI_IP6;
|
||||
safi_t safi = SAFI_UNICAST;
|
||||
int exact_match = 0;
|
||||
enum bgp_show_type sh_type = bgp_show_type_normal;
|
||||
struct bgp *bgp = NULL;
|
||||
int idx = 0;
|
||||
int idx_community_type = 0;
|
||||
@ -8969,23 +8970,8 @@ DEFUN (show_ip_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);
|
||||
else if (argv_find(argv, argc, "parameters", &idx))
|
||||
if (argv_find(argv, argc, "parameters", &idx))
|
||||
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,
|
||||
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)) {
|
||||
@ -9037,6 +9019,66 @@ DEFUN (show_ip_bgp,
|
||||
safi,
|
||||
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)
|
||||
return bgp_show_mpls_vpn(vty, afi, NULL, bgp_show_type_normal,
|
||||
NULL, 0, uj);
|
||||
@ -9146,7 +9188,7 @@ DEFUN (show_ip_bgp_regexp,
|
||||
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);
|
||||
XFREE(MTYPE_TMP, regstr);
|
||||
return rc;
|
||||
@ -9181,7 +9223,8 @@ DEFUN (show_ip_bgp_instance_all,
|
||||
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)
|
||||
{
|
||||
regex_t *regex;
|
||||
@ -9193,7 +9236,7 @@ static int bgp_show_regexp(struct vty *vty, const char *regstr, afi_t afi,
|
||||
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);
|
||||
return rc;
|
||||
}
|
||||
@ -9399,6 +9442,7 @@ static const char *table_stats_strs[] = {
|
||||
struct bgp_table_stats {
|
||||
struct bgp_table *table;
|
||||
unsigned long long counts[BGP_STATS_MAX];
|
||||
double total_space;
|
||||
};
|
||||
|
||||
#if 0
|
||||
@ -9467,8 +9511,8 @@ static int bgp_table_stats_walker(struct thread *t)
|
||||
ts->counts[BGP_STATS_UNAGGREGATEABLE]++;
|
||||
/* announced address space */
|
||||
if (space)
|
||||
ts->counts[BGP_STATS_SPACE] +=
|
||||
1 << (space - rn->p.prefixlen);
|
||||
ts->total_space += pow(2.0,
|
||||
space - rn->p.prefixlen);
|
||||
} else if (prn->info)
|
||||
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;
|
||||
case BGP_STATS_SPACE:
|
||||
vty_out(vty, "%-30s: ", table_stats_strs[i]);
|
||||
vty_out(vty, "%12llu\n", ts.counts[i]);
|
||||
if (ts.counts[BGP_STATS_MAXBITLEN] < 9)
|
||||
break;
|
||||
vty_out(vty, "%30s: ", "%% announced ");
|
||||
vty_out(vty, "%12g\n", ts.total_space);
|
||||
|
||||
if (afi == AFI_IP6) {
|
||||
vty_out(vty, "%30s: ", "/32 equivalent ");
|
||||
vty_out(vty, "%12g\n",
|
||||
ts.total_space * pow(2.0, -128+32));
|
||||
vty_out(vty, "%30s: ", "/48 equivalent ");
|
||||
vty_out(vty, "%12g\n",
|
||||
ts.total_space * pow(2.0, -128+48));
|
||||
} else {
|
||||
vty_out(vty, "%30s: ", "% announced ");
|
||||
vty_out(vty, "%12.2f\n",
|
||||
100 * (float)ts.counts[BGP_STATS_SPACE]
|
||||
/ (float)((uint64_t)1UL
|
||||
<< ts.counts
|
||||
[BGP_STATS_MAXBITLEN]));
|
||||
ts.total_space * 100. * pow(2.0, -32));
|
||||
vty_out(vty, "%30s: ", "/8 equivalent ");
|
||||
vty_out(vty, "%12.2f\n",
|
||||
(float)ts.counts[BGP_STATS_SPACE]
|
||||
/ (float)(1UL
|
||||
<< (ts.counts
|
||||
[BGP_STATS_MAXBITLEN]
|
||||
- 8)));
|
||||
if (ts.counts[BGP_STATS_MAXBITLEN] < 25)
|
||||
break;
|
||||
ts.total_space * pow(2.0, -32+8));
|
||||
vty_out(vty, "%30s: ", "/24 equivalent ");
|
||||
vty_out(vty, "%12.2f",
|
||||
(float)ts.counts[BGP_STATS_SPACE]
|
||||
/ (float)(1UL
|
||||
<< (ts.counts
|
||||
[BGP_STATS_MAXBITLEN]
|
||||
- 24)));
|
||||
vty_out(vty, "%12.2f\n",
|
||||
ts.total_space * pow(2.0, -32+24));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
vty_out(vty, "%-30s: ", table_stats_strs[i]);
|
||||
@ -11332,6 +11371,7 @@ void bgp_route_init(void)
|
||||
/* IPv4 labeled-unicast configuration. */
|
||||
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_json_cmd);
|
||||
install_element(VIEW_NODE, &show_ip_bgp_route_cmd);
|
||||
install_element(VIEW_NODE, &show_ip_bgp_regexp_cmd);
|
||||
|
||||
|
@ -22,6 +22,7 @@
|
||||
#define _QUAGGA_BGP_ROUTE_H
|
||||
|
||||
#include "queue.h"
|
||||
#include "nexthop.h"
|
||||
#include "bgp_table.h"
|
||||
|
||||
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 void bgp_redistribute_add(struct bgp *, struct prefix *,
|
||||
const struct in_addr *,
|
||||
const struct in6_addr *, unsigned int ifindex,
|
||||
const union g_addr *, unsigned int ifindex,
|
||||
u_int32_t, u_char, u_short, route_tag_t);
|
||||
extern void bgp_redistribute_delete(struct bgp *, struct prefix *, u_char,
|
||||
u_short);
|
||||
|
@ -7081,26 +7081,6 @@ static int bgp_show_summary(struct vty *vty, struct bgp *bgp, int afi, int safi,
|
||||
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,
|
||||
int safi, u_char use_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)
|
||||
safi = 1; /* SAFI_UNICAST */
|
||||
while (safi < SAFI_MAX) {
|
||||
if (bgp_show_summary_afi_safi_peer_exists(bgp, afi,
|
||||
safi)) {
|
||||
if (bgp_afi_safi_peer_exists(bgp, afi, safi)) {
|
||||
json_output = true;
|
||||
if (is_wildcard) {
|
||||
/*
|
||||
|
651
bgpd/bgp_zebra.c
651
bgpd/bgp_zebra.c
@ -58,11 +58,6 @@
|
||||
/* All information about zebra. */
|
||||
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
|
||||
route-map apply. Arrays are being used here to minimize mallocs and
|
||||
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. */
|
||||
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)
|
||||
{
|
||||
struct stream *s;
|
||||
struct zapi_ipv4 api;
|
||||
struct in_addr nexthop;
|
||||
struct prefix_ipv4 p;
|
||||
struct zapi_route api;
|
||||
union g_addr nexthop;
|
||||
unsigned int ifindex;
|
||||
int i;
|
||||
int add, i;
|
||||
struct bgp *bgp;
|
||||
|
||||
bgp = bgp_lookup_by_vrf_id(vrf_id);
|
||||
if (!bgp)
|
||||
return 0;
|
||||
|
||||
s = zclient->ibuf;
|
||||
nexthop.s_addr = 0;
|
||||
if (zapi_route_decode(zclient->ibuf, &api) < 0)
|
||||
return -1;
|
||||
|
||||
/* Type, flags, message. */
|
||||
api.type = stream_getc(s);
|
||||
api.instance = stream_getw(s);
|
||||
api.flags = stream_getl(s);
|
||||
api.message = stream_getc(s);
|
||||
/* we completely ignore srcdest routes for now. */
|
||||
if (CHECK_FLAG(api.message, ZAPI_MESSAGE_SRCPFX))
|
||||
return 0;
|
||||
|
||||
/* 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));
|
||||
/* ignore link-local address. */
|
||||
if (api.prefix.family == AF_INET6
|
||||
&& IN6_IS_ADDR_LINKLOCAL(&api.prefix.u.prefix6))
|
||||
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);
|
||||
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);
|
||||
}
|
||||
nexthop = api.nexthops[0].gate;
|
||||
ifindex = api.nexthops[0].ifindex;
|
||||
|
||||
add = (command == ZEBRA_REDISTRIBUTE_ROUTE_ADD);
|
||||
if (add) {
|
||||
/*
|
||||
* The ADD message is actually an UPDATE and there is no
|
||||
* explicit DEL
|
||||
@ -639,156 +595,30 @@ static int zebra_read_ipv4(int command, struct zclient *zclient,
|
||||
*/
|
||||
for (i = 0; i < ZEBRA_ROUTE_MAX; i++) {
|
||||
if (i != api.type)
|
||||
bgp_redistribute_delete(bgp,
|
||||
(struct prefix *)&p, i,
|
||||
bgp_redistribute_delete(bgp, &api.prefix, i,
|
||||
api.instance);
|
||||
}
|
||||
|
||||
/* Now perform the add/update. */
|
||||
bgp_redistribute_add(bgp, (struct prefix *)&p, &nexthop, NULL,
|
||||
ifindex, api.metric, api.type,
|
||||
api.instance, 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 */
|
||||
bgp_redistribute_add(bgp, &api.prefix, &nexthop, ifindex,
|
||||
api.metric, api.type, api.instance,
|
||||
api.tag);
|
||||
} else {
|
||||
ifindex = 0;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
/* 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,
|
||||
bgp_redistribute_delete(bgp, &api.prefix, api.type,
|
||||
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];
|
||||
if (bgp_debug_zebra(&api.prefix)) {
|
||||
char buf[2][PREFIX_STRLEN];
|
||||
|
||||
prefix2str(&api.prefix, buf[0], sizeof(buf[0]));
|
||||
inet_ntop(api.prefix.family, &nexthop, buf[1], sizeof(buf[1]));
|
||||
zlog_debug(
|
||||
"Rx IPv6 route delete VRF %u %s[%d] %s/%d "
|
||||
"Rx route %s VRF %u %s[%d] %s "
|
||||
"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);
|
||||
(add) ? "add" : "delete", vrf_id,
|
||||
zebra_route_string(api.type), api.instance, buf[0],
|
||||
buf[1], api.metric, api.tag);
|
||||
}
|
||||
|
||||
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,
|
||||
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;
|
||||
struct peer *peer;
|
||||
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))
|
||||
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)
|
||||
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;
|
||||
|
||||
tag = info->attr->tag;
|
||||
@ -1189,40 +1022,39 @@ void bgp_zebra_announce(struct bgp_node *rn, struct prefix *p,
|
||||
* in
|
||||
* the RIB */
|
||||
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
|
||||
|| info->sub_type == BGP_ROUTE_AGGREGATE) {
|
||||
SET_FLAG(flags, ZEBRA_FLAG_IBGP);
|
||||
SET_FLAG(flags, ZEBRA_FLAG_INTERNAL);
|
||||
SET_FLAG(api.flags, ZEBRA_FLAG_IBGP);
|
||||
SET_FLAG(api.flags, ZEBRA_FLAG_INTERNAL);
|
||||
}
|
||||
|
||||
if ((peer->sort == BGP_PEER_EBGP && peer->ttl != 1)
|
||||
|| CHECK_FLAG(peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK)
|
||||
|| 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)) {
|
||||
struct zapi_ipv4 api;
|
||||
struct in_addr *nexthop;
|
||||
char buf[2][INET_ADDRSTRLEN];
|
||||
int valid_nh_count = 0;
|
||||
int has_valid_label = 0;
|
||||
|
||||
/* resize nexthop buffer size if necessary */
|
||||
stream_reset(bgp_nexthop_buf);
|
||||
nexthop = NULL;
|
||||
|
||||
stream_reset(bgp_label_buf);
|
||||
/* Get nexthop address-family */
|
||||
if (p->family == AF_INET && !BGP_ATTR_NEXTHOP_AFI_IP6(info->attr))
|
||||
nh_family = AF_INET;
|
||||
else if (p->family == AF_INET6
|
||||
|| (p->family == AF_INET
|
||||
&& BGP_ATTR_NEXTHOP_AFI_IP6(info->attr)))
|
||||
nh_family = AF_INET6;
|
||||
else
|
||||
return;
|
||||
|
||||
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)) {
|
||||
for (mpinfo = info; mpinfo; mpinfo = bgp_info_mpath_next(mpinfo)) {
|
||||
if (nh_family == AF_INET) {
|
||||
struct in_addr *nexthop;
|
||||
|
||||
nexthop = NULL;
|
||||
|
||||
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,
|
||||
info_cp)) {
|
||||
if (mpinfo == info) {
|
||||
/* Metric is currently based on
|
||||
* the best-path only */
|
||||
metric = info_cp->attr->med;
|
||||
tag = info_cp->attr->tag;
|
||||
}
|
||||
@ -1248,118 +1078,13 @@ void bgp_zebra_announce(struct bgp_node *rn, struct prefix *p,
|
||||
if (nexthop == NULL)
|
||||
continue;
|
||||
|
||||
stream_put(bgp_nexthop_buf, &nexthop,
|
||||
sizeof(struct in_addr *));
|
||||
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++;
|
||||
}
|
||||
|
||||
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);
|
||||
api_nh = &api.nexthops[valid_nh_count];
|
||||
api_nh->gate.ipv4 = *nexthop;
|
||||
api_nh->type = NEXTHOP_TYPE_IPV4;
|
||||
} else {
|
||||
api.label_num = 0;
|
||||
api.label = NULL;
|
||||
}
|
||||
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;
|
||||
nexthop = NULL;
|
||||
|
||||
@ -1407,61 +1132,31 @@ void bgp_zebra_announce(struct bgp_node *rn, struct prefix *p,
|
||||
if (ifindex == 0)
|
||||
continue;
|
||||
|
||||
stream_put(bgp_nexthop_buf, &nexthop,
|
||||
sizeof(struct in6_addr *));
|
||||
stream_put(bgp_ifindices_buf, &ifindex,
|
||||
sizeof(unsigned int));
|
||||
api_nh = &api.nexthops[valid_nh_count];
|
||||
api_nh->gate.ipv6 = *nexthop;
|
||||
api_nh->ifindex = ifindex;
|
||||
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));
|
||||
|
||||
api_nh->label_num = 1;
|
||||
api_nh->labels[0] = label;
|
||||
}
|
||||
valid_nh_count++;
|
||||
}
|
||||
|
||||
/* Make Zebra API structure. */
|
||||
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_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
|
||||
if (!CHECK_FLAG(api.flags, ZEBRA_FLAG_BLACKHOLE))
|
||||
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);
|
||||
api.metric = metric;
|
||||
api.tag = 0;
|
||||
|
||||
if (tag) {
|
||||
SET_FLAG(api.message, ZAPI_MESSAGE_TAG);
|
||||
@ -1474,80 +1169,35 @@ void bgp_zebra_announce(struct bgp_node *rn, struct prefix *p,
|
||||
api.distance = distance;
|
||||
}
|
||||
|
||||
if (p->family == AF_INET) {
|
||||
if (bgp_debug_zebra(p)) {
|
||||
int i;
|
||||
char prefix_buf[PREFIX_STRLEN];
|
||||
char nh_buf[INET6_ADDRSTRLEN];
|
||||
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);
|
||||
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.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),
|
||||
api_nh->labels[0]);
|
||||
zlog_debug(" nhop [%d]: %s %s", i + 1, nh_buf,
|
||||
label_buf);
|
||||
}
|
||||
}
|
||||
|
||||
if (valid_nh_count)
|
||||
zapi_ipv4_route_ipv6_nexthop(
|
||||
ZEBRA_IPV4_ROUTE_IPV6_NEXTHOP_ADD,
|
||||
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(
|
||||
valid_nh_count ? ZEBRA_IPV6_ROUTE_ADD
|
||||
: ZEBRA_IPV6_ROUTE_DELETE,
|
||||
zclient, (struct prefix_ipv6 *)p, NULL, &api);
|
||||
}
|
||||
}
|
||||
zclient_route_send(valid_nh_count ? ZEBRA_ROUTE_ADD
|
||||
: ZEBRA_ROUTE_DELETE,
|
||||
zclient, &api);
|
||||
}
|
||||
|
||||
/* 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)
|
||||
{
|
||||
u_int32_t flags;
|
||||
struct zapi_route api;
|
||||
struct peer *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))
|
||||
return;
|
||||
|
||||
if ((p->family == AF_INET
|
||||
&& !vrf_bitmap_check(zclient->redist[AFI_IP][ZEBRA_ROUTE_BGP],
|
||||
peer->bgp->vrf_id))
|
||||
|| (p->family == AF_INET6
|
||||
&& !vrf_bitmap_check(zclient->redist[AFI_IP6][ZEBRA_ROUTE_BGP],
|
||||
peer->bgp->vrf_id)))
|
||||
return;
|
||||
|
||||
flags = 0;
|
||||
memset(&api, 0, sizeof(api));
|
||||
api.vrf_id = peer->bgp->vrf_id;
|
||||
api.type = ZEBRA_ROUTE_BGP;
|
||||
api.safi = safi;
|
||||
api.prefix = *p;
|
||||
|
||||
if (peer->sort == BGP_PEER_IBGP) {
|
||||
SET_FLAG(flags, ZEBRA_FLAG_INTERNAL);
|
||||
SET_FLAG(flags, ZEBRA_FLAG_IBGP);
|
||||
SET_FLAG(api.flags, ZEBRA_FLAG_INTERNAL);
|
||||
SET_FLAG(api.flags, ZEBRA_FLAG_IBGP);
|
||||
}
|
||||
|
||||
if ((peer->sort == BGP_PEER_EBGP && peer->ttl != 1)
|
||||
|| CHECK_FLAG(peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK)
|
||||
|| bgp_flag_check(peer->bgp, BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
|
||||
SET_FLAG(flags, ZEBRA_FLAG_INTERNAL);
|
||||
|
||||
if (p->family == AF_INET) {
|
||||
struct zapi_ipv4 api;
|
||||
|
||||
api.vrf_id = peer->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);
|
||||
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;
|
||||
}
|
||||
SET_FLAG(api.flags, ZEBRA_FLAG_INTERNAL);
|
||||
|
||||
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);
|
||||
char buf[PREFIX_STRLEN];
|
||||
|
||||
prefix2str(&api.prefix, buf, sizeof(buf));
|
||||
zlog_debug("Tx route delete VRF %u %s", peer->bgp->vrf_id, buf);
|
||||
}
|
||||
|
||||
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;
|
||||
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);
|
||||
}
|
||||
zclient_route_send(ZEBRA_ROUTE_DELETE, zclient, &api);
|
||||
}
|
||||
|
||||
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 =
|
||||
bgp_interface_nbr_address_delete;
|
||||
zclient->interface_vrf_update = bgp_interface_vrf_update;
|
||||
zclient->redistribute_route_ipv4_add = zebra_read_ipv4;
|
||||
zclient->redistribute_route_ipv4_del = zebra_read_ipv4;
|
||||
zclient->redistribute_route_add = zebra_read_route;
|
||||
zclient->redistribute_route_del = zebra_read_route;
|
||||
zclient->interface_up = bgp_interface_up;
|
||||
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->import_check_update = bgp_read_import_check_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_macip_add = 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)
|
||||
{
|
||||
|
||||
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)
|
||||
return;
|
||||
zclient_stop(zclient);
|
||||
|
73
bgpd/bgpd.c
73
bgpd/bgpd.c
@ -1391,17 +1391,11 @@ void bgp_peer_conf_if_to_su_update(struct peer *peer)
|
||||
hash_get(peer->bgp->peerhash, peer, hash_alloc_intern);
|
||||
}
|
||||
|
||||
/* Force a bestpath recalculation for all prefixes. This is used
|
||||
* when 'bgp bestpath' commands are entered.
|
||||
*/
|
||||
void bgp_recalculate_all_bestpaths(struct bgp *bgp)
|
||||
static void bgp_recalculate_afi_safi_bestpaths(struct bgp *bgp, afi_t afi,
|
||||
safi_t safi)
|
||||
{
|
||||
afi_t afi;
|
||||
safi_t safi;
|
||||
struct bgp_node *rn, *nrn;
|
||||
|
||||
for (afi = AFI_IP; afi < AFI_MAX; afi++) {
|
||||
for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) {
|
||||
for (rn = bgp_table_top(bgp->rib[afi][safi]); rn;
|
||||
rn = bgp_route_next(rn)) {
|
||||
if (rn->info != NULL) {
|
||||
@ -1422,6 +1416,19 @@ void bgp_recalculate_all_bestpaths(struct bgp *bgp)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Force a bestpath recalculation for all prefixes. This is used
|
||||
* when 'bgp bestpath' commands are entered.
|
||||
*/
|
||||
void bgp_recalculate_all_bestpaths(struct bgp *bgp)
|
||||
{
|
||||
afi_t afi;
|
||||
safi_t safi;
|
||||
|
||||
for (afi = AFI_IP; afi < AFI_MAX; afi++) {
|
||||
for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) {
|
||||
bgp_recalculate_afi_safi_bestpaths(bgp, afi, safi);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1500,6 +1507,25 @@ struct peer *peer_create_accept(struct bgp *bgp)
|
||||
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. */
|
||||
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 listnode *node, *nnode;
|
||||
struct peer *tmp_peer;
|
||||
struct bgp *bgp;
|
||||
|
||||
/* Nothing to do if we've already activated this peer */
|
||||
if (peer->afc[afi][safi])
|
||||
return ret;
|
||||
|
||||
bgp = peer->bgp;
|
||||
|
||||
/* This is a peer-group so activate all of the members of the
|
||||
* peer-group as well */
|
||||
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);
|
||||
}
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
@ -1798,6 +1838,7 @@ int peer_deactivate(struct peer *peer, afi_t afi, safi_t safi)
|
||||
struct peer_group *group;
|
||||
struct peer *tmp_peer;
|
||||
struct listnode *node, *nnode;
|
||||
struct bgp *bgp;
|
||||
|
||||
/* Nothing to do if we've already de-activated this peer */
|
||||
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);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@ -3087,6 +3142,8 @@ int bgp_delete(struct bgp *bgp)
|
||||
* routes to be processed still referencing the struct bgp.
|
||||
*/
|
||||
listnode_delete(bm->bgp, bgp);
|
||||
if (list_isempty(bm->bgp))
|
||||
bgp_close();
|
||||
|
||||
/* Deregister from Zebra, if needed */
|
||||
if (IS_BGP_INST_KNOWN_TO_ZEBRA(bgp))
|
||||
|
@ -334,6 +334,9 @@ struct bgp {
|
||||
/* BGP redistribute configuration. */
|
||||
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 */
|
||||
struct thread *t_rmap_def_originate_eval;
|
||||
#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_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 int peer_remote_as(struct bgp *, union sockunion *, const char *, as_t *,
|
||||
int, afi_t, safi_t);
|
||||
|
@ -57,8 +57,8 @@ static struct zclient *zclient_vnc = NULL;
|
||||
/*
|
||||
* Routes coming from zebra get added to VNC here
|
||||
*/
|
||||
static void vnc_redistribute_add(struct prefix *p, struct in_addr *nexthop,
|
||||
u_int32_t metric, uint8_t type)
|
||||
static void vnc_redistribute_add(struct prefix *p, u_int32_t metric,
|
||||
uint8_t type)
|
||||
{
|
||||
struct bgp *bgp = bgp_get_default();
|
||||
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
|
||||
*/
|
||||
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)
|
||||
{
|
||||
struct stream *s;
|
||||
struct zapi_ipv4 api;
|
||||
struct in_addr nexthop;
|
||||
struct prefix_ipv4 p;
|
||||
struct zapi_route api;
|
||||
int add;
|
||||
|
||||
s = zclient->ibuf;
|
||||
nexthop.s_addr = 0;
|
||||
if (zapi_route_decode(zclient->ibuf, &api) < 0)
|
||||
return -1;
|
||||
|
||||
/* Type, flags, message. */
|
||||
api.type = stream_getc(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));
|
||||
|
||||
/* 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. */
|
||||
if (CHECK_FLAG(api.message, ZAPI_MESSAGE_SRCPFX))
|
||||
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);
|
||||
stream_getl(s);
|
||||
}
|
||||
if (CHECK_FLAG(api.message, ZAPI_MESSAGE_DISTANCE))
|
||||
api.distance = stream_getc(s);
|
||||
add = (command == ZEBRA_REDISTRIBUTE_ROUTE_ADD);
|
||||
if (add)
|
||||
vnc_redistribute_add(&api.prefix, api.metric, api.type);
|
||||
else
|
||||
api.distance = 0;
|
||||
if (CHECK_FLAG(api.message, ZAPI_MESSAGE_METRIC))
|
||||
api.metric = stream_getl(s);
|
||||
else
|
||||
api.metric = 0;
|
||||
vnc_redistribute_delete(&api.prefix, api.type);
|
||||
|
||||
/* Simply ignore link-local address. */
|
||||
if (IN6_IS_ADDR_LINKLOCAL(&p.prefix))
|
||||
return 0;
|
||||
if (BGP_DEBUG(zebra, ZEBRA)) {
|
||||
char buf[PREFIX_STRLEN];
|
||||
|
||||
if (command == ZEBRA_IPV6_ROUTE_ADD) {
|
||||
if (BGP_DEBUG(zebra, ZEBRA)) {
|
||||
char buf[INET6_ADDRSTRLEN];
|
||||
prefix2str(&api.prefix, buf, sizeof(buf));
|
||||
vnc_zlog_debug_verbose(
|
||||
"Zebra rcvd: IPv6 route add %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_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);
|
||||
"%s: Zebra rcvd: route delete %s %s metric %u",
|
||||
__func__, zebra_route_string(api.type), buf,
|
||||
api.metric);
|
||||
}
|
||||
|
||||
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,
|
||||
int add) /* 1 = add, 0 = del */
|
||||
{
|
||||
struct zapi_route api;
|
||||
struct zapi_nexthop *api_nh;
|
||||
int i;
|
||||
|
||||
if (!nhp_count) {
|
||||
vnc_zlog_debug_verbose("%s: empty nexthop list, skipping",
|
||||
__func__);
|
||||
return;
|
||||
}
|
||||
|
||||
if (p->family == AF_INET) {
|
||||
|
||||
struct zapi_ipv4 api;
|
||||
|
||||
api.flags = 0;
|
||||
memset(&api, 0, sizeof(api));
|
||||
api.vrf_id = VRF_DEFAULT;
|
||||
api.type = ZEBRA_ROUTE_VNC;
|
||||
api.message = 0;
|
||||
SET_FLAG(api.message,
|
||||
ZAPI_MESSAGE_NEXTHOP); /* TBD what's it mean? */
|
||||
api.nexthop_num = nhp_count;
|
||||
api.nexthop = nhp_ary;
|
||||
api.ifindex_num = 0;
|
||||
api.instance = 0;
|
||||
api.safi = SAFI_UNICAST;
|
||||
api.prefix = *p;
|
||||
|
||||
/* 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_nh = &api.nexthops[i];
|
||||
switch (p->family) {
|
||||
case AF_INET:
|
||||
nhp_ary4 = nhp_ary;
|
||||
memcpy(&api_nh->gate.ipv4, &nhp_ary4[i],
|
||||
sizeof(api_nh->gate.ipv4));
|
||||
api_nh->type = NEXTHOP_TYPE_IPV4;
|
||||
break;
|
||||
case AF_INET6:
|
||||
nhp_ary6 = nhp_ary;
|
||||
memcpy(&api_nh->gate.ipv6, &nhp_ary6[i],
|
||||
sizeof(api_nh->gate.ipv6));
|
||||
api_nh->type = NEXTHOP_TYPE_IPV6;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (BGP_DEBUG(zebra, ZEBRA)) {
|
||||
char buf[PREFIX_STRLEN];
|
||||
|
||||
char buf[INET_ADDRSTRLEN];
|
||||
prefix2str(&api.prefix, buf, sizeof(buf));
|
||||
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);
|
||||
"%s: Zebra send: route %s %s, nhp_count=%d", __func__,
|
||||
(add ? "add" : "del"), buf, 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;
|
||||
}
|
||||
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_init(zclient_vnc, ZEBRA_ROUTE_VNC, 0);
|
||||
|
||||
zclient_vnc->redistribute_route_ipv4_add = vnc_zebra_read_ipv4;
|
||||
zclient_vnc->redistribute_route_ipv4_del = vnc_zebra_read_ipv4;
|
||||
zclient_vnc->redistribute_route_ipv6_add = vnc_zebra_read_ipv6;
|
||||
zclient_vnc->redistribute_route_ipv6_del = vnc_zebra_read_ipv6;
|
||||
zclient_vnc->redistribute_route_add = vnc_zebra_read_route;
|
||||
zclient_vnc->redistribute_route_del = vnc_zebra_read_route;
|
||||
}
|
||||
|
||||
void vnc_zebra_destroy(void)
|
||||
|
@ -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
|
||||
.c_clippy.c:
|
||||
@{ 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
|
||||
@{ test -f $@ && diff $@.tmp $@ >/dev/null 2>/dev/null; } && rm $@.tmp || mv $@.tmp $@
|
||||
$(AM_V_CLIPPY)$(top_builddir)/$(HOSTTOOLS)lib/clippy $(top_srcdir)/python/clidef.py -o $@ $<
|
||||
|
||||
## automake's "ylwrap" is a great piece of GNU software... not.
|
||||
.l.c:
|
||||
|
@ -158,7 +158,7 @@ const char *eigrp_topology_ip_string(struct eigrp_prefix_entry *tn)
|
||||
static char buf[EIGRP_IF_STRING_MAXLEN] = "";
|
||||
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",
|
||||
(ifaddr >> 24) & 0xff, (ifaddr >> 16) & 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)
|
||||
{
|
||||
struct list *successors = eigrp_topology_get_successor(tn);
|
||||
char buffer[PREFIX_STRLEN];
|
||||
|
||||
vty_out(vty, "%-3c", (tn->state > 0) ? 'A' : 'P');
|
||||
|
||||
vty_out(vty, "%s/%u, ", inet_ntoa(tn->destination_ipv4->prefix),
|
||||
tn->destination_ipv4->prefixlen);
|
||||
vty_out(vty, "%s, ",
|
||||
prefix2str(tn->destination, buffer, PREFIX_STRLEN));
|
||||
vty_out(vty, "%u successors, ", successors->count);
|
||||
vty_out(vty, "FD is %u, serno: %" PRIu64 " \n", tn->fdistance,
|
||||
tn->serno);
|
||||
|
@ -178,7 +178,7 @@ struct {
|
||||
* 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
|
||||
// struct eigrp *eigrp = msg->eigrp;
|
||||
@ -204,8 +204,7 @@ int eigrp_get_fsm_event(struct eigrp_fsm_action_message *msg)
|
||||
switch (actual_state) {
|
||||
case EIGRP_FSM_STATE_PASSIVE: {
|
||||
struct eigrp_neighbor_entry *head =
|
||||
(struct eigrp_neighbor_entry *)
|
||||
entry->prefix->entries->head->data;
|
||||
listnode_head(prefix->entries);
|
||||
|
||||
if (head->reported_distance < prefix->fdistance) {
|
||||
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: {
|
||||
if (msg->packet_type == EIGRP_OPC_REPLY) {
|
||||
struct eigrp_neighbor_entry *head =
|
||||
(struct eigrp_neighbor_entry *)
|
||||
entry->prefix->entries->head->data;
|
||||
listnode_head(prefix->entries);
|
||||
|
||||
listnode_delete(prefix->rij, entry->adv_router);
|
||||
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: {
|
||||
if (msg->packet_type == EIGRP_OPC_REPLY) {
|
||||
struct eigrp_neighbor_entry *head =
|
||||
(struct eigrp_neighbor_entry *)
|
||||
prefix->entries->head->data;
|
||||
listnode_head(prefix->entries);
|
||||
|
||||
listnode_delete(prefix->rij, entry->adv_router);
|
||||
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.
|
||||
* 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",
|
||||
msg->eigrp->AS, msg->prefix->state, event,
|
||||
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_prefix_entry *prefix = msg->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?
|
||||
|
||||
ne = listnode_head(successors);
|
||||
prefix->state = EIGRP_FSM_STATE_ACTIVE_1;
|
||||
prefix->rdistance = prefix->distance = prefix->fdistance =
|
||||
((struct eigrp_neighbor_entry *)successors->head->data)
|
||||
->distance;
|
||||
prefix->reported_metric =
|
||||
((struct eigrp_neighbor_entry *)successors->head->data)
|
||||
->total_metric;
|
||||
ne->distance;
|
||||
prefix->reported_metric = ne->total_metric;
|
||||
|
||||
if (eigrp_nbr_count_get()) {
|
||||
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_prefix_entry *prefix = msg->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.
|
||||
|
||||
ne = listnode_head(successors);
|
||||
prefix->state = EIGRP_FSM_STATE_ACTIVE_3;
|
||||
prefix->rdistance = prefix->distance = prefix->fdistance =
|
||||
((struct eigrp_neighbor_entry *)successors->head->data)
|
||||
->distance;
|
||||
prefix->reported_metric =
|
||||
((struct eigrp_neighbor_entry *)successors->head->data)
|
||||
->total_metric;
|
||||
ne->distance;
|
||||
prefix->reported_metric = ne->total_metric;
|
||||
if (eigrp_nbr_count_get()) {
|
||||
prefix->req_action |= EIGRP_FSM_NEED_QUERY;
|
||||
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)
|
||||
{
|
||||
struct eigrp_prefix_entry *prefix = msg->prefix;
|
||||
struct eigrp_neighbor_entry *ne = listnode_head(prefix->entries);
|
||||
|
||||
if (prefix->state == EIGRP_FSM_STATE_PASSIVE) {
|
||||
if (!eigrp_metrics_is_same(prefix->reported_metric,
|
||||
((struct eigrp_neighbor_entry *)
|
||||
prefix->entries->head->data)
|
||||
->total_metric)) {
|
||||
ne->total_metric)) {
|
||||
prefix->rdistance = prefix->fdistance =
|
||||
prefix->distance =
|
||||
((struct eigrp_neighbor_entry *)
|
||||
prefix->entries->head->data)
|
||||
->distance;
|
||||
prefix->distance = ne->distance;
|
||||
prefix->reported_metric =
|
||||
((struct eigrp_neighbor_entry *)
|
||||
prefix->entries->head->data)
|
||||
->total_metric;
|
||||
ne->total_metric;
|
||||
if (msg->packet_type == EIGRP_OPC_QUERY)
|
||||
eigrp_send_reply(msg->adv_router, prefix);
|
||||
prefix->req_action |= EIGRP_FSM_NEED_UPDATE;
|
||||
@ -441,21 +431,19 @@ int eigrp_fsm_event_lr(struct eigrp_fsm_action_message *msg)
|
||||
{
|
||||
struct eigrp *eigrp = msg->eigrp;
|
||||
struct eigrp_prefix_entry *prefix = msg->prefix;
|
||||
struct eigrp_neighbor_entry *ne = listnode_head(prefix->entries);
|
||||
|
||||
prefix->fdistance = prefix->distance = prefix->rdistance =
|
||||
((struct eigrp_neighbor_entry *)(prefix->entries->head->data))
|
||||
->distance;
|
||||
prefix->reported_metric =
|
||||
((struct eigrp_neighbor_entry *)(prefix->entries->head->data))
|
||||
->total_metric;
|
||||
ne->distance;
|
||||
prefix->reported_metric = ne->total_metric;
|
||||
|
||||
if (prefix->state == EIGRP_FSM_STATE_ACTIVE_3) {
|
||||
struct list *successors = eigrp_topology_get_successor(prefix);
|
||||
|
||||
assert(successors); // It's like Napolean and Waterloo
|
||||
|
||||
eigrp_send_reply(
|
||||
((struct eigrp_neighbor_entry *)successors->head->data)
|
||||
->adv_router,
|
||||
ne = listnode_head(successors);
|
||||
eigrp_send_reply(ne->adv_router,
|
||||
prefix);
|
||||
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)
|
||||
{
|
||||
struct list *successors = eigrp_topology_get_successor(msg->prefix);
|
||||
struct eigrp_neighbor_entry *ne;
|
||||
|
||||
assert(successors); // Trump and his big hands
|
||||
|
||||
ne = listnode_head(successors);
|
||||
msg->prefix->state = msg->prefix->state == EIGRP_FSM_STATE_ACTIVE_1
|
||||
? EIGRP_FSM_STATE_ACTIVE_0
|
||||
: EIGRP_FSM_STATE_ACTIVE_2;
|
||||
msg->prefix->distance =
|
||||
((struct eigrp_neighbor_entry *)successors->head->data)
|
||||
->distance;
|
||||
msg->prefix->distance = ne->distance;
|
||||
if (!msg->prefix->rij->count)
|
||||
(*(NSM[msg->prefix->state][eigrp_get_fsm_event(msg)].func))(
|
||||
msg);
|
||||
@ -495,13 +483,11 @@ int eigrp_fsm_event_lr_fcs(struct eigrp_fsm_action_message *msg)
|
||||
{
|
||||
struct eigrp *eigrp = msg->eigrp;
|
||||
struct eigrp_prefix_entry *prefix = msg->prefix;
|
||||
struct eigrp_neighbor_entry *ne = listnode_head(prefix->entries);
|
||||
|
||||
prefix->state = EIGRP_FSM_STATE_PASSIVE;
|
||||
prefix->distance = prefix->rdistance =
|
||||
((struct eigrp_neighbor_entry *)(prefix->entries->head->data))
|
||||
->distance;
|
||||
prefix->reported_metric =
|
||||
((struct eigrp_neighbor_entry *)(prefix->entries->head->data))
|
||||
->total_metric;
|
||||
prefix->distance = prefix->rdistance = ne->distance;
|
||||
prefix->reported_metric = ne->total_metric;
|
||||
prefix->fdistance = prefix->fdistance > prefix->distance
|
||||
? prefix->distance
|
||||
: prefix->fdistance;
|
||||
@ -510,10 +496,8 @@ int eigrp_fsm_event_lr_fcs(struct eigrp_fsm_action_message *msg)
|
||||
|
||||
assert(successors); // Having a spoon and all you need is a
|
||||
// knife
|
||||
|
||||
eigrp_send_reply(
|
||||
((struct eigrp_neighbor_entry *)successors->head->data)
|
||||
->adv_router,
|
||||
ne = listnode_head(successors);
|
||||
eigrp_send_reply(ne->adv_router,
|
||||
prefix);
|
||||
|
||||
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_prefix_entry *prefix = msg->prefix;
|
||||
struct eigrp_neighbor_entry *best_successor;
|
||||
struct list *successors = eigrp_topology_get_successor(prefix);
|
||||
|
||||
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
|
||||
? EIGRP_FSM_STATE_ACTIVE_1
|
||||
: 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->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)
|
||||
{
|
||||
struct list *successors = eigrp_topology_get_successor(msg->prefix);
|
||||
struct eigrp_neighbor_entry *ne;
|
||||
|
||||
assert(successors); // Cats and no Dogs
|
||||
|
||||
ne = listnode_head(successors);
|
||||
msg->prefix->state = EIGRP_FSM_STATE_ACTIVE_2;
|
||||
msg->prefix->distance =
|
||||
((struct eigrp_neighbor_entry *)(successors->head->data))
|
||||
->distance;
|
||||
msg->prefix->distance = ne->distance;
|
||||
|
||||
list_delete(successors);
|
||||
return 1;
|
||||
|
@ -28,8 +28,7 @@
|
||||
#ifndef _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 *, int);
|
||||
extern int eigrp_fsm_event(struct eigrp_fsm_action_message *msg);
|
||||
|
||||
|
||||
#endif /* _ZEBRA_EIGRP_DUAL_H */
|
||||
|
@ -53,6 +53,7 @@
|
||||
#include "eigrpd/eigrp_network.h"
|
||||
#include "eigrpd/eigrp_topology.h"
|
||||
#include "eigrpd/eigrp_memory.h"
|
||||
#include "eigrpd/eigrp_fsm.h"
|
||||
|
||||
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 in_addr addr)
|
||||
{
|
||||
struct prefix_ipv4 p;
|
||||
struct prefix p;
|
||||
struct route_node *rn;
|
||||
|
||||
p.family = AF_INET;
|
||||
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) {
|
||||
route_unlock_node(rn);
|
||||
@ -279,49 +280,63 @@ int eigrp_if_up(struct eigrp_interface *ei)
|
||||
|
||||
/*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->ei = ei;
|
||||
ne->reported_metric = metric;
|
||||
ne->total_metric = metric;
|
||||
ne->distance = eigrp_calculate_metrics(eigrp, metric);
|
||||
ne->reported_distance = 0;
|
||||
ne->prefix = pe;
|
||||
ne->adv_router = eigrp->neighbor_self;
|
||||
ne->flags = EIGRP_NEIGHBOR_ENTRY_SUCCESSOR_FLAG;
|
||||
|
||||
struct prefix dest_addr;
|
||||
|
||||
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)) {
|
||||
if (ei2->nbrs->count != 0) {
|
||||
eigrp_update_send(ei2);
|
||||
}
|
||||
}
|
||||
|
||||
pe->req_action &= ~EIGRP_FSM_NEED_UPDATE;
|
||||
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;
|
||||
}
|
||||
@ -416,7 +431,7 @@ u_char eigrp_default_iftype(struct interface *ifp)
|
||||
|
||||
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 *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);
|
||||
}
|
||||
|
||||
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);
|
||||
dest_addr = *ei->connected->address;
|
||||
apply_mask(&dest_addr);
|
||||
pe = eigrp_topology_table_lookup_ipv4(eigrp->topology_table,
|
||||
&dest_addr);
|
||||
if (pe)
|
||||
@ -532,11 +545,11 @@ struct eigrp_interface *eigrp_if_lookup_recv_if(struct eigrp *eigrp,
|
||||
struct interface *ifp)
|
||||
{
|
||||
struct route_node *rn;
|
||||
struct prefix_ipv4 addr;
|
||||
struct prefix addr;
|
||||
struct eigrp_interface *ei, *match;
|
||||
|
||||
addr.family = AF_INET;
|
||||
addr.prefix = src;
|
||||
addr.u.prefix4 = src;
|
||||
addr.prefixlen = IPV4_MAX_BITLEN;
|
||||
|
||||
match = NULL;
|
||||
@ -551,7 +564,7 @@ struct eigrp_interface *eigrp_if_lookup_recv_if(struct eigrp *eigrp,
|
||||
continue;
|
||||
|
||||
if (prefix_match(CONNECTED_PREFIX(ei->connected),
|
||||
(struct prefix *)&addr)) {
|
||||
&addr)) {
|
||||
if ((match == NULL) || (match->address->prefixlen
|
||||
< ei->address->prefixlen))
|
||||
match = ei;
|
||||
|
@ -357,3 +357,11 @@ void eigrp_nbr_hard_restart(struct eigrp_neighbor *nbr, struct vty *vty)
|
||||
/* delete neighbor */
|
||||
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);
|
||||
}
|
||||
|
@ -53,4 +53,6 @@ extern struct eigrp_neighbor *eigrp_nbr_lookup_by_addr_process(struct eigrp *,
|
||||
struct in_addr);
|
||||
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 */
|
||||
|
@ -229,7 +229,7 @@ int eigrp_if_drop_allspfrouters(struct eigrp *top, struct prefix *p,
|
||||
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 interface *ifp;
|
||||
@ -242,7 +242,7 @@ int eigrp_network_set(struct eigrp *eigrp, struct prefix_ipv4 *p)
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct prefix_ipv4 *pref = prefix_ipv4_new();
|
||||
struct prefix *pref = prefix_new();
|
||||
PREFIX_COPY_IPV4(pref, p);
|
||||
rn->info = (void *)pref;
|
||||
|
||||
@ -253,7 +253,7 @@ int eigrp_network_set(struct eigrp *eigrp, struct prefix_ipv4 *p)
|
||||
/* Get target interface. */
|
||||
for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), node, ifp)) {
|
||||
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;
|
||||
}
|
||||
@ -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 listnode *node, *nnode;
|
||||
struct eigrp_interface *ei;
|
||||
struct prefix *pref;
|
||||
|
||||
rn = route_node_lookup(eigrp->networks, (struct prefix *)p);
|
||||
rn = route_node_lookup(eigrp->networks, p);
|
||||
if (rn == NULL)
|
||||
return 0;
|
||||
|
||||
pref = rn->info;
|
||||
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;
|
||||
|
||||
prefix_ipv4_free(rn->info);
|
||||
|
@ -32,8 +32,8 @@
|
||||
|
||||
extern int eigrp_sock_init(void);
|
||||
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_unset(struct eigrp *eigrp, struct prefix_ipv4 *p);
|
||||
extern int eigrp_network_set(struct eigrp *eigrp, struct prefix *p);
|
||||
extern int eigrp_network_unset(struct eigrp *eigrp, struct prefix *p);
|
||||
|
||||
extern int eigrp_hello_timer(struct thread *);
|
||||
extern void eigrp_if_update(struct interface *);
|
||||
|
@ -1101,6 +1101,16 @@ struct eigrp_packet *eigrp_packet_duplicate(struct eigrp_packet *old,
|
||||
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 *tlv;
|
||||
@ -1157,21 +1167,21 @@ u_int16_t eigrp_add_internalTLV_to_stream(struct stream *s,
|
||||
u_int16_t length;
|
||||
|
||||
stream_putw(s, EIGRP_TLV_IPv4_INT);
|
||||
if (pe->destination_ipv4->prefixlen <= 8) {
|
||||
if (pe->destination->prefixlen <= 8) {
|
||||
stream_putw(s, 0x001A);
|
||||
length = 0x001A;
|
||||
}
|
||||
if ((pe->destination_ipv4->prefixlen > 8)
|
||||
&& (pe->destination_ipv4->prefixlen <= 16)) {
|
||||
if ((pe->destination->prefixlen > 8)
|
||||
&& (pe->destination->prefixlen <= 16)) {
|
||||
stream_putw(s, 0x001B);
|
||||
length = 0x001B;
|
||||
}
|
||||
if ((pe->destination_ipv4->prefixlen > 16)
|
||||
&& (pe->destination_ipv4->prefixlen <= 24)) {
|
||||
if ((pe->destination->prefixlen > 16)
|
||||
&& (pe->destination->prefixlen <= 24)) {
|
||||
stream_putw(s, 0x001C);
|
||||
length = 0x001C;
|
||||
}
|
||||
if (pe->destination_ipv4->prefixlen > 24) {
|
||||
if (pe->destination->prefixlen > 24) {
|
||||
stream_putw(s, 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.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_ipv4->prefix.s_addr & 0xFF);
|
||||
}
|
||||
if ((pe->destination_ipv4->prefixlen > 8)
|
||||
&& (pe->destination_ipv4->prefixlen <= 16)) {
|
||||
stream_putc(s, pe->destination_ipv4->prefix.s_addr & 0xFF);
|
||||
stream_putc(s, pe->destination->u.prefix4.s_addr & 0xFF);
|
||||
if (pe->destination->prefixlen > 8)
|
||||
stream_putc(s,
|
||||
(pe->destination_ipv4->prefix.s_addr >> 8) & 0xFF);
|
||||
}
|
||||
if ((pe->destination_ipv4->prefixlen > 16)
|
||||
&& (pe->destination_ipv4->prefixlen <= 24)) {
|
||||
stream_putc(s, pe->destination_ipv4->prefix.s_addr & 0xFF);
|
||||
(pe->destination->u.prefix4.s_addr >> 8) & 0xFF);
|
||||
if (pe->destination->prefixlen > 16)
|
||||
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,
|
||||
(pe->destination_ipv4->prefix.s_addr >> 16) & 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);
|
||||
}
|
||||
(pe->destination->u.prefix4.s_addr >> 24) & 0xFF);
|
||||
|
||||
return length;
|
||||
}
|
||||
@ -1332,16 +1326,6 @@ void eigrp_authTLV_SHA256_free(struct TLV_SHA256_Authentication_Type *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(
|
||||
struct TLV_IPv4_Internal_type *IPv4_InternalTLV)
|
||||
{
|
||||
|
@ -152,7 +152,6 @@ extern int eigrp_check_sha256_digest(struct stream *,
|
||||
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 struct TLV_Sequence_Type *eigrp_SequenceTLV_new(void);
|
||||
|
@ -91,7 +91,7 @@ void eigrp_query_receive(struct eigrp *eigrp, struct ip *iph,
|
||||
{
|
||||
struct eigrp_neighbor *nbr;
|
||||
struct TLV_IPv4_Internal_type *tlv;
|
||||
struct prefix_ipv4 dest_addr;
|
||||
struct prefix dest_addr;
|
||||
|
||||
u_int16_t type;
|
||||
u_int16_t length;
|
||||
@ -116,7 +116,7 @@ void eigrp_query_receive(struct eigrp *eigrp, struct ip *iph,
|
||||
tlv = eigrp_read_ipv4_tlv(s);
|
||||
|
||||
dest_addr.family = AF_INET;
|
||||
dest_addr.prefix = tlv->destination;
|
||||
dest_addr.u.prefix4 = tlv->destination;
|
||||
dest_addr.prefixlen = tlv->prefix_length;
|
||||
struct eigrp_prefix_entry *dest =
|
||||
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
|
||||
* know)*/
|
||||
if (dest != NULL) {
|
||||
struct eigrp_fsm_action_message *msg;
|
||||
msg = XCALLOC(MTYPE_EIGRP_FSM_MSG,
|
||||
sizeof(struct
|
||||
eigrp_fsm_action_message));
|
||||
struct eigrp_fsm_action_message msg;
|
||||
struct eigrp_neighbor_entry *entry =
|
||||
eigrp_prefix_entry_lookup(dest->entries,
|
||||
nbr);
|
||||
msg->packet_type = EIGRP_OPC_QUERY;
|
||||
msg->eigrp = eigrp;
|
||||
msg->data_type = EIGRP_TLV_IPv4_INT;
|
||||
msg->adv_router = nbr;
|
||||
msg->data.ipv4_int_type = tlv;
|
||||
msg->entry = entry;
|
||||
msg->prefix = dest;
|
||||
int event = eigrp_get_fsm_event(msg);
|
||||
eigrp_fsm_event(msg, event);
|
||||
msg.packet_type = EIGRP_OPC_QUERY;
|
||||
msg.eigrp = eigrp;
|
||||
msg.data_type = EIGRP_INT;
|
||||
msg.adv_router = nbr;
|
||||
msg.metrics = tlv->metric;
|
||||
msg.entry = entry;
|
||||
msg.prefix = dest;
|
||||
eigrp_fsm_event(&msg);
|
||||
}
|
||||
eigrp_IPv4_InternalTLV_free(tlv);
|
||||
break;
|
||||
|
@ -87,19 +87,19 @@ void eigrp_send_reply(struct eigrp_neighbor *nbr, struct eigrp_prefix_entry *pe)
|
||||
|
||||
/* Check if any list fits */
|
||||
if ((alist
|
||||
&& access_list_apply(alist, (struct prefix *)pe2->destination_ipv4)
|
||||
&& access_list_apply(alist, pe2->destination)
|
||||
== FILTER_DENY)
|
||||
|| (plist
|
||||
&& prefix_list_apply(plist,
|
||||
(struct prefix *)pe2->destination_ipv4)
|
||||
pe2->destination)
|
||||
== PREFIX_DENY)
|
||||
|| (alist_i
|
||||
&& access_list_apply(alist_i,
|
||||
(struct prefix *)pe2->destination_ipv4)
|
||||
pe2->destination)
|
||||
== FILTER_DENY)
|
||||
|| (plist_i
|
||||
&& prefix_list_apply(plist_i,
|
||||
(struct prefix *)pe2->destination_ipv4)
|
||||
pe2->destination)
|
||||
== PREFIX_DENY)) {
|
||||
zlog_info("REPLY SEND: Setting Metric to max");
|
||||
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) {
|
||||
type = stream_getw(s);
|
||||
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));
|
||||
|
||||
tlv = eigrp_read_ipv4_tlv(s);
|
||||
|
||||
dest_addr.family = AF_INET;
|
||||
dest_addr.prefix = tlv->destination;
|
||||
dest_addr.u.prefix4 = tlv->destination;
|
||||
dest_addr.prefixlen = tlv->prefix_length;
|
||||
struct eigrp_prefix_entry *dest =
|
||||
eigrp_topology_table_lookup_ipv4(
|
||||
@ -196,9 +196,7 @@ void eigrp_reply_receive(struct eigrp *eigrp, struct ip *iph,
|
||||
*/
|
||||
assert(dest);
|
||||
|
||||
struct eigrp_fsm_action_message *msg;
|
||||
msg = XCALLOC(MTYPE_EIGRP_FSM_MSG,
|
||||
sizeof(struct eigrp_fsm_action_message));
|
||||
struct eigrp_fsm_action_message msg;
|
||||
struct eigrp_neighbor_entry *entry =
|
||||
eigrp_prefix_entry_lookup(dest->entries, nbr);
|
||||
|
||||
@ -237,15 +235,14 @@ void eigrp_reply_receive(struct eigrp *eigrp, struct ip *iph,
|
||||
* End of filtering
|
||||
*/
|
||||
|
||||
msg->packet_type = EIGRP_OPC_REPLY;
|
||||
msg->eigrp = eigrp;
|
||||
msg->data_type = EIGRP_TLV_IPv4_INT;
|
||||
msg->adv_router = nbr;
|
||||
msg->data.ipv4_int_type = tlv;
|
||||
msg->entry = entry;
|
||||
msg->prefix = dest;
|
||||
int event = eigrp_get_fsm_event(msg);
|
||||
eigrp_fsm_event(msg, event);
|
||||
msg.packet_type = EIGRP_OPC_REPLY;
|
||||
msg.eigrp = eigrp;
|
||||
msg.data_type = EIGRP_INT;
|
||||
msg.adv_router = nbr;
|
||||
msg.metrics = tlv->metric;
|
||||
msg.entry = entry;
|
||||
msg.prefix = dest;
|
||||
eigrp_fsm_event(&msg);
|
||||
|
||||
|
||||
eigrp_IPv4_InternalTLV_free(tlv);
|
||||
|
@ -78,14 +78,14 @@ void eigrp_siaquery_receive(struct eigrp *eigrp, struct ip *iph,
|
||||
while (s->endp > s->getp) {
|
||||
type = stream_getw(s);
|
||||
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));
|
||||
|
||||
tlv = eigrp_read_ipv4_tlv(s);
|
||||
|
||||
dest_addr.family = AFI_IP;
|
||||
dest_addr.prefix = tlv->destination;
|
||||
dest_addr.u.prefix4 = tlv->destination;
|
||||
dest_addr.prefixlen = tlv->prefix_length;
|
||||
struct eigrp_prefix_entry *dest =
|
||||
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
|
||||
* know)*/
|
||||
if (dest != NULL) {
|
||||
struct eigrp_fsm_action_message *msg;
|
||||
msg = XCALLOC(MTYPE_EIGRP_FSM_MSG,
|
||||
sizeof(struct
|
||||
eigrp_fsm_action_message));
|
||||
struct eigrp_fsm_action_message msg;
|
||||
struct eigrp_neighbor_entry *entry =
|
||||
eigrp_prefix_entry_lookup(dest->entries,
|
||||
nbr);
|
||||
msg->packet_type = EIGRP_OPC_SIAQUERY;
|
||||
msg->eigrp = eigrp;
|
||||
msg->data_type = EIGRP_TLV_IPv4_INT;
|
||||
msg->adv_router = nbr;
|
||||
msg->data.ipv4_int_type = tlv;
|
||||
msg->entry = entry;
|
||||
msg->prefix = dest;
|
||||
int event = eigrp_get_fsm_event(msg);
|
||||
eigrp_fsm_event(msg, event);
|
||||
msg.packet_type = EIGRP_OPC_SIAQUERY;
|
||||
msg.eigrp = eigrp;
|
||||
msg.data_type = EIGRP_INT;
|
||||
msg.adv_router = nbr;
|
||||
msg.metrics = tlv->metric;
|
||||
msg.entry = entry;
|
||||
msg.prefix = dest;
|
||||
eigrp_fsm_event(&msg);
|
||||
}
|
||||
eigrp_IPv4_InternalTLV_free(tlv);
|
||||
}
|
||||
|
@ -77,14 +77,14 @@ void eigrp_siareply_receive(struct eigrp *eigrp, struct ip *iph,
|
||||
while (s->endp > s->getp) {
|
||||
type = stream_getw(s);
|
||||
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));
|
||||
|
||||
tlv = eigrp_read_ipv4_tlv(s);
|
||||
|
||||
dest_addr.family = AFI_IP;
|
||||
dest_addr.prefix = tlv->destination;
|
||||
dest_addr.u.prefix4 = tlv->destination;
|
||||
dest_addr.prefixlen = tlv->prefix_length;
|
||||
struct eigrp_prefix_entry *dest =
|
||||
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
|
||||
* know)*/
|
||||
if (dest != NULL) {
|
||||
struct eigrp_fsm_action_message *msg;
|
||||
msg = XCALLOC(MTYPE_EIGRP_FSM_MSG,
|
||||
sizeof(struct
|
||||
eigrp_fsm_action_message));
|
||||
struct eigrp_fsm_action_message msg;
|
||||
struct eigrp_neighbor_entry *entry =
|
||||
eigrp_prefix_entry_lookup(dest->entries,
|
||||
nbr);
|
||||
msg->packet_type = EIGRP_OPC_SIAQUERY;
|
||||
msg->eigrp = eigrp;
|
||||
msg->data_type = EIGRP_TLV_IPv4_INT;
|
||||
msg->adv_router = nbr;
|
||||
msg->data.ipv4_int_type = tlv;
|
||||
msg->entry = entry;
|
||||
msg->prefix = dest;
|
||||
int event = eigrp_get_fsm_event(msg);
|
||||
eigrp_fsm_event(msg, event);
|
||||
msg.packet_type = EIGRP_OPC_SIAQUERY;
|
||||
msg.eigrp = eigrp;
|
||||
msg.data_type = EIGRP_INT;
|
||||
msg.adv_router = nbr;
|
||||
msg.metrics = tlv->metric;
|
||||
msg.entry = entry;
|
||||
msg.prefix = dest;
|
||||
eigrp_fsm_event(&msg);
|
||||
}
|
||||
eigrp_IPv4_InternalTLV_free(tlv);
|
||||
}
|
||||
|
@ -469,10 +469,7 @@ struct eigrp_prefix_entry {
|
||||
u_char af; // address family
|
||||
u_char req_action; // required action
|
||||
|
||||
struct prefix_ipv4
|
||||
*destination_ipv4; // pointer to struct with ipv4 address
|
||||
struct prefix_ipv6
|
||||
*destination_ipv6; // pointer to struct with ipv6 address
|
||||
struct prefix *destination;
|
||||
|
||||
// If network type is REMOTE_EXTERNAL, pointer will have reference to
|
||||
// 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 */
|
||||
|
||||
@ -508,11 +510,8 @@ struct eigrp_fsm_action_message {
|
||||
struct eigrp_neighbor *adv_router; // advertising neighbor
|
||||
struct eigrp_neighbor_entry *entry;
|
||||
struct eigrp_prefix_entry *prefix;
|
||||
int data_type; // internal or external tlv type
|
||||
union {
|
||||
struct TLV_IPv4_External_type *ipv4_ext_data;
|
||||
struct TLV_IPv4_Internal_type *ipv4_int_type;
|
||||
} data;
|
||||
msg_data_t data_type; // internal or external tlv type
|
||||
struct eigrp_metrics metrics;
|
||||
};
|
||||
|
||||
#endif /* _ZEBRA_EIGRP_STRUCTURES_H_ */
|
||||
|
@ -81,25 +81,18 @@ static int eigrp_prefix_entry_cmp(struct eigrp_prefix_entry *node1,
|
||||
{
|
||||
if (node1->af == AF_INET) {
|
||||
if (node2->af == AF_INET) {
|
||||
if (node1->destination_ipv4->prefix.s_addr
|
||||
< node2->destination_ipv4->prefix.s_addr) {
|
||||
return -1; // if it belong above node2
|
||||
} else {
|
||||
if (node1->destination_ipv4->prefix.s_addr
|
||||
> node2->destination_ipv4->prefix.s_addr) {
|
||||
return 1; // if it belongs under node2
|
||||
} else {
|
||||
return 0; // same value... ERROR...in
|
||||
// case of adding same prefix
|
||||
// again
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (node1->destination->u.prefix4.s_addr
|
||||
< node2->destination->u.prefix4.s_addr)
|
||||
return -1;
|
||||
if (node1->destination->u.prefix4.s_addr
|
||||
> node2->destination->u.prefix4.s_addr)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
} else
|
||||
return 1;
|
||||
} else
|
||||
return 1;
|
||||
}
|
||||
} else { // TODO check if the prefix dont exists
|
||||
return 1; // add to end
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@ -125,8 +118,7 @@ struct eigrp_prefix_entry *eigrp_prefix_entry_new()
|
||||
new->rij = list_new();
|
||||
new->entries->cmp = (int (*)(void *, void *))eigrp_neighbor_entry_cmp;
|
||||
new->distance = new->fdistance = new->rdistance = EIGRP_MAX_METRIC;
|
||||
new->destination_ipv4 = NULL;
|
||||
new->destination_ipv6 = NULL;
|
||||
new->destination = NULL;
|
||||
|
||||
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,
|
||||
struct eigrp_neighbor_entry *entry2)
|
||||
{
|
||||
if (entry1->distance
|
||||
< entry2->distance) // parameter used in list_add_sort ()
|
||||
return -1; // actually set to sort by distance
|
||||
if (entry1->distance < entry2->distance)
|
||||
return -1;
|
||||
if (entry1->distance > entry2->distance)
|
||||
return 1;
|
||||
|
||||
@ -205,7 +196,7 @@ void eigrp_neighbor_entry_add(struct eigrp_prefix_entry *node,
|
||||
listnode_add_sort(node->entries, entry);
|
||||
entry->prefix = node;
|
||||
|
||||
eigrp_zebra_route_add(node->destination_ipv4, l);
|
||||
eigrp_zebra_route_add(node->destination, l);
|
||||
}
|
||||
|
||||
list_delete(l);
|
||||
@ -230,7 +221,7 @@ void eigrp_prefix_entry_delete(struct list *topology,
|
||||
list_free(node->entries);
|
||||
list_free(node->rij);
|
||||
listnode_delete(topology, node);
|
||||
eigrp_zebra_route_delete(node->destination_ipv4);
|
||||
eigrp_zebra_route_delete(node->destination);
|
||||
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) {
|
||||
listnode_delete(node->entries, entry);
|
||||
eigrp_zebra_route_delete(node->destination_ipv4);
|
||||
eigrp_zebra_route_delete(node->destination);
|
||||
XFREE(MTYPE_EIGRP_NEIGHBOR_ENTRY, entry);
|
||||
}
|
||||
}
|
||||
@ -270,16 +261,12 @@ unsigned int eigrp_topology_table_isempty(struct list *topology)
|
||||
|
||||
struct eigrp_prefix_entry *
|
||||
eigrp_topology_table_lookup_ipv4(struct list *topology_table,
|
||||
struct prefix_ipv4 *address)
|
||||
struct prefix *address)
|
||||
{
|
||||
struct eigrp_prefix_entry *data;
|
||||
struct listnode *node;
|
||||
for (ALL_LIST_ELEMENTS_RO(topology_table, node, data)) {
|
||||
if ((data->af == AF_INET)
|
||||
&& (data->destination_ipv4->prefix.s_addr
|
||||
== address->prefix.s_addr)
|
||||
&& (data->destination_ipv4->prefixlen
|
||||
== address->prefixlen))
|
||||
if (prefix_same(data->destination, address))
|
||||
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_neighbor_entry *entry = msg->entry;
|
||||
enum metric_change change = METRIC_SAME;
|
||||
assert(entry);
|
||||
|
||||
struct TLV_IPv4_External_type *ext_data = NULL;
|
||||
struct TLV_IPv4_Internal_type *int_data = NULL;
|
||||
if (msg->data_type == EIGRP_TLV_IPv4_INT) {
|
||||
u_int32_t new_reported_distance;
|
||||
|
||||
int_data = msg->data.ipv4_int_type;
|
||||
if (eigrp_metrics_is_same(int_data->metric,
|
||||
assert(entry);
|
||||
|
||||
switch(msg->data_type) {
|
||||
case EIGRP_CONNECTED:
|
||||
if (prefix->nt == EIGRP_TOPOLOGY_TYPE_CONNECTED)
|
||||
return change;
|
||||
|
||||
change = METRIC_DECREASE;
|
||||
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)) {
|
||||
return change; // No change
|
||||
}
|
||||
|
||||
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;
|
||||
else
|
||||
goto distance_done;
|
||||
} else
|
||||
change = METRIC_DECREASE;
|
||||
|
||||
entry->reported_metric = int_data->metric;
|
||||
entry->reported_metric = msg->metrics;
|
||||
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);
|
||||
} else {
|
||||
ext_data = msg->data.ipv4_ext_data;
|
||||
if (eigrp_metrics_is_same(ext_data->metric,
|
||||
break;
|
||||
case EIGRP_EXT:
|
||||
if (prefix->nt == EIGRP_TOPOLOGY_TYPE_REMOTE_EXTERNAL) {
|
||||
if (eigrp_metrics_is_same(msg->metrics,
|
||||
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
|
||||
*/
|
||||
@ -464,13 +470,14 @@ void eigrp_update_routing_table(struct eigrp_prefix_entry *prefix)
|
||||
struct eigrp_neighbor_entry *entry;
|
||||
|
||||
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))
|
||||
entry->flags |= EIGRP_NEIGHBOR_ENTRY_INTABLE_FLAG;
|
||||
|
||||
list_delete(successors);
|
||||
} else {
|
||||
eigrp_zebra_route_delete(prefix->destination_ipv4);
|
||||
eigrp_zebra_route_delete(prefix->destination);
|
||||
for (ALL_LIST_ELEMENTS_RO(prefix->entries, node, entry))
|
||||
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(prefix->entries, node2, node22, entry)) {
|
||||
if (entry->adv_router == nbr) {
|
||||
struct eigrp_fsm_action_message *msg;
|
||||
msg = XCALLOC(MTYPE_EIGRP_FSM_MSG,
|
||||
sizeof(struct
|
||||
eigrp_fsm_action_message));
|
||||
struct TLV_IPv4_Internal_type *tlv =
|
||||
eigrp_IPv4_InternalTLV_new();
|
||||
tlv->metric.delay = EIGRP_MAX_METRIC;
|
||||
msg->packet_type = EIGRP_OPC_UPDATE;
|
||||
msg->eigrp = eigrp;
|
||||
msg->data_type = EIGRP_TLV_IPv4_INT;
|
||||
msg->adv_router = nbr;
|
||||
msg->data.ipv4_int_type = tlv;
|
||||
msg->entry = entry;
|
||||
msg->prefix = prefix;
|
||||
int event = eigrp_get_fsm_event(msg);
|
||||
eigrp_fsm_event(msg, event);
|
||||
}
|
||||
struct eigrp_fsm_action_message msg;
|
||||
|
||||
if (entry->adv_router != nbr)
|
||||
continue;
|
||||
|
||||
msg.metrics.delay = EIGRP_MAX_METRIC;
|
||||
msg.packet_type = EIGRP_OPC_UPDATE;
|
||||
msg.eigrp = eigrp;
|
||||
msg.data_type = EIGRP_INT;
|
||||
msg.adv_router = nbr;
|
||||
msg.entry = entry;
|
||||
msg.prefix = prefix;
|
||||
eigrp_fsm_event(&msg);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -49,7 +49,7 @@ extern void eigrp_neighbor_entry_delete(struct eigrp_prefix_entry *,
|
||||
extern void eigrp_topology_delete_all(struct list *);
|
||||
extern unsigned int eigrp_topology_table_isempty(struct list *);
|
||||
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_max(struct eigrp_prefix_entry *pe,
|
||||
|
@ -112,47 +112,31 @@ static void eigrp_update_receive_GR_ask(struct eigrp *eigrp,
|
||||
{
|
||||
struct listnode *node1;
|
||||
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 */
|
||||
for (ALL_LIST_ELEMENTS_RO(nbr_prefixes, node1, prefix)) {
|
||||
zlog_debug("GR receive: Neighbor not advertised %s/%d",
|
||||
inet_ntoa(prefix->destination_ipv4->prefix),
|
||||
prefix->destination_ipv4->prefixlen);
|
||||
char buffer[PREFIX_STRLEN];
|
||||
zlog_debug("GR receive: Neighbor not advertised %s",
|
||||
prefix2str(prefix->destination,
|
||||
buffer, PREFIX_STRLEN));
|
||||
|
||||
/* create internal IPv4 TLV with infinite delay */
|
||||
tlv_max = eigrp_IPv4_InternalTLV_new();
|
||||
tlv_max->type = EIGRP_TLV_IPv4_INT;
|
||||
tlv_max->length = 28U;
|
||||
tlv_max->metric = prefix->reported_metric;
|
||||
fsm_msg.metrics = prefix->reported_metric;
|
||||
/* set delay to MAX */
|
||||
tlv_max->metric.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));
|
||||
fsm_msg.metrics.delay = EIGRP_MAX_METRIC;
|
||||
|
||||
struct eigrp_neighbor_entry *entry =
|
||||
eigrp_prefix_entry_lookup(prefix->entries, nbr);
|
||||
|
||||
fsm_msg->packet_type = EIGRP_OPC_UPDATE;
|
||||
fsm_msg->eigrp = eigrp;
|
||||
fsm_msg->data_type = EIGRP_TLV_IPv4_INT;
|
||||
fsm_msg->adv_router = nbr;
|
||||
fsm_msg->data.ipv4_int_type = tlv_max;
|
||||
fsm_msg->entry = entry;
|
||||
fsm_msg->prefix = prefix;
|
||||
fsm_msg.packet_type = EIGRP_OPC_UPDATE;
|
||||
fsm_msg.eigrp = eigrp;
|
||||
fsm_msg.data_type = EIGRP_INT;
|
||||
fsm_msg.adv_router = nbr;
|
||||
fsm_msg.entry = entry;
|
||||
fsm_msg.prefix = prefix;
|
||||
|
||||
/* send message to FSM */
|
||||
int event = eigrp_get_fsm_event(fsm_msg);
|
||||
eigrp_fsm_event(fsm_msg, event);
|
||||
|
||||
/* free memory used by TLV */
|
||||
eigrp_IPv4_InternalTLV_free(tlv_max);
|
||||
eigrp_fsm_event(&fsm_msg);
|
||||
}
|
||||
}
|
||||
|
||||
@ -173,7 +157,7 @@ void eigrp_update_receive(struct eigrp *eigrp, struct ip *iph,
|
||||
u_char same;
|
||||
struct access_list *alist;
|
||||
struct prefix_list *plist;
|
||||
struct prefix_ipv4 dest_addr;
|
||||
struct prefix dest_addr;
|
||||
struct eigrp *e;
|
||||
u_char graceful_restart;
|
||||
u_char graceful_restart_final;
|
||||
@ -297,7 +281,7 @@ void eigrp_update_receive(struct eigrp *eigrp, struct ip *iph,
|
||||
|
||||
/*searching if destination exists */
|
||||
dest_addr.family = AF_INET;
|
||||
dest_addr.prefix = tlv->destination;
|
||||
dest_addr.u.prefix4 = tlv->destination;
|
||||
dest_addr.prefixlen = tlv->prefix_length;
|
||||
struct eigrp_prefix_entry *dest =
|
||||
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,
|
||||
dest);
|
||||
|
||||
struct eigrp_fsm_action_message *msg;
|
||||
msg = XCALLOC(MTYPE_EIGRP_FSM_MSG,
|
||||
sizeof(struct
|
||||
eigrp_fsm_action_message));
|
||||
struct eigrp_fsm_action_message msg;
|
||||
struct eigrp_neighbor_entry *entry =
|
||||
eigrp_prefix_entry_lookup(dest->entries,
|
||||
nbr);
|
||||
|
||||
msg->packet_type = EIGRP_OPC_UPDATE;
|
||||
msg->eigrp = eigrp;
|
||||
msg->data_type = EIGRP_TLV_IPv4_INT;
|
||||
msg->adv_router = nbr;
|
||||
msg->data.ipv4_int_type = tlv;
|
||||
msg->entry = entry;
|
||||
msg->prefix = dest;
|
||||
int event = eigrp_get_fsm_event(msg);
|
||||
eigrp_fsm_event(msg, event);
|
||||
msg.packet_type = EIGRP_OPC_UPDATE;
|
||||
msg.eigrp = eigrp;
|
||||
msg.data_type = EIGRP_INT;
|
||||
msg.adv_router = nbr;
|
||||
msg.metrics = tlv->metric;
|
||||
msg.entry = entry;
|
||||
msg.prefix = dest;
|
||||
eigrp_fsm_event(&msg);
|
||||
} else {
|
||||
/*Here comes topology information save*/
|
||||
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->destination = (struct prefix *)prefix_ipv4_new();
|
||||
prefix_copy(pe->destination,
|
||||
&dest_addr);
|
||||
pe->af = AF_INET;
|
||||
pe->state = EIGRP_FSM_STATE_PASSIVE;
|
||||
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 */
|
||||
if (alist
|
||||
&& access_list_apply(
|
||||
alist,
|
||||
(struct prefix *)&dest_addr)
|
||||
&& access_list_apply(alist,
|
||||
&dest_addr)
|
||||
== FILTER_DENY) {
|
||||
/* If yes, set reported metric to Max */
|
||||
ne->reported_metric.delay =
|
||||
@ -376,9 +354,8 @@ void eigrp_update_receive(struct eigrp *eigrp, struct ip *iph,
|
||||
|
||||
/* Check if prefix-list fits */
|
||||
if (plist
|
||||
&& prefix_list_apply(
|
||||
plist,
|
||||
(struct prefix *)&dest_addr)
|
||||
&& prefix_list_apply(plist,
|
||||
&dest_addr)
|
||||
== PREFIX_DENY) {
|
||||
/* If yes, set reported metric to Max */
|
||||
ne->reported_metric.delay =
|
||||
@ -390,9 +367,8 @@ void eigrp_update_receive(struct eigrp *eigrp, struct ip *iph,
|
||||
|
||||
/* Check if access-list fits */
|
||||
if (alist
|
||||
&& access_list_apply(
|
||||
alist,
|
||||
(struct prefix *)&dest_addr)
|
||||
&& access_list_apply(alist,
|
||||
&dest_addr)
|
||||
== FILTER_DENY) {
|
||||
/* If yes, set reported metric to Max */
|
||||
ne->reported_metric.delay =
|
||||
@ -403,9 +379,8 @@ void eigrp_update_receive(struct eigrp *eigrp, struct ip *iph,
|
||||
|
||||
/* Check if prefix-list fits */
|
||||
if (plist
|
||||
&& prefix_list_apply(
|
||||
plist,
|
||||
(struct prefix *)&dest_addr)
|
||||
&& prefix_list_apply(plist,
|
||||
&dest_addr)
|
||||
== PREFIX_DENY) {
|
||||
/* If yes, set reported metric to Max */
|
||||
ne->reported_metric.delay =
|
||||
@ -592,7 +567,7 @@ void eigrp_update_send_EOT(struct eigrp_neighbor *nbr)
|
||||
struct access_list *alist_i;
|
||||
struct prefix_list *plist_i;
|
||||
struct eigrp *e;
|
||||
struct prefix_ipv4 *dest_addr;
|
||||
struct prefix *dest_addr;
|
||||
u_int32_t seq_no = nbr->ei->eigrp->sequence_number;
|
||||
|
||||
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(pe->entries, node2, nnode2, te)) {
|
||||
if ((te->ei == nbr->ei)
|
||||
&& (te->prefix->nt == EIGRP_TOPOLOGY_TYPE_REMOTE))
|
||||
if (eigrp_nbr_split_horizon_check(te, nbr->ei))
|
||||
continue;
|
||||
|
||||
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 */
|
||||
dest_addr = pe->destination_ipv4;
|
||||
dest_addr = pe->destination;
|
||||
|
||||
/*
|
||||
* Filtering
|
||||
@ -648,13 +622,13 @@ void eigrp_update_send_EOT(struct eigrp_neighbor *nbr)
|
||||
/* Check if any list fits */
|
||||
if ((alist
|
||||
&& access_list_apply (alist,
|
||||
(struct prefix *) dest_addr) == FILTER_DENY)||
|
||||
dest_addr) == FILTER_DENY)||
|
||||
(plist && prefix_list_apply (plist,
|
||||
(struct prefix *) dest_addr) == PREFIX_DENY)||
|
||||
dest_addr) == PREFIX_DENY)||
|
||||
(alist_i && access_list_apply (alist_i,
|
||||
(struct prefix *) dest_addr) == FILTER_DENY)||
|
||||
dest_addr) == FILTER_DENY)||
|
||||
(plist_i && prefix_list_apply (plist_i,
|
||||
(struct prefix *) dest_addr) == PREFIX_DENY)) {
|
||||
dest_addr) == PREFIX_DENY)) {
|
||||
//pe->reported_metric.delay = EIGRP_MAX_METRIC;
|
||||
continue;
|
||||
} else {
|
||||
@ -678,7 +652,7 @@ void eigrp_update_send(struct eigrp_interface *ei)
|
||||
struct access_list *alist_i;
|
||||
struct prefix_list *plist_i;
|
||||
struct eigrp *e;
|
||||
struct prefix_ipv4 *dest_addr;
|
||||
struct prefix *dest_addr;
|
||||
u_int32_t seq_no = ei->eigrp->sequence_number;
|
||||
|
||||
if (ei->nbrs->count == 0)
|
||||
@ -701,10 +675,15 @@ void eigrp_update_send(struct eigrp_interface *ei)
|
||||
has_tlv = 0;
|
||||
for (ALL_LIST_ELEMENTS(ei->eigrp->topology_changes_internalIPV4, node,
|
||||
nnode, pe)) {
|
||||
struct eigrp_neighbor_entry *ne;
|
||||
|
||||
if (!(pe->req_action & EIGRP_FSM_NEED_UPDATE))
|
||||
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 ((IF_DEF_PARAMS(ei->ifp)->auth_type == EIGRP_AUTH_TYPE_MD5)
|
||||
&& (IF_DEF_PARAMS(ei->ifp)->auth_keychain != NULL)) {
|
||||
@ -731,7 +710,7 @@ void eigrp_update_send(struct eigrp_interface *ei)
|
||||
has_tlv = 0;
|
||||
}
|
||||
/* Get destination address from prefix */
|
||||
dest_addr = pe->destination_ipv4;
|
||||
dest_addr = pe->destination;
|
||||
|
||||
/*
|
||||
* Filtering
|
||||
@ -747,19 +726,19 @@ void eigrp_update_send(struct eigrp_interface *ei)
|
||||
/* Check if any list fits */
|
||||
if ((alist
|
||||
&& access_list_apply(alist,
|
||||
(struct prefix *)dest_addr)
|
||||
dest_addr)
|
||||
== FILTER_DENY)
|
||||
|| (plist
|
||||
&& prefix_list_apply(plist,
|
||||
(struct prefix *)dest_addr)
|
||||
dest_addr)
|
||||
== PREFIX_DENY)
|
||||
|| (alist_i
|
||||
&& access_list_apply(alist_i,
|
||||
(struct prefix *)dest_addr)
|
||||
dest_addr)
|
||||
== FILTER_DENY)
|
||||
|| (plist_i
|
||||
&& prefix_list_apply(plist_i,
|
||||
(struct prefix *)dest_addr)
|
||||
dest_addr)
|
||||
== PREFIX_DENY)) {
|
||||
// pe->reported_metric.delay = EIGRP_MAX_METRIC;
|
||||
continue;
|
||||
@ -841,14 +820,13 @@ static void eigrp_update_send_GR_part(struct eigrp_neighbor *nbr)
|
||||
u_int16_t length = EIGRP_HEADER_LEN;
|
||||
struct listnode *node, *nnode;
|
||||
struct eigrp_prefix_entry *pe;
|
||||
struct prefix_ipv4 *dest_addr;
|
||||
struct prefix *dest_addr;
|
||||
struct eigrp *e;
|
||||
struct access_list *alist, *alist_i;
|
||||
struct prefix_list *plist, *plist_i;
|
||||
struct list *prefixes;
|
||||
u_int32_t flags;
|
||||
unsigned int send_prefixes;
|
||||
struct TLV_IPv4_Internal_type *tlv_max;
|
||||
|
||||
/* get prefixes to send to neighbor */
|
||||
prefixes = nbr->nbr_gr_prefixes_send;
|
||||
@ -905,7 +883,7 @@ static void eigrp_update_send_GR_part(struct eigrp_neighbor *nbr)
|
||||
/*
|
||||
* Filtering
|
||||
*/
|
||||
dest_addr = pe->destination_ipv4;
|
||||
dest_addr = pe->destination;
|
||||
/* get list from eigrp process */
|
||||
e = eigrp_lookup();
|
||||
/* 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 */
|
||||
if ((alist
|
||||
&& access_list_apply(alist, (struct prefix *)dest_addr)
|
||||
&& access_list_apply(alist, dest_addr)
|
||||
== FILTER_DENY)
|
||||
|| (plist
|
||||
&& prefix_list_apply(plist, (struct prefix *)dest_addr)
|
||||
&& prefix_list_apply(plist, dest_addr)
|
||||
== PREFIX_DENY)
|
||||
|| (alist_i
|
||||
&& access_list_apply(alist_i,
|
||||
(struct prefix *)dest_addr)
|
||||
&& access_list_apply(alist_i, dest_addr)
|
||||
== FILTER_DENY)
|
||||
|| (plist_i
|
||||
&& prefix_list_apply(plist_i,
|
||||
(struct prefix *)dest_addr)
|
||||
&& prefix_list_apply(plist_i, dest_addr)
|
||||
== PREFIX_DENY)) {
|
||||
/* do not send filtered route */
|
||||
zlog_info("Filtered prefix %s won't be sent out.",
|
||||
inet_ntoa(dest_addr->prefix));
|
||||
inet_ntoa(dest_addr->u.prefix4));
|
||||
} else {
|
||||
/* sending route which wasn't filtered */
|
||||
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 */
|
||||
if ((alist
|
||||
&& access_list_apply(alist, (struct prefix *)dest_addr)
|
||||
&& access_list_apply(alist, dest_addr)
|
||||
== FILTER_DENY)
|
||||
|| (plist
|
||||
&& prefix_list_apply(plist, (struct prefix *)dest_addr)
|
||||
&& prefix_list_apply(plist, dest_addr)
|
||||
== PREFIX_DENY)
|
||||
|| (alist_i
|
||||
&& access_list_apply(alist_i,
|
||||
(struct prefix *)dest_addr)
|
||||
&& access_list_apply(alist_i, dest_addr)
|
||||
== FILTER_DENY)
|
||||
|| (plist_i
|
||||
&& prefix_list_apply(plist_i,
|
||||
(struct prefix *)dest_addr)
|
||||
&& prefix_list_apply(plist_i, dest_addr)
|
||||
== PREFIX_DENY)) {
|
||||
/* do not send filtered route */
|
||||
zlog_info("Filtered prefix %s will be removed.",
|
||||
inet_ntoa(dest_addr->prefix));
|
||||
|
||||
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;
|
||||
inet_ntoa(dest_addr->u.prefix4));
|
||||
|
||||
/* 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_fsm_action_message fsm_msg;
|
||||
|
||||
struct eigrp_neighbor_entry *entry =
|
||||
eigrp_prefix_entry_lookup(pe->entries, nbr);
|
||||
|
||||
fsm_msg->packet_type = EIGRP_OPC_UPDATE;
|
||||
fsm_msg->eigrp = e;
|
||||
fsm_msg->data_type = EIGRP_TLV_IPv4_INT;
|
||||
fsm_msg->adv_router = nbr;
|
||||
fsm_msg->data.ipv4_int_type = tlv_max;
|
||||
fsm_msg->entry = entry;
|
||||
fsm_msg->prefix = pe;
|
||||
fsm_msg.packet_type = EIGRP_OPC_UPDATE;
|
||||
fsm_msg.eigrp = e;
|
||||
fsm_msg.data_type = EIGRP_INT;
|
||||
fsm_msg.adv_router = nbr;
|
||||
fsm_msg.metrics = pe->reported_metric;
|
||||
/* Set delay to MAX */
|
||||
fsm_msg.metrics.delay = EIGRP_MAX_METRIC;
|
||||
fsm_msg.entry = entry;
|
||||
fsm_msg.prefix = pe;
|
||||
|
||||
/* send message to FSM */
|
||||
int event = eigrp_get_fsm_event(fsm_msg);
|
||||
eigrp_fsm_event(fsm_msg, event);
|
||||
|
||||
/* free memory used by TLV */
|
||||
eigrp_IPv4_InternalTLV_free(tlv_max);
|
||||
eigrp_fsm_event(&fsm_msg);
|
||||
}
|
||||
/*
|
||||
* End of filtering
|
||||
|
@ -391,10 +391,10 @@ DEFUN (eigrp_network,
|
||||
"EIGRP network prefix\n")
|
||||
{
|
||||
VTY_DECLVAR_CONTEXT(eigrp, eigrp);
|
||||
struct prefix_ipv4 p;
|
||||
struct prefix p;
|
||||
int ret;
|
||||
|
||||
str2prefix_ipv4(argv[1]->arg, &p);
|
||||
str2prefix(argv[1]->arg, &p);
|
||||
|
||||
ret = eigrp_network_set(eigrp, &p);
|
||||
|
||||
@ -414,10 +414,10 @@ DEFUN (no_eigrp_network,
|
||||
"EIGRP network prefix\n")
|
||||
{
|
||||
VTY_DECLVAR_CONTEXT(eigrp, eigrp);
|
||||
struct prefix_ipv4 p;
|
||||
struct prefix p;
|
||||
int ret;
|
||||
|
||||
str2prefix_ipv4(argv[2]->arg, &p);
|
||||
str2prefix(argv[2]->arg, &p);
|
||||
|
||||
ret = eigrp_network_unset(eigrp, &p);
|
||||
|
||||
|
@ -66,7 +66,7 @@ static int eigrp_interface_state_down(int, struct zclient *, zebra_size_t,
|
||||
vrf_id_t vrf_id);
|
||||
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);
|
||||
|
||||
/* Zebra structure to hold current status. */
|
||||
@ -112,59 +112,31 @@ void eigrp_zebra_init(void)
|
||||
zclient->interface_down = eigrp_interface_state_down;
|
||||
zclient->interface_address_add = eigrp_interface_address_add;
|
||||
zclient->interface_address_delete = eigrp_interface_address_delete;
|
||||
zclient->redistribute_route_ipv4_add = eigrp_zebra_read_ipv4;
|
||||
zclient->redistribute_route_ipv4_del = eigrp_zebra_read_ipv4;
|
||||
zclient->redistribute_route_add = eigrp_zebra_read_route;
|
||||
zclient->redistribute_route_del = eigrp_zebra_read_route;
|
||||
}
|
||||
|
||||
|
||||
/* 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)
|
||||
{
|
||||
struct stream *s;
|
||||
struct zapi_ipv4 api;
|
||||
struct prefix_ipv4 p;
|
||||
struct zapi_route api;
|
||||
struct eigrp *eigrp;
|
||||
|
||||
s = zclient->ibuf;
|
||||
if (zapi_route_decode(zclient->ibuf, &api) < 0)
|
||||
return -1;
|
||||
|
||||
/* Type, flags, message. */
|
||||
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)))
|
||||
if (IPV4_NET127(ntohl(api.prefix.u.prefix4.s_addr)))
|
||||
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();
|
||||
if (eigrp == NULL)
|
||||
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);
|
||||
}
|
||||
|
||||
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 listnode *node;
|
||||
u_char message;
|
||||
u_char flags;
|
||||
int psize;
|
||||
struct stream *s;
|
||||
int count = 0;
|
||||
|
||||
if (zclient->redist[AFI_IP][ZEBRA_ROUTE_EIGRP]) {
|
||||
message = 0;
|
||||
flags = 0;
|
||||
if (!zclient->redist[AFI_IP][ZEBRA_ROUTE_EIGRP])
|
||||
return;
|
||||
|
||||
/* EIGRP pass nexthop and metric */
|
||||
SET_FLAG(message, ZAPI_MESSAGE_NEXTHOP);
|
||||
memset(&api, 0, sizeof(api));
|
||||
api.vrf_id = VRF_DEFAULT;
|
||||
api.type = ZEBRA_ROUTE_EIGRP;
|
||||
api.safi = SAFI_UNICAST;
|
||||
memcpy(&api.prefix, p, sizeof(*p));
|
||||
|
||||
/* 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_EIGRP);
|
||||
stream_putw(s, 0);
|
||||
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, successors->count);
|
||||
SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
|
||||
api.nexthop_num = successors->count;
|
||||
|
||||
/* Nexthop, ifindex, distance and metric information. */
|
||||
for (ALL_LIST_ELEMENTS_RO(successors, node, te)) {
|
||||
api_nh = &api.nexthops[count];
|
||||
if (te->adv_router->src.s_addr) {
|
||||
stream_putc(s, NEXTHOP_TYPE_IPV4_IFINDEX);
|
||||
stream_put_in_addr(s, &te->adv_router->src);
|
||||
api_nh->gate.ipv4 = te->adv_router->src;
|
||||
api_nh->type = NEXTHOP_TYPE_IPV4_IFINDEX;
|
||||
} else
|
||||
stream_putc(s, NEXTHOP_TYPE_IFINDEX);
|
||||
stream_putl(s, te->ei->ifp->ifindex);
|
||||
api_nh->type = NEXTHOP_TYPE_IFINDEX;
|
||||
api_nh->ifindex = te->ei->ifp->ifindex;
|
||||
|
||||
count++;
|
||||
}
|
||||
|
||||
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])));
|
||||
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));
|
||||
}
|
||||
|
||||
stream_putw_at(s, 0, stream_get_endp(s));
|
||||
|
||||
zclient_send_message(zclient);
|
||||
}
|
||||
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])
|
||||
return;
|
||||
|
||||
memset(&api, 0, sizeof(api));
|
||||
api.vrf_id = VRF_DEFAULT;
|
||||
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);
|
||||
memcpy(&api.prefix, p, sizeof(*p));
|
||||
zclient_route_send(ZEBRA_ROUTE_DELETE, zclient, &api);
|
||||
|
||||
if (IS_DEBUG_EIGRP(zebra, ZEBRA_REDISTRIBUTE)) {
|
||||
char buf[2][INET_ADDRSTRLEN];
|
||||
zlog_debug("Zebra: Route del %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])));
|
||||
}
|
||||
char buf[PREFIX_STRLEN];
|
||||
zlog_debug("Zebra: Route del %s",
|
||||
prefix2str(p, buf, PREFIX_STRLEN));
|
||||
}
|
||||
|
||||
return;
|
||||
|
@ -33,8 +33,8 @@
|
||||
|
||||
extern void eigrp_zebra_init(void);
|
||||
|
||||
extern void eigrp_zebra_route_add(struct prefix_ipv4 *, struct list *);
|
||||
extern void eigrp_zebra_route_delete(struct prefix_ipv4 *);
|
||||
extern void eigrp_zebra_route_add(struct prefix *, struct list *);
|
||||
extern void eigrp_zebra_route_delete(struct prefix *);
|
||||
extern int eigrp_redistribute_set(struct eigrp *, int, struct eigrp_metrics);
|
||||
extern int eigrp_redistribute_unset(struct eigrp *, int);
|
||||
extern int eigrp_is_type_redistributed(int);
|
||||
|
@ -11,14 +11,28 @@ def run(cmd):
|
||||
proc.wait()
|
||||
return rv
|
||||
|
||||
clangfmt = run(['git', 'show', 'master:.clang-format'])
|
||||
|
||||
argp = argparse.ArgumentParser(description = 'git whitespace-fixing tool')
|
||||
argp.add_argument('branch', metavar='BRANCH', type = str, nargs = '?', default = 'HEAD')
|
||||
args = argp.parse_args()
|
||||
|
||||
branch = args.branch
|
||||
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()
|
||||
afterbase = run(['git', 'merge-base', commit, afterid]).strip()
|
||||
@ -28,10 +42,10 @@ if afterbase == afterid:
|
||||
sys.exit(1)
|
||||
|
||||
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)
|
||||
|
||||
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()
|
||||
|
||||
srcdir = os.getcwd()
|
||||
@ -39,9 +53,12 @@ tmpdir = tempfile.mkdtemp('frrindent')
|
||||
os.chdir(tmpdir)
|
||||
|
||||
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')
|
||||
|
||||
with open('.clang-format', 'w') as fd:
|
||||
fd.write(clangfmt)
|
||||
|
||||
prev = beforeid
|
||||
for rev in revs:
|
||||
filestat = run(['git', 'diff', '-z', '--name-status', prev, rev]).rstrip('\0').split('\0')
|
||||
|
@ -48,14 +48,15 @@
|
||||
extern struct zebra_privs_t isisd_privs;
|
||||
|
||||
struct bpf_insn llcfilter[] = {
|
||||
BPF_STMT(BPF_LD + BPF_B + BPF_ABS,
|
||||
ETHER_HDR_LEN), /* check first byte */
|
||||
/* 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_STMT(BPF_LD + BPF_B + BPF_ABS, ETHER_HDR_LEN + 1),
|
||||
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, ISO_SAP, 0,
|
||||
3), /* check second byte */
|
||||
BPF_STMT(BPF_LD + BPF_B + BPF_ABS, ETHER_HDR_LEN + 2),
|
||||
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 0x03, 0, 1), /* check third byte */
|
||||
/* check second byte */
|
||||
BPF_STMT(BPF_LD + BPF_B + BPF_ABS, ETH_ALEN + 1),
|
||||
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, ISO_SAP, 0, 3),
|
||||
/* 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, 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);
|
||||
|
||||
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 */
|
||||
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);
|
||||
|
||||
memcpy(ssnpa, readbuff + bpf_hdr->bh_hdrlen + ETH_ALEN,
|
||||
ETH_ALEN);
|
||||
memcpy(ssnpa, readbuff + bpf_hdr->bh_hdrlen + ETH_ALEN, ETH_ALEN);
|
||||
|
||||
if (ioctl(circuit->fd, BIOCFLUSH, &one) < 0)
|
||||
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;
|
||||
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)) {
|
||||
zlog_warn(
|
||||
"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
|
||||
*/
|
||||
sock_buff[ETHER_HDR_LEN] = ISO_SAP;
|
||||
sock_buff[ETHER_HDR_LEN + 1] = ISO_SAP;
|
||||
sock_buff[ETHER_HDR_LEN + 2] = 0x03;
|
||||
sock_buff[ETH_ALEN] = ISO_SAP;
|
||||
sock_buff[ETH_ALEN + 1] = ISO_SAP;
|
||||
sock_buff[ETH_ALEN + 2] = 0x03;
|
||||
|
||||
/* 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));
|
||||
|
||||
/* now we can send this */
|
||||
|
@ -181,7 +181,7 @@ DEFUN (no_isis_passive,
|
||||
|
||||
if (if_is_loopback(circuit->interface)) {
|
||||
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);
|
||||
@ -206,7 +206,7 @@ DEFUN (isis_circuit_type,
|
||||
is_type = string2circuit_t(argv[idx_level]->arg);
|
||||
if (!is_type) {
|
||||
vty_out(vty, "Unknown circuit-type \n");
|
||||
return CMD_ERR_AMBIGUOUS;
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
}
|
||||
|
||||
if (circuit->state == C_STATE_UP
|
||||
@ -214,7 +214,7 @@ DEFUN (isis_circuit_type,
|
||||
&& circuit->area->is_type != is_type) {
|
||||
vty_out(vty, "Invalid circuit level for area %s.\n",
|
||||
circuit->area->area_tag);
|
||||
return CMD_ERR_AMBIGUOUS;
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
}
|
||||
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)) {
|
||||
vty_out(vty,
|
||||
"isis network point-to-point is valid only on broadcast interfaces\n");
|
||||
return CMD_ERR_AMBIGUOUS;
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
}
|
||||
|
||||
return CMD_SUCCESS;
|
||||
@ -283,7 +283,7 @@ DEFUN (no_isis_network,
|
||||
if (isis_circuit_circ_type_set(circuit, CIRCUIT_T_BROADCAST)) {
|
||||
vty_out(vty,
|
||||
"isis network point-to-point is valid only on broadcast interfaces\n");
|
||||
return CMD_ERR_AMBIGUOUS;
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
}
|
||||
|
||||
return CMD_SUCCESS;
|
||||
@ -313,7 +313,7 @@ DEFUN (isis_passwd,
|
||||
argv[idx_word]->arg);
|
||||
if (rv) {
|
||||
vty_out(vty, "Too long circuit password (>254)\n");
|
||||
return CMD_ERR_AMBIGUOUS;
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
}
|
||||
|
||||
return CMD_SUCCESS;
|
||||
@ -355,7 +355,7 @@ DEFUN (isis_priority,
|
||||
prio = atoi(argv[idx_number]->arg);
|
||||
if (prio < MIN_PRIORITY || prio > MAX_PRIORITY) {
|
||||
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;
|
||||
@ -400,7 +400,7 @@ DEFUN (isis_priority_l1,
|
||||
prio = atoi(argv[idx_number]->arg);
|
||||
if (prio < MIN_PRIORITY || prio > MAX_PRIORITY) {
|
||||
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;
|
||||
@ -444,7 +444,7 @@ DEFUN (isis_priority_l2,
|
||||
prio = atoi(argv[idx_number]->arg);
|
||||
if (prio < MIN_PRIORITY || prio > MAX_PRIORITY) {
|
||||
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;
|
||||
@ -494,7 +494,7 @@ DEFUN (isis_metric,
|
||||
"Invalid metric %d - should be <0-63> "
|
||||
"when narrow metric type enabled\n",
|
||||
met);
|
||||
return CMD_ERR_AMBIGUOUS;
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
}
|
||||
|
||||
/* RFC4444 */
|
||||
@ -504,7 +504,7 @@ DEFUN (isis_metric,
|
||||
"Invalid metric %d - should be <0-16777215> "
|
||||
"when wide metric type enabled\n",
|
||||
met);
|
||||
return CMD_ERR_AMBIGUOUS;
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
}
|
||||
|
||||
isis_circuit_metric_set(circuit, IS_LEVEL_1, met);
|
||||
@ -554,7 +554,7 @@ DEFUN (isis_metric_l1,
|
||||
"Invalid metric %d - should be <0-63> "
|
||||
"when narrow metric type enabled\n",
|
||||
met);
|
||||
return CMD_ERR_AMBIGUOUS;
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
}
|
||||
|
||||
/* RFC4444 */
|
||||
@ -564,7 +564,7 @@ DEFUN (isis_metric_l1,
|
||||
"Invalid metric %d - should be <0-16777215> "
|
||||
"when wide metric type enabled\n",
|
||||
met);
|
||||
return CMD_ERR_AMBIGUOUS;
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
}
|
||||
|
||||
isis_circuit_metric_set(circuit, IS_LEVEL_1, met);
|
||||
@ -613,7 +613,7 @@ DEFUN (isis_metric_l2,
|
||||
"Invalid metric %d - should be <0-63> "
|
||||
"when narrow metric type enabled\n",
|
||||
met);
|
||||
return CMD_ERR_AMBIGUOUS;
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
}
|
||||
|
||||
/* RFC4444 */
|
||||
@ -623,7 +623,7 @@ DEFUN (isis_metric_l2,
|
||||
"Invalid metric %d - should be <0-16777215> "
|
||||
"when wide metric type enabled\n",
|
||||
met);
|
||||
return CMD_ERR_AMBIGUOUS;
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
}
|
||||
|
||||
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) {
|
||||
vty_out(vty, "Invalid hello-interval %d - should be <1-600>\n",
|
||||
interval);
|
||||
return CMD_ERR_AMBIGUOUS;
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
}
|
||||
|
||||
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) {
|
||||
vty_out(vty, "Invalid hello-interval %ld - should be <1-600>\n",
|
||||
interval);
|
||||
return CMD_ERR_AMBIGUOUS;
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
}
|
||||
|
||||
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) {
|
||||
vty_out(vty, "Invalid hello-interval %ld - should be <1-600>\n",
|
||||
interval);
|
||||
return CMD_ERR_AMBIGUOUS;
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
}
|
||||
|
||||
circuit->hello_interval[1] = (u_int16_t)interval;
|
||||
@ -806,7 +806,7 @@ DEFUN (isis_hello_multiplier,
|
||||
vty_out(vty,
|
||||
"Invalid hello-multiplier %d - should be <2-100>\n",
|
||||
mult);
|
||||
return CMD_ERR_AMBIGUOUS;
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
}
|
||||
|
||||
circuit->hello_multiplier[0] = (u_int16_t)mult;
|
||||
@ -854,7 +854,7 @@ DEFUN (isis_hello_multiplier_l1,
|
||||
vty_out(vty,
|
||||
"Invalid hello-multiplier %d - should be <2-100>\n",
|
||||
mult);
|
||||
return CMD_ERR_AMBIGUOUS;
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
}
|
||||
|
||||
circuit->hello_multiplier[0] = (u_int16_t)mult;
|
||||
@ -901,7 +901,7 @@ DEFUN (isis_hello_multiplier_l2,
|
||||
vty_out(vty,
|
||||
"Invalid hello-multiplier %d - should be <2-100>\n",
|
||||
mult);
|
||||
return CMD_ERR_AMBIGUOUS;
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
}
|
||||
|
||||
circuit->hello_multiplier[1] = (u_int16_t)mult;
|
||||
@ -979,7 +979,7 @@ DEFUN (csnp_interval,
|
||||
if (interval < MIN_CSNP_INTERVAL || interval > MAX_CSNP_INTERVAL) {
|
||||
vty_out(vty, "Invalid csnp-interval %lu - should be <1-600>\n",
|
||||
interval);
|
||||
return CMD_ERR_AMBIGUOUS;
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
}
|
||||
|
||||
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) {
|
||||
vty_out(vty, "Invalid csnp-interval %lu - should be <1-600>\n",
|
||||
interval);
|
||||
return CMD_ERR_AMBIGUOUS;
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
}
|
||||
|
||||
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) {
|
||||
vty_out(vty, "Invalid csnp-interval %lu - should be <1-600>\n",
|
||||
interval);
|
||||
return CMD_ERR_AMBIGUOUS;
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
}
|
||||
|
||||
circuit->csnp_interval[1] = (u_int16_t)interval;
|
||||
@ -1117,7 +1117,7 @@ DEFUN (psnp_interval,
|
||||
if (interval < MIN_PSNP_INTERVAL || interval > MAX_PSNP_INTERVAL) {
|
||||
vty_out(vty, "Invalid psnp-interval %lu - should be <1-120>\n",
|
||||
interval);
|
||||
return CMD_ERR_AMBIGUOUS;
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
}
|
||||
|
||||
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) {
|
||||
vty_out(vty, "Invalid psnp-interval %lu - should be <1-120>\n",
|
||||
interval);
|
||||
return CMD_ERR_AMBIGUOUS;
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
}
|
||||
|
||||
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) {
|
||||
vty_out(vty, "Invalid psnp-interval %lu - should be <1-120>\n",
|
||||
interval);
|
||||
return CMD_ERR_AMBIGUOUS;
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
}
|
||||
|
||||
circuit->psnp_interval[1] = (u_int16_t)interval;
|
||||
@ -1253,12 +1253,12 @@ DEFUN (circuit_topology,
|
||||
if (circuit->area && circuit->area->oldmetric) {
|
||||
vty_out(vty,
|
||||
"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) {
|
||||
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);
|
||||
@ -1281,12 +1281,12 @@ DEFUN (no_circuit_topology,
|
||||
if (circuit->area && circuit->area->oldmetric) {
|
||||
vty_out(vty,
|
||||
"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) {
|
||||
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);
|
||||
@ -1298,11 +1298,11 @@ static int validate_metric_style_narrow(struct vty *vty, struct isis_area *area)
|
||||
struct listnode *node;
|
||||
|
||||
if (!vty)
|
||||
return CMD_ERR_AMBIGUOUS;
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
|
||||
if (!area) {
|
||||
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)) {
|
||||
@ -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)) {
|
||||
vty_out(vty, "ISIS circuit %s metric is invalid\n",
|
||||
circuit->interface->name);
|
||||
return CMD_ERR_AMBIGUOUS;
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
}
|
||||
if ((area->is_type & IS_LEVEL_2)
|
||||
&& (circuit->is_type & IS_LEVEL_2)
|
||||
&& (circuit->te_metric[1] > MAX_NARROW_LINK_METRIC)) {
|
||||
vty_out(vty, "ISIS circuit %s metric is invalid\n",
|
||||
circuit->interface->name);
|
||||
return CMD_ERR_AMBIGUOUS;
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1345,7 +1345,7 @@ DEFUN (metric_style,
|
||||
if (area_is_mt(area)) {
|
||||
vty_out(vty,
|
||||
"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);
|
||||
@ -1373,7 +1373,7 @@ DEFUN (no_metric_style,
|
||||
if (area_is_mt(area)) {
|
||||
vty_out(vty,
|
||||
"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);
|
||||
@ -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",
|
||||
circuit->interface->name,
|
||||
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 "
|
||||
"the LSP refresh interval %us\n",
|
||||
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",
|
||||
refresh_interval,
|
||||
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 "
|
||||
"the configured LSP gen interval %us\n",
|
||||
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)) {
|
||||
vty_out(vty,
|
||||
"LSP refresh interval %us must be less than "
|
||||
"the configured LSP lifetime %us less 300\n",
|
||||
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) {
|
||||
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);
|
||||
|
@ -245,406 +245,131 @@ static int isis_zebra_link_params(int command, struct zclient *zclient,
|
||||
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)
|
||||
{
|
||||
u_char message;
|
||||
u_int32_t flags;
|
||||
int psize;
|
||||
struct stream *stream;
|
||||
struct zapi_route api;
|
||||
struct zapi_nexthop *api_nh;
|
||||
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;
|
||||
int i, size;
|
||||
struct listnode *node;
|
||||
struct prefix_ipv6 prefix6;
|
||||
int count = 0;
|
||||
|
||||
if (CHECK_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED))
|
||||
return;
|
||||
|
||||
memset(&api, 0, sizeof(api));
|
||||
api.vrf_id = VRF_DEFAULT;
|
||||
api.type = ZEBRA_ROUTE_ISIS;
|
||||
api.instance = 0;
|
||||
api.flags = 0;
|
||||
api.message = 0;
|
||||
api.safi = SAFI_UNICAST;
|
||||
api.prefix = *prefix;
|
||||
SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
|
||||
SET_FLAG(api.message, ZAPI_MESSAGE_IFINDEX);
|
||||
SET_FLAG(api.message, ZAPI_MESSAGE_METRIC);
|
||||
api.metric = route_info->cost;
|
||||
#if 0
|
||||
SET_FLAG(api.message, ZAPI_MESSAGE_DISTANCE);
|
||||
api.distance = route_info->depth;
|
||||
#endif
|
||||
api.nexthop_num = listcount(route_info->nexthops6);
|
||||
api.ifindex_num = listcount(route_info->nexthops6);
|
||||
|
||||
/* allocate memory for nexthop_list */
|
||||
size = sizeof(struct isis_nexthop6 *)
|
||||
* listcount(route_info->nexthops6);
|
||||
nexthop_list = (struct in6_addr **)XMALLOC(MTYPE_ISIS_TMP, size);
|
||||
if (!nexthop_list) {
|
||||
zlog_err("isis_zebra_add_route_ipv6: out of memory!");
|
||||
return;
|
||||
/* Nexthops */
|
||||
switch (prefix->family) {
|
||||
case AF_INET:
|
||||
for (ALL_LIST_ELEMENTS_RO(route_info->nexthops, node,
|
||||
nexthop)) {
|
||||
api_nh = &api.nexthops[count];
|
||||
/* FIXME: can it be ? */
|
||||
if (nexthop->ip.s_addr != INADDR_ANY) {
|
||||
api_nh->type = NEXTHOP_TYPE_IPV4_IFINDEX;
|
||||
api_nh->gate.ipv4 = nexthop->ip;
|
||||
} else {
|
||||
api_nh->type = NEXTHOP_TYPE_IFINDEX;
|
||||
}
|
||||
|
||||
/* 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_add_route_ipv6: out of memory!");
|
||||
XFREE(MTYPE_ISIS_TMP, nexthop_list);
|
||||
return;
|
||||
api_nh->ifindex = nexthop->ifindex;
|
||||
count++;
|
||||
}
|
||||
|
||||
/* for each nexthop */
|
||||
i = 0;
|
||||
for (ALL_LIST_ELEMENTS_RO(route_info->nexthops6, node, nexthop6)) {
|
||||
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)) {
|
||||
api.nexthop_num--;
|
||||
api.ifindex_num--;
|
||||
continue;
|
||||
}
|
||||
|
||||
nexthop_list[i] = &nexthop6->ip6;
|
||||
ifindex_list[i] = nexthop6->ifindex;
|
||||
i++;
|
||||
api_nh = &api.nexthops[count];
|
||||
api_nh->gate.ipv6 = nexthop6->ip6;
|
||||
api_nh->ifindex = nexthop6->ifindex;
|
||||
api_nh->type = NEXTHOP_TYPE_IPV6_IFINDEX;
|
||||
count++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (!count)
|
||||
return;
|
||||
|
||||
api.nexthop = nexthop_list;
|
||||
api.ifindex = ifindex_list;
|
||||
api.nexthop_num = count;
|
||||
|
||||
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_ADD, zclient, &prefix6, NULL,
|
||||
&api);
|
||||
zclient_route_send(ZEBRA_ROUTE_ADD, zclient, &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 zapi_ipv6 api;
|
||||
struct in6_addr **nexthop_list;
|
||||
ifindex_t *ifindex_list;
|
||||
struct isis_nexthop6 *nexthop6;
|
||||
int i, size;
|
||||
struct listnode *node;
|
||||
struct prefix_ipv6 prefix6;
|
||||
struct zapi_route api;
|
||||
|
||||
if (!CHECK_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED))
|
||||
return;
|
||||
|
||||
memset(&api, 0, sizeof(api));
|
||||
api.vrf_id = VRF_DEFAULT;
|
||||
api.type = ZEBRA_ROUTE_ISIS;
|
||||
api.instance = 0;
|
||||
api.flags = 0;
|
||||
api.message = 0;
|
||||
api.safi = SAFI_UNICAST;
|
||||
SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
|
||||
SET_FLAG(api.message, ZAPI_MESSAGE_IFINDEX);
|
||||
api.nexthop_num = listcount(route_info->nexthops6);
|
||||
api.ifindex_num = listcount(route_info->nexthops6);
|
||||
api.prefix = *prefix;
|
||||
|
||||
/* allocate memory for nexthop_list */
|
||||
size = sizeof(struct isis_nexthop6 *)
|
||||
* 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);
|
||||
zclient_route_send(ZEBRA_ROUTE_DELETE, zclient, &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,
|
||||
struct isis_route_info *route_info)
|
||||
{
|
||||
if (zclient->sock < 0)
|
||||
return;
|
||||
|
||||
if ((prefix->family == AF_INET
|
||||
&& !vrf_bitmap_check(zclient->redist[AFI_IP][ZEBRA_ROUTE_ISIS],
|
||||
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);
|
||||
if (CHECK_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ACTIVE))
|
||||
isis_zebra_route_add_route(prefix, route_info);
|
||||
else
|
||||
isis_redist_delete(api.type, p_generic);
|
||||
|
||||
return 0;
|
||||
isis_zebra_route_del_route(prefix, route_info);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
struct stream *stream;
|
||||
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));
|
||||
struct zapi_route api;
|
||||
|
||||
stream = zclient->ibuf;
|
||||
memset(&api, 0, sizeof(api));
|
||||
memset(&p, 0, sizeof(struct prefix_ipv6));
|
||||
memset(&nexthop, 0, sizeof(nexthop));
|
||||
ifindex = 0;
|
||||
if (zapi_route_decode(zclient->ibuf, &api) < 0)
|
||||
return -1;
|
||||
|
||||
api.type = stream_getc(stream);
|
||||
api.instance = stream_getw(stream);
|
||||
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. */
|
||||
if (CHECK_FLAG(api.message, ZAPI_MESSAGE_SRCPFX))
|
||||
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
|
||||
* 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_IPV6_ROUTE_DELETE;
|
||||
if (api.prefix.prefixlen == 0 && api.type == ZEBRA_ROUTE_ISIS)
|
||||
command = ZEBRA_REDISTRIBUTE_ROUTE_DEL;
|
||||
|
||||
if (command == ZEBRA_REDISTRIBUTE_IPV6_ADD)
|
||||
isis_redist_add(api.type, p_generic, api.distance, api.metric);
|
||||
if (command == ZEBRA_REDISTRIBUTE_ROUTE_ADD)
|
||||
isis_redist_add(api.type, &api.prefix, api.distance,
|
||||
api.metric);
|
||||
else
|
||||
isis_redist_delete(api.type, p_generic);
|
||||
isis_redist_delete(api.type, &api.prefix);
|
||||
|
||||
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_delete = isis_zebra_if_address_del;
|
||||
zclient->interface_link_params = isis_zebra_link_params;
|
||||
zclient->redistribute_route_ipv4_add = isis_zebra_read_ipv4;
|
||||
zclient->redistribute_route_ipv4_del = isis_zebra_read_ipv4;
|
||||
zclient->redistribute_route_ipv6_add = isis_zebra_read_ipv6;
|
||||
zclient->redistribute_route_ipv6_del = isis_zebra_read_ipv6;
|
||||
zclient->redistribute_route_add = isis_zebra_read;
|
||||
zclient->redistribute_route_del = isis_zebra_read;
|
||||
|
||||
return;
|
||||
}
|
||||
|
@ -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",
|
||||
addr->addr_len);
|
||||
XFREE(MTYPE_ISIS_AREA_ADDR, addr);
|
||||
return CMD_ERR_AMBIGUOUS;
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
}
|
||||
|
||||
if (addr->area_addr[addr->addr_len - 1] != 0) {
|
||||
vty_out(vty,
|
||||
"nsel byte (last byte) in area address must be 0\n");
|
||||
XFREE(MTYPE_ISIS_AREA_ADDR, addr);
|
||||
return CMD_ERR_AMBIGUOUS;
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
}
|
||||
|
||||
if (isis->sysid_set == 0) {
|
||||
@ -374,7 +374,7 @@ int area_net_title(struct vty *vty, const char *net_title)
|
||||
vty_out(vty,
|
||||
"System ID must not change when defining additional area addresses\n");
|
||||
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 */
|
||||
@ -419,7 +419,7 @@ int area_clear_net_title(struct vty *vty, const char *net_title)
|
||||
vty_out(vty,
|
||||
"Unsupported area address length %d, should be 8...20 \n",
|
||||
addr.addr_len);
|
||||
return CMD_ERR_AMBIGUOUS;
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
}
|
||||
|
||||
memcpy(addr.area_addr, buff, (int)addr.addr_len);
|
||||
@ -1260,8 +1260,8 @@ DEFUN (show_isis_spf_ietf,
|
||||
if (area->spf_timer[level - 1]) {
|
||||
struct timeval remain = thread_timer_remain(
|
||||
area->spf_timer[level - 1]);
|
||||
vty_out(vty, "Pending, due in %ld msec\n",
|
||||
remain.tv_sec * 1000
|
||||
vty_out(vty, "Pending, due in %lld msec\n",
|
||||
(long long)remain.tv_sec * 1000
|
||||
+ remain.tv_usec / 1000);
|
||||
} else {
|
||||
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);
|
||||
pos -= 4;
|
||||
if (strncmp(pos, ".", 1) != 0)
|
||||
return CMD_ERR_AMBIGUOUS;
|
||||
return CMD_WARNING;
|
||||
}
|
||||
if (strncmp(pos, ".", 1) == 0) {
|
||||
memcpy(number, ++pos, 2);
|
||||
@ -1570,16 +1570,16 @@ DEFUN (isis_topology,
|
||||
if (area->oldmetric) {
|
||||
vty_out(vty,
|
||||
"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) {
|
||||
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) {
|
||||
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);
|
||||
@ -1603,16 +1603,16 @@ DEFUN (no_isis_topology,
|
||||
if (area->oldmetric) {
|
||||
vty_out(vty,
|
||||
"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) {
|
||||
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) {
|
||||
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);
|
||||
|
105
ldpd/ldp_zebra.c
105
ldpd/ldp_zebra.c
@ -396,19 +396,34 @@ static int
|
||||
ldp_zebra_read_route(int command, struct zclient *zclient, zebra_size_t length,
|
||||
vrf_id_t vrf_id)
|
||||
{
|
||||
struct stream *s;
|
||||
u_char type;
|
||||
u_char message_flags;
|
||||
struct zapi_route api;
|
||||
struct zapi_nexthop *api_nh;
|
||||
struct kroute kr;
|
||||
int nhnum = 0, nhlen;
|
||||
size_t nhmark;
|
||||
int add = 0;
|
||||
int i, 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));
|
||||
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 (type) {
|
||||
switch (api.type) {
|
||||
case ZEBRA_ROUTE_CONNECT:
|
||||
kr.flags |= F_CONNECTED;
|
||||
break;
|
||||
@ -419,84 +434,38 @@ ldp_zebra_read_route(int command, struct zclient *zclient, zebra_size_t length,
|
||||
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) ||
|
||||
(kr.af == AF_INET6 && IN6_IS_SCOPE_EMBED(&kr.prefix.v6)))
|
||||
return (0);
|
||||
|
||||
if (kr.af == AF_INET6 &&
|
||||
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)
|
||||
if (command == ZEBRA_REDISTRIBUTE_ROUTE_ADD)
|
||||
add = 1;
|
||||
|
||||
if (nhnum == 0)
|
||||
if (api.nexthop_num == 0)
|
||||
debug_zebra_in("route %s %s/%d (%s)", (add) ? "add" : "delete",
|
||||
log_addr(kr.af, &kr.prefix), kr.prefixlen,
|
||||
zebra_route_string(type));
|
||||
zebra_route_string(api.type));
|
||||
|
||||
/* 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) {
|
||||
case AF_INET:
|
||||
kr.nexthop.v4.s_addr = stream_get_ipv4(s);
|
||||
kr.nexthop.v4 = api_nh->gate.ipv4;
|
||||
break;
|
||||
case AF_INET6:
|
||||
stream_get(&kr.nexthop.v6, s, sizeof(kr.nexthop.v6));
|
||||
kr.nexthop.v6 = api_nh->gate.ipv6;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
stream_getc(s); /* ifindex_num, unused. */
|
||||
kr.ifindex = stream_getl(s);
|
||||
kr.ifindex = api_nh->ifindex;;
|
||||
|
||||
debug_zebra_in("route %s %s/%d nexthop %s ifindex %u (%s)",
|
||||
(add) ? "add" : "delete", log_addr(kr.af, &kr.prefix),
|
||||
kr.prefixlen, log_addr(kr.af, &kr.nexthop), kr.ifindex,
|
||||
zebra_route_string(type));
|
||||
zebra_route_string(api.type));
|
||||
|
||||
if (add)
|
||||
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_address_add = ldp_interface_address_add;
|
||||
zclient->interface_address_delete = ldp_interface_address_delete;
|
||||
zclient->redistribute_route_ipv4_add = ldp_zebra_read_route;
|
||||
zclient->redistribute_route_ipv4_del = ldp_zebra_read_route;
|
||||
zclient->redistribute_route_ipv6_add = ldp_zebra_read_route;
|
||||
zclient->redistribute_route_ipv6_del = ldp_zebra_read_route;
|
||||
zclient->redistribute_route_add = ldp_zebra_read_route;
|
||||
zclient->redistribute_route_del = ldp_zebra_read_route;
|
||||
zclient->pw_status_update = ldp_zebra_read_pw_status_update;
|
||||
}
|
||||
|
||||
|
@ -42,6 +42,7 @@
|
||||
#include "command_graph.h"
|
||||
#include "qobj.h"
|
||||
#include "defaults.h"
|
||||
#include "libfrr.h"
|
||||
|
||||
DEFINE_MTYPE(LIB, HOST, "Host config")
|
||||
DEFINE_MTYPE(LIB, STRVEC, "String vector")
|
||||
@ -359,21 +360,23 @@ void install_element(enum node_type ntype, struct cmd_element *cmd)
|
||||
return;
|
||||
}
|
||||
|
||||
cnode = vector_slot(cmdvec, ntype);
|
||||
cnode = vector_lookup(cmdvec, ntype);
|
||||
|
||||
if (cnode == NULL) {
|
||||
fprintf(stderr,
|
||||
"Command node %d doesn't exist, please check it\n",
|
||||
ntype);
|
||||
fprintf(stderr,
|
||||
"Have you called install_node before this install_element?\n");
|
||||
"%s[%s]:\n"
|
||||
"\tnode %d (%s) does not exist.\n"
|
||||
"\tplease call install_node() before install_element()\n",
|
||||
cmd->name, cmd->string, ntype, node_names[ntype]);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (hash_lookup(cnode->cmd_hash, cmd) != NULL) {
|
||||
fprintf(stderr,
|
||||
"Multiple command installs to node %d of command:\n%s\n",
|
||||
ntype, cmd->string);
|
||||
"%s[%s]:\n"
|
||||
"\tnode %d (%s) already has this command installed.\n"
|
||||
"\tduplicate install_element call?\n",
|
||||
cmd->name, cmd->string, ntype, node_names[ntype]);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -406,21 +409,23 @@ void uninstall_element(enum node_type ntype, struct cmd_element *cmd)
|
||||
return;
|
||||
}
|
||||
|
||||
cnode = vector_slot(cmdvec, ntype);
|
||||
cnode = vector_lookup(cmdvec, ntype);
|
||||
|
||||
if (cnode == NULL) {
|
||||
fprintf(stderr,
|
||||
"Command node %d doesn't exist, please check it\n",
|
||||
ntype);
|
||||
fprintf(stderr,
|
||||
"Have you called install_node before this install_element?\n");
|
||||
"%s[%s]:\n"
|
||||
"\tnode %d (%s) does not exist.\n"
|
||||
"\tplease call install_node() before uninstall_element()\n",
|
||||
cmd->name, cmd->string, ntype, node_names[ntype]);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (hash_release(cnode->cmd_hash, cmd) == NULL) {
|
||||
fprintf(stderr,
|
||||
"Trying to uninstall non-installed command (node %d):\n%s\n",
|
||||
ntype, cmd->string);
|
||||
"%s[%s]:\n"
|
||||
"\tnode %d (%s) does not have this command installed.\n"
|
||||
"\tduplicate uninstall_element call?\n",
|
||||
cmd->name, cmd->string, ntype, node_names[ntype]);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -555,6 +560,9 @@ static int config_write_host(struct vty *vty)
|
||||
else if (!host.motd)
|
||||
vty_out(vty, "no banner motd\n");
|
||||
|
||||
if (debug_memstats_at_exit)
|
||||
vty_out(vty, "!\ndebug memstats-at-exit\n");
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -2366,6 +2374,17 @@ DEFUN (no_config_log_timestamp_precision,
|
||||
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 success = CMD_SUCCESS;
|
||||
@ -2527,6 +2546,7 @@ void cmd_init(int terminal)
|
||||
/* Each node's basic commands. */
|
||||
install_element(VIEW_NODE, &show_version_cmd);
|
||||
install_element(ENABLE_NODE, &show_startup_config_cmd);
|
||||
install_element(ENABLE_NODE, &debug_memstats_cmd);
|
||||
|
||||
if (terminal) {
|
||||
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, &no_hostname_cmd);
|
||||
install_element(CONFIG_NODE, &frr_version_defaults_cmd);
|
||||
install_element(CONFIG_NODE, &debug_memstats_cmd);
|
||||
|
||||
if (terminal > 0) {
|
||||
install_element(CONFIG_NODE, &password_cmd);
|
||||
|
@ -46,8 +46,9 @@ DEFINE_MTYPE_STATIC(LIB, CMD_MATCHSTACK, "Command Match Stack")
|
||||
static int add_nexthops(struct list *, struct graph_node *,
|
||||
struct graph_node **, size_t);
|
||||
|
||||
static struct list *command_match_r(struct graph_node *, vector, unsigned int,
|
||||
struct graph_node **);
|
||||
static enum matcher_rv command_match_r(struct graph_node *, vector,
|
||||
unsigned int, struct graph_node **,
|
||||
struct list **);
|
||||
|
||||
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);
|
||||
|
||||
/* matching functions */
|
||||
static enum matcher_rv matcher_rv;
|
||||
|
||||
enum matcher_rv command_match(struct graph *cmdgraph, vector vline,
|
||||
struct list **argv, const struct cmd_element **el)
|
||||
{
|
||||
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
|
||||
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;
|
||||
|
||||
struct graph_node *start = vector_slot(cmdgraph->nodes, 0);
|
||||
if ((*argv = command_match_r(start, vvline, 0,
|
||||
stack))) // successful match
|
||||
{
|
||||
status = command_match_r(start, vvline, 0, stack, argv);
|
||||
if (status == MATCHER_OK) { // successful match
|
||||
struct listnode *head = listhead(*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
|
||||
assert(*el);
|
||||
} else if (*argv) {
|
||||
del_arglist(*argv);
|
||||
*argv = NULL;
|
||||
}
|
||||
|
||||
if (!*el) {
|
||||
@ -129,7 +130,7 @@ enum matcher_rv command_match(struct graph *cmdgraph, vector vline,
|
||||
// free vector
|
||||
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.
|
||||
*/
|
||||
static struct list *command_match_r(struct graph_node *start, vector vline,
|
||||
unsigned int n, struct graph_node **stack)
|
||||
static enum matcher_rv command_match_r(struct graph_node *start, vector vline,
|
||||
unsigned int n,
|
||||
struct graph_node **stack,
|
||||
struct list **currbest)
|
||||
{
|
||||
assert(n < vector_active(vline));
|
||||
|
||||
enum matcher_rv status = MATCHER_NO_MATCH;
|
||||
|
||||
// get the minimum match level that can count as a full match
|
||||
struct cmd_token *token = start->data;
|
||||
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
|
||||
* circle in the graph (used for keyword arguments) */
|
||||
if (n == MAXDEPTH)
|
||||
return NULL;
|
||||
return MATCHER_NO_MATCH;
|
||||
if (!token->allowrepeat)
|
||||
for (size_t s = 0; s < n; s++)
|
||||
if (stack[s] == start)
|
||||
return NULL;
|
||||
return MATCHER_NO_MATCH;
|
||||
|
||||
// get the current operating input token
|
||||
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 (match_token(token, input_token) < minmatch)
|
||||
return NULL;
|
||||
return MATCHER_NO_MATCH;
|
||||
|
||||
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);
|
||||
|
||||
// determine the best match
|
||||
int ambiguous = 0;
|
||||
struct list *currbest = NULL;
|
||||
for (ALL_LIST_ELEMENTS_RO(next, ln, gn)) {
|
||||
// if we've matched all input we're looking for END_TKN
|
||||
if (n + 1 == vector_active(vline)) {
|
||||
struct cmd_token *tok = gn->data;
|
||||
if (tok->type == END_TKN) {
|
||||
if (currbest) // there is more than one END_TKN
|
||||
// in the follow set
|
||||
{
|
||||
ambiguous = 1;
|
||||
// if more than one END_TKN in the follow set
|
||||
if (*currbest) {
|
||||
status = MATCHER_AMBIGUOUS;
|
||||
break;
|
||||
} else {
|
||||
status = MATCHER_OK;
|
||||
}
|
||||
currbest = list_new();
|
||||
*currbest = list_new();
|
||||
// node should have one child node with the
|
||||
// element
|
||||
struct graph_node *leaf =
|
||||
vector_slot(gn->to, 0);
|
||||
// last node in the list will hold the
|
||||
// cmd_element;
|
||||
// this is important because list_delete()
|
||||
// expects
|
||||
// that all nodes have the same data type, so
|
||||
// when
|
||||
// deleting this list the last node must be
|
||||
// manually deleted
|
||||
// cmd_element; this is important because
|
||||
// list_delete() expects that all nodes have
|
||||
// the same data type, so when deleting this
|
||||
// list the last node must be manually deleted
|
||||
struct cmd_element *el = leaf->data;
|
||||
listnode_add(currbest, el);
|
||||
currbest->del =
|
||||
listnode_add(*currbest, el);
|
||||
(*currbest)->del =
|
||||
(void (*)(void *)) & cmd_token_del;
|
||||
// do not break immediately; continue walking
|
||||
// through the follow set
|
||||
// to ensure that there is exactly one END_TKN
|
||||
// through the follow set to ensure that there
|
||||
// is exactly one END_TKN
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// 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
|
||||
if (result && currbest) {
|
||||
if (result && *currbest) {
|
||||
// pick the best of two matches
|
||||
struct list *newbest =
|
||||
disambiguate(currbest, result, vline, n + 1);
|
||||
// set ambiguity flag
|
||||
ambiguous =
|
||||
!newbest || (ambiguous && newbest == currbest);
|
||||
disambiguate(*currbest, result, vline, n + 1);
|
||||
|
||||
// current best and result are ambiguous
|
||||
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
|
||||
struct list *todelete =
|
||||
((newbest && newbest == result) ? currbest
|
||||
((newbest && newbest == result) ? *currbest
|
||||
: result);
|
||||
del_arglist(todelete);
|
||||
|
||||
currbest = newbest ? newbest : currbest;
|
||||
} else if (result)
|
||||
currbest = result;
|
||||
*currbest = newbest ? newbest : *currbest;
|
||||
} else if (result) {
|
||||
status = rstat;
|
||||
*currbest = result;
|
||||
} else if (!*currbest) {
|
||||
status = MAX(rstat, status);
|
||||
}
|
||||
|
||||
if (currbest) {
|
||||
if (ambiguous) {
|
||||
del_arglist(currbest);
|
||||
currbest = NULL;
|
||||
matcher_rv = MATCHER_AMBIGUOUS;
|
||||
} else {
|
||||
}
|
||||
if (*currbest) {
|
||||
// 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)
|
||||
matcher_rv = MATCHER_INCOMPLETE;
|
||||
listnode_add_before(*currbest, (*currbest)->head, copy);
|
||||
} else if (n + 1 == vector_active(vline) && status == MATCHER_NO_MATCH)
|
||||
status = MATCHER_INCOMPLETE;
|
||||
|
||||
// cleanup
|
||||
list_delete(next);
|
||||
|
||||
return currbest;
|
||||
return status;
|
||||
}
|
||||
|
||||
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`
|
||||
*/
|
||||
|
||||
matcher_rv = idx == vector_active(vline) && next->count
|
||||
enum matcher_rv mrv = idx == vector_active(vline) && next->count
|
||||
? MATCHER_OK
|
||||
: MATCHER_NO_MATCH;
|
||||
|
||||
*completions = NULL;
|
||||
if (!MATCHER_ERROR(matcher_rv)) {
|
||||
if (!MATCHER_ERROR(mrv)) {
|
||||
// extract cmd_token into list
|
||||
*completions = list_new();
|
||||
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(next);
|
||||
|
||||
return matcher_rv;
|
||||
return mrv;
|
||||
}
|
||||
|
||||
/**
|
||||
|
81
lib/compiler.h
Normal file
81
lib/compiler.h
Normal 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 */
|
@ -404,7 +404,8 @@ DEFUN (grammar_findambig,
|
||||
nodegraph = cnode->cmdgraph;
|
||||
if (!nodegraph)
|
||||
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);
|
||||
|
35
lib/libfrr.c
35
lib/libfrr.c
@ -52,6 +52,8 @@ char frr_zclientpath[256];
|
||||
static char pidfile_default[256];
|
||||
static char vtypath_default[256];
|
||||
|
||||
bool debug_memstats_at_exit = 0;
|
||||
|
||||
static char comb_optstr[256];
|
||||
static struct option comb_lo[64];
|
||||
static struct option *comb_next_lo = &comb_lo[0];
|
||||
@ -639,7 +641,10 @@ static void frr_daemon_wait(int fd)
|
||||
exit(0);
|
||||
|
||||
/* 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,
|
||||
WEXITSTATUS(exitstat));
|
||||
else if (WIFSIGNALED(exitstat))
|
||||
@ -841,6 +846,10 @@ void frr_early_fini(void)
|
||||
|
||||
void frr_fini(void)
|
||||
{
|
||||
FILE *fp;
|
||||
char filename[128];
|
||||
int have_leftovers;
|
||||
|
||||
hook_call(frr_fini);
|
||||
|
||||
/* memory_init -> nothing needed */
|
||||
@ -851,4 +860,28 @@ void frr_fini(void)
|
||||
thread_master_free(master);
|
||||
closezlog();
|
||||
/* 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);
|
||||
}
|
||||
}
|
||||
|
@ -121,4 +121,6 @@ extern const char frr_moduledir[];
|
||||
extern char frr_protoname[];
|
||||
extern char frr_protonameinst[];
|
||||
|
||||
extern bool debug_memstats_at_exit;
|
||||
|
||||
#endif /* _ZEBRA_FRR_H */
|
||||
|
14
lib/log.c
14
lib/log.c
@ -701,7 +701,7 @@ void _zlog_assert_failed(const char *assertion, const char *file,
|
||||
assertion, file, line, (function ? function : "?"));
|
||||
zlog_backtrace(LOG_CRIT);
|
||||
zlog_thread_info(LOG_CRIT);
|
||||
log_memstats_stderr("log");
|
||||
log_memstats(stderr, "log");
|
||||
abort();
|
||||
}
|
||||
|
||||
@ -867,6 +867,8 @@ static const struct zebra_desc_table command_types[] = {
|
||||
DESC_ENTRY(ZEBRA_INTERFACE_UP),
|
||||
DESC_ENTRY(ZEBRA_INTERFACE_DOWN),
|
||||
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_DELETE),
|
||||
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_UPDATE),
|
||||
DESC_ENTRY(ZEBRA_BFD_DEST_REPLAY),
|
||||
DESC_ENTRY(ZEBRA_REDISTRIBUTE_IPV4_ADD),
|
||||
DESC_ENTRY(ZEBRA_REDISTRIBUTE_IPV4_DEL),
|
||||
DESC_ENTRY(ZEBRA_REDISTRIBUTE_IPV6_ADD),
|
||||
DESC_ENTRY(ZEBRA_REDISTRIBUTE_IPV6_DEL),
|
||||
DESC_ENTRY(ZEBRA_REDISTRIBUTE_ROUTE_ADD),
|
||||
DESC_ENTRY(ZEBRA_REDISTRIBUTE_ROUTE_DEL),
|
||||
DESC_ENTRY(ZEBRA_VRF_UNREGISTER),
|
||||
DESC_ENTRY(ZEBRA_VRF_ADD),
|
||||
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_MPLS_LABELS_ADD),
|
||||
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_LABEL_MANAGER_CONNECT),
|
||||
DESC_ENTRY(ZEBRA_GET_LABEL_CHUNK),
|
||||
|
10
lib/memory.c
10
lib/memory.c
@ -104,6 +104,7 @@ int qmem_walk(qmem_walk_fn *func, void *arg)
|
||||
}
|
||||
|
||||
struct exit_dump_args {
|
||||
FILE *fp;
|
||||
const char *prefix;
|
||||
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;
|
||||
|
||||
if (!mt) {
|
||||
fprintf(stderr,
|
||||
fprintf(eda->fp,
|
||||
"%s: showing active allocations in "
|
||||
"memory group %s\n",
|
||||
eda->prefix, mg->name);
|
||||
@ -122,15 +123,16 @@ static int qmem_exit_walker(void *arg, struct memgroup *mg, struct memtype *mt)
|
||||
char size[32];
|
||||
eda->error++;
|
||||
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,
|
||||
mt->size == SIZE_VAR ? "(variably sized)" : size);
|
||||
}
|
||||
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);
|
||||
return eda.error;
|
||||
}
|
||||
|
40
lib/memory.h
40
lib/memory.h
@ -18,7 +18,9 @@
|
||||
#define _QUAGGA_MEMORY_H
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <frratomic.h>
|
||||
#include "compiler.h"
|
||||
|
||||
#define array_size(ar) (sizeof(ar) / sizeof(ar[0]))
|
||||
|
||||
@ -36,41 +38,6 @@ struct memgroup {
|
||||
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:
|
||||
*
|
||||
* mydaemon.h
|
||||
@ -194,7 +161,8 @@ static inline size_t mtype_stats_alloc(struct memtype *mt)
|
||||
* last value from qmem_walk_fn. */
|
||||
typedef int qmem_walk_fn(void *arg, struct memgroup *mg, struct memtype *mt);
|
||||
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);
|
||||
|
||||
|
@ -42,8 +42,10 @@ static struct frrmod_info frrmod_default_info = {
|
||||
.description = "libfrr core module",
|
||||
};
|
||||
union _frrmod_runtime_u frrmod_default = {
|
||||
.r.info = &frrmod_default_info,
|
||||
.r.finished_loading = 1,
|
||||
.r = {
|
||||
.info = &frrmod_default_info,
|
||||
.finished_loading = 1,
|
||||
},
|
||||
};
|
||||
|
||||
// if defined(HAVE_SYS_WEAK_ALIAS_ATTRIBUTE)
|
||||
|
@ -44,6 +44,9 @@
|
||||
#define MPLS_DEFAULT_MIN_SRGB_LABEL 16000
|
||||
#define MPLS_DEFAULT_MAX_SRGB_LABEL 23999
|
||||
|
||||
/* Maximum # labels that can be pushed. */
|
||||
#define MPLS_MAX_LABELS 16
|
||||
|
||||
#define IS_MPLS_RESERVED_LABEL(label) \
|
||||
(label >= MPLS_MIN_RESERVED_LABEL && label <= MPLS_MAX_RESERVED_LABEL)
|
||||
|
||||
|
@ -122,6 +122,14 @@ const char *prefix_list_name(struct prefix_list *plist)
|
||||
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. */
|
||||
static struct prefix_list *prefix_list_lookup_do(afi_t afi, int orf,
|
||||
const char *name)
|
||||
|
@ -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 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 enum prefix_list_type prefix_list_apply(struct prefix_list *, void *);
|
||||
|
||||
|
@ -1263,5 +1263,6 @@ unsigned prefix_hash_key(void *pp)
|
||||
* padding and unused prefix bytes. */
|
||||
memset(©, 0, sizeof(copy));
|
||||
prefix_copy(©, (struct prefix *)pp);
|
||||
return jhash(©, sizeof(copy), 0x55aa5a5a);
|
||||
return jhash(©, offsetof(struct prefix, u.prefix)
|
||||
+ PSIZE(copy.prefixlen), 0x55aa5a5a);
|
||||
}
|
||||
|
19
lib/prefix.h
19
lib/prefix.h
@ -33,28 +33,13 @@
|
||||
#endif
|
||||
#include "sockunion.h"
|
||||
#include "ipaddr.h"
|
||||
#include "compiler.h"
|
||||
|
||||
#ifndef ETH_ALEN
|
||||
#define ETH_ALEN 6
|
||||
#endif
|
||||
|
||||
/* 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
|
||||
#undef ETHER_ADDR_LEN
|
||||
#endif
|
||||
@ -140,7 +125,7 @@ struct prefix {
|
||||
struct in_addr adv_router;
|
||||
} lp;
|
||||
struct ethaddr prefix_eth; /* AF_ETHERNET */
|
||||
u_char val[8];
|
||||
u_char val[16];
|
||||
uintptr_t ptr;
|
||||
struct evpn_addr prefix_evpn; /* AF_EVPN */
|
||||
} u __attribute__((aligned(8)));
|
||||
|
@ -245,7 +245,7 @@ core_handler(int signo
|
||||
#endif
|
||||
);
|
||||
/* dump memory stats on core */
|
||||
log_memstats_stderr("core_handler");
|
||||
log_memstats(stderr, "core_handler");
|
||||
abort();
|
||||
}
|
||||
|
||||
|
@ -226,8 +226,9 @@ void spf_backoff_show(struct spf_backoff *backoff, struct vty *vty,
|
||||
if (backoff->t_holddown) {
|
||||
struct timeval remain =
|
||||
thread_timer_remain(backoff->t_holddown);
|
||||
vty_out(vty, "%s Still runs for %ld msec\n",
|
||||
prefix, remain.tv_sec * 1000 + remain.tv_usec / 1000);
|
||||
vty_out(vty, "%s Still runs for %lld msec\n",
|
||||
prefix, (long long)remain.tv_sec * 1000
|
||||
+ remain.tv_usec / 1000);
|
||||
} else {
|
||||
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) {
|
||||
struct timeval remain =
|
||||
thread_timer_remain(backoff->t_timetolearn);
|
||||
vty_out(vty, "%s Still runs for %ld msec\n",
|
||||
prefix, remain.tv_sec * 1000 + remain.tv_usec / 1000);
|
||||
vty_out(vty, "%s Still runs for %lld msec\n",
|
||||
prefix, (long long)remain.tv_sec * 1000
|
||||
+ remain.tv_usec / 1000);
|
||||
} else {
|
||||
vty_out(vty, "%s Inactive\n", prefix);
|
||||
}
|
||||
|
@ -85,6 +85,7 @@ pkginclude_HEADERS += \
|
||||
lib/command.h \
|
||||
lib/command_graph.h \
|
||||
lib/command_match.h \
|
||||
lib/compiler.h \
|
||||
lib/csv.h \
|
||||
lib/distribute.h \
|
||||
lib/event_counter.h \
|
||||
|
@ -227,7 +227,7 @@ extern void route_table_iter_cleanup(route_table_iter_t *iter);
|
||||
/* Lock node. */
|
||||
static inline struct route_node *route_lock_node(struct route_node *node)
|
||||
{
|
||||
node->lock++;
|
||||
(*(unsigned *)&node->lock)++;
|
||||
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)
|
||||
{
|
||||
assert(node->lock > 0);
|
||||
node->lock--;
|
||||
(*(unsigned *)&node->lock)--;
|
||||
|
||||
if (node->lock == 0)
|
||||
route_node_delete(node);
|
||||
|
@ -31,48 +31,60 @@ struct ttable_style ttable_styles[] = {
|
||||
.corner = '+',
|
||||
.rownums_on = false,
|
||||
.indent = 1,
|
||||
.border.top = '-',
|
||||
.border.bottom = '-',
|
||||
.border.left = '|',
|
||||
.border.right = '|',
|
||||
.border.top_on = true,
|
||||
.border.bottom_on = true,
|
||||
.border.left_on = true,
|
||||
.border.right_on = true,
|
||||
.cell.lpad = 1,
|
||||
.cell.rpad = 1,
|
||||
.cell.align = LEFT,
|
||||
.cell.border.bottom = '-',
|
||||
.cell.border.bottom_on = true,
|
||||
.cell.border.top = '-',
|
||||
.cell.border.top_on = false,
|
||||
.cell.border.right = '|',
|
||||
.cell.border.right_on = true,
|
||||
.cell.border.left = '|',
|
||||
.cell.border.left_on = false,
|
||||
.border = {
|
||||
.top = '-',
|
||||
.bottom = '-',
|
||||
.left = '|',
|
||||
.right = '|',
|
||||
.top_on = true,
|
||||
.bottom_on = true,
|
||||
.left_on = true,
|
||||
.right_on = true,
|
||||
},
|
||||
.cell = {
|
||||
.lpad = 1,
|
||||
.rpad = 1,
|
||||
.align = LEFT,
|
||||
.border = {
|
||||
.bottom = '-',
|
||||
.bottom_on = true,
|
||||
.top = '-',
|
||||
.top_on = false,
|
||||
.right = '|',
|
||||
.right_on = true,
|
||||
.left = '|',
|
||||
.left_on = false,
|
||||
},
|
||||
},
|
||||
}, { // blank, suitable for plaintext alignment
|
||||
.corner = ' ',
|
||||
.rownums_on = false,
|
||||
.indent = 1,
|
||||
.border.top = ' ',
|
||||
.border.bottom = ' ',
|
||||
.border.left = ' ',
|
||||
.border.right = ' ',
|
||||
.border.top_on = false,
|
||||
.border.bottom_on = false,
|
||||
.border.left_on = false,
|
||||
.border.right_on = false,
|
||||
.cell.lpad = 0,
|
||||
.cell.rpad = 3,
|
||||
.cell.align = LEFT,
|
||||
.cell.border.bottom = ' ',
|
||||
.cell.border.bottom_on = false,
|
||||
.cell.border.top = ' ',
|
||||
.cell.border.top_on = false,
|
||||
.cell.border.right = ' ',
|
||||
.cell.border.right_on = false,
|
||||
.cell.border.left = ' ',
|
||||
.cell.border.left_on = false,
|
||||
.border = {
|
||||
.top = ' ',
|
||||
.bottom = ' ',
|
||||
.left = ' ',
|
||||
.right = ' ',
|
||||
.top_on = false,
|
||||
.bottom_on = false,
|
||||
.left_on = false,
|
||||
.right_on = false,
|
||||
},
|
||||
.cell = {
|
||||
.lpad = 0,
|
||||
.rpad = 3,
|
||||
.align = LEFT,
|
||||
.border = {
|
||||
.bottom = ' ',
|
||||
.bottom_on = false,
|
||||
.top = ' ',
|
||||
.top_on = false,
|
||||
.right = ' ',
|
||||
.right_on = false,
|
||||
.left = ' ',
|
||||
.left_on = false,
|
||||
},
|
||||
}
|
||||
}
|
||||
};
|
||||
/* clang-format on */
|
||||
|
19
lib/vty.h
19
lib/vty.h
@ -25,6 +25,7 @@
|
||||
#include "log.h"
|
||||
#include "sockunion.h"
|
||||
#include "qobj.h"
|
||||
#include "compiler.h"
|
||||
|
||||
#define VTY_BUFSIZ 4096
|
||||
#define VTY_MAXHIST 20
|
||||
@ -182,23 +183,11 @@ struct vty_arg {
|
||||
/* Integrated configuration file. */
|
||||
#define INTEGRATE_DEFAULT_CONFIG "frr.conf"
|
||||
|
||||
/* 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)
|
||||
#if CONFDATE > 20180401
|
||||
CPP_NOTICE("It's probably time to remove VTY_NEWLINE compatibility foo.")
|
||||
#endif
|
||||
|
||||
/* for compatibility */
|
||||
#define VNL "\n" CPP_WARN("VNL 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.")
|
||||
|
265
lib/zclient.c
265
lib/zclient.c
@ -352,10 +352,6 @@ void zclient_send_reg_requests(struct zclient *zclient, vrf_id_t vrf_id)
|
||||
int i;
|
||||
afi_t afi;
|
||||
|
||||
/* zclient is disabled. */
|
||||
if (!zclient->enable)
|
||||
return;
|
||||
|
||||
/* If not connected to the zebra yet. */
|
||||
if (zclient->sock < 0)
|
||||
return;
|
||||
@ -418,10 +414,6 @@ void zclient_send_dereg_requests(struct zclient *zclient, vrf_id_t vrf_id)
|
||||
int i;
|
||||
afi_t afi;
|
||||
|
||||
/* zclient is disabled. */
|
||||
if (!zclient->enable)
|
||||
return;
|
||||
|
||||
/* If not connected to the zebra yet. */
|
||||
if (zclient->sock < 0)
|
||||
return;
|
||||
@ -485,10 +477,6 @@ void zclient_send_interface_radv_req(struct zclient *zclient, vrf_id_t vrf_id,
|
||||
{
|
||||
struct stream *s;
|
||||
|
||||
/* zclient is disabled. */
|
||||
if (!zclient->enable)
|
||||
return;
|
||||
|
||||
/* If not connected to the zebra yet. */
|
||||
if (zclient->sock < 0)
|
||||
return;
|
||||
@ -516,10 +504,6 @@ int zclient_start(struct zclient *zclient)
|
||||
if (zclient_debug)
|
||||
zlog_info("zclient_start is called");
|
||||
|
||||
/* zclient is disabled. */
|
||||
if (!zclient->enable)
|
||||
return 0;
|
||||
|
||||
/* If already connected to the zebra. */
|
||||
if (zclient->sock >= 0)
|
||||
return 0;
|
||||
@ -564,9 +548,6 @@ void zclient_init(struct zclient *zclient, int redist_default, u_short instance)
|
||||
{
|
||||
int afi, i;
|
||||
|
||||
/* Enable zebra client connection by default. */
|
||||
zclient->enable = 1;
|
||||
|
||||
/* Set -1 to the default socket value. */
|
||||
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);
|
||||
}
|
||||
|
||||
int zapi_route(u_char cmd, struct zclient *zclient, struct prefix *p,
|
||||
struct prefix_ipv6 *src_p, struct zapi_route *api)
|
||||
int zclient_route_send(u_char cmd, struct zclient *zclient,
|
||||
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 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);
|
||||
|
||||
zclient_create_header(s, cmd, api->vrf_id);
|
||||
|
||||
/* Put type and nexthop. */
|
||||
stream_putc(s, api->type);
|
||||
stream_putw(s, api->instance);
|
||||
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);
|
||||
|
||||
/* Put prefix information. */
|
||||
psize = PSIZE(p->prefixlen);
|
||||
stream_putc(s, p->prefixlen);
|
||||
stream_write(s, (u_char *)&p->u.prefix, psize);
|
||||
stream_putc(s, api->prefix.family);
|
||||
psize = PSIZE(api->prefix.prefixlen);
|
||||
stream_putc(s, api->prefix.prefixlen);
|
||||
stream_write(s, (u_char *)&api->prefix.u.prefix, psize);
|
||||
|
||||
if (CHECK_FLAG(api->message, ZAPI_MESSAGE_SRCPFX)) {
|
||||
psize = PSIZE(src_p->prefixlen);
|
||||
stream_putc(s, src_p->prefixlen);
|
||||
stream_write(s, (u_char *)&src_p->prefix, psize);
|
||||
psize = PSIZE(api->src_prefix.prefixlen);
|
||||
stream_putc(s, api->src_prefix.prefixlen);
|
||||
stream_write(s, (u_char *)&api->src_prefix.prefix, psize);
|
||||
}
|
||||
|
||||
/* Nexthop, ifindex, distance and metric information. */
|
||||
/* Nexthops. */
|
||||
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++) {
|
||||
stream_putc(s, api->nexthop[i]->type);
|
||||
switch (api->nexthop[i]->type) {
|
||||
api_nh = &api->nexthops[i];
|
||||
|
||||
stream_putc(s, api_nh->type);
|
||||
switch (api_nh->type) {
|
||||
case NEXTHOP_TYPE_BLACKHOLE:
|
||||
break;
|
||||
case NEXTHOP_TYPE_IPV4:
|
||||
stream_put_in_addr(s,
|
||||
&api->nexthop[i]->gate.ipv4);
|
||||
|
||||
/* For labeled-unicast, each nexthop is followed
|
||||
* by label. */
|
||||
if (CHECK_FLAG(api->message,
|
||||
ZAPI_MESSAGE_LABEL))
|
||||
stream_putl(
|
||||
s,
|
||||
api->nexthop[i]
|
||||
->nh_label->label[0]);
|
||||
stream_put_in_addr(s, &api_nh->gate.ipv4);
|
||||
break;
|
||||
case NEXTHOP_TYPE_IPV4_IFINDEX:
|
||||
stream_put_in_addr(s,
|
||||
&api->nexthop[i]->gate.ipv4);
|
||||
stream_putl(s, api->nexthop[i]->ifindex);
|
||||
stream_put_in_addr(s, &api_nh->gate.ipv4);
|
||||
stream_putl(s, api_nh->ifindex);
|
||||
break;
|
||||
case NEXTHOP_TYPE_IFINDEX:
|
||||
stream_putl(s, api->nexthop[i]->ifindex);
|
||||
stream_putl(s, api_nh->ifindex);
|
||||
break;
|
||||
case NEXTHOP_TYPE_IPV6:
|
||||
stream_write(
|
||||
s,
|
||||
(u_char *)&api->nexthop[i]->gate.ipv6,
|
||||
stream_write(s, (u_char *)&api_nh->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;
|
||||
case NEXTHOP_TYPE_IPV6_IFINDEX:
|
||||
stream_write(
|
||||
s,
|
||||
(u_char *)&api->nexthop[i]->gate.ipv6,
|
||||
stream_write(s, (u_char *)&api_nh->gate.ipv6,
|
||||
16);
|
||||
stream_putl(s, api->nexthop[i]->ifindex);
|
||||
stream_putl(s, api_nh->ifindex);
|
||||
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))
|
||||
stream_putc(s, api->distance);
|
||||
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. */
|
||||
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,
|
||||
vrf_id);
|
||||
break;
|
||||
case ZEBRA_REDISTRIBUTE_IPV4_ADD:
|
||||
if (zclient->redistribute_route_ipv4_add)
|
||||
(*zclient->redistribute_route_ipv4_add)(
|
||||
command, zclient, length, vrf_id);
|
||||
case ZEBRA_REDISTRIBUTE_ROUTE_ADD:
|
||||
if (zclient->redistribute_route_add)
|
||||
(*zclient->redistribute_route_add)(command, zclient,
|
||||
length, vrf_id);
|
||||
break;
|
||||
case ZEBRA_REDISTRIBUTE_IPV4_DEL:
|
||||
if (zclient->redistribute_route_ipv4_del)
|
||||
(*zclient->redistribute_route_ipv4_del)(
|
||||
command, zclient, 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);
|
||||
case ZEBRA_REDISTRIBUTE_ROUTE_DEL:
|
||||
if (zclient->redistribute_route_del)
|
||||
(*zclient->redistribute_route_del)(command, zclient,
|
||||
length, vrf_id);
|
||||
break;
|
||||
case ZEBRA_INTERFACE_LINK_PARAMS:
|
||||
if (zclient->interface_link_params)
|
||||
|
@ -21,7 +21,7 @@
|
||||
#ifndef _ZEBRA_ZCLIENT_H
|
||||
#define _ZEBRA_ZCLIENT_H
|
||||
|
||||
/* For struct zapi_ipv{4,6}. */
|
||||
/* For struct zapi_route. */
|
||||
#include "prefix.h"
|
||||
|
||||
/* For struct interface and struct connected. */
|
||||
@ -59,6 +59,8 @@ typedef enum {
|
||||
ZEBRA_INTERFACE_UP,
|
||||
ZEBRA_INTERFACE_DOWN,
|
||||
ZEBRA_INTERFACE_SET_MASTER,
|
||||
ZEBRA_ROUTE_ADD,
|
||||
ZEBRA_ROUTE_DELETE,
|
||||
ZEBRA_IPV4_ROUTE_ADD,
|
||||
ZEBRA_IPV4_ROUTE_DELETE,
|
||||
ZEBRA_IPV6_ROUTE_ADD,
|
||||
@ -85,10 +87,8 @@ typedef enum {
|
||||
ZEBRA_BFD_DEST_DEREGISTER,
|
||||
ZEBRA_BFD_DEST_UPDATE,
|
||||
ZEBRA_BFD_DEST_REPLAY,
|
||||
ZEBRA_REDISTRIBUTE_IPV4_ADD,
|
||||
ZEBRA_REDISTRIBUTE_IPV4_DEL,
|
||||
ZEBRA_REDISTRIBUTE_IPV6_ADD,
|
||||
ZEBRA_REDISTRIBUTE_IPV6_DEL,
|
||||
ZEBRA_REDISTRIBUTE_ROUTE_ADD,
|
||||
ZEBRA_REDISTRIBUTE_ROUTE_DEL,
|
||||
ZEBRA_VRF_UNREGISTER,
|
||||
ZEBRA_VRF_ADD,
|
||||
ZEBRA_VRF_DELETE,
|
||||
@ -100,10 +100,6 @@ typedef enum {
|
||||
ZEBRA_INTERFACE_LINK_PARAMS,
|
||||
ZEBRA_MPLS_LABELS_ADD,
|
||||
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_LABEL_MANAGER_CONNECT,
|
||||
ZEBRA_GET_LABEL_CHUNK,
|
||||
@ -141,10 +137,6 @@ struct zclient {
|
||||
/* Socket to zebra daemon. */
|
||||
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. */
|
||||
int fail;
|
||||
|
||||
@ -194,13 +186,9 @@ struct zclient {
|
||||
int (*nexthop_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 (*redistribute_route_ipv4_add)(int, struct zclient *, uint16_t,
|
||||
int (*redistribute_route_add)(int, struct zclient *, uint16_t,
|
||||
vrf_id_t);
|
||||
int (*redistribute_route_ipv4_del)(int, struct zclient *, uint16_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,
|
||||
int (*redistribute_route_del)(int, struct zclient *, uint16_t,
|
||||
vrf_id_t);
|
||||
int (*fec_update)(int, struct zclient *, uint16_t);
|
||||
int (*local_vni_add)(int, struct zclient *, uint16_t, vrf_id_t);
|
||||
@ -212,13 +200,12 @@ struct zclient {
|
||||
|
||||
/* Zebra API message flag. */
|
||||
#define ZAPI_MESSAGE_NEXTHOP 0x01
|
||||
#define ZAPI_MESSAGE_IFINDEX 0x02
|
||||
#define ZAPI_MESSAGE_DISTANCE 0x04
|
||||
#define ZAPI_MESSAGE_METRIC 0x08
|
||||
#define ZAPI_MESSAGE_TAG 0x10
|
||||
#define ZAPI_MESSAGE_MTU 0x20
|
||||
#define ZAPI_MESSAGE_SRCPFX 0x40
|
||||
#define ZAPI_MESSAGE_LABEL 0x80
|
||||
#define ZAPI_MESSAGE_DISTANCE 0x02
|
||||
#define ZAPI_MESSAGE_METRIC 0x04
|
||||
#define ZAPI_MESSAGE_TAG 0x08
|
||||
#define ZAPI_MESSAGE_MTU 0x10
|
||||
#define ZAPI_MESSAGE_SRCPFX 0x20
|
||||
#define ZAPI_MESSAGE_LABEL 0x40
|
||||
|
||||
/* Zserv protocol message header */
|
||||
struct zserv_header {
|
||||
@ -232,6 +219,16 @@ struct zserv_header {
|
||||
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 {
|
||||
u_char type;
|
||||
u_short instance;
|
||||
@ -242,8 +239,11 @@ struct zapi_route {
|
||||
|
||||
safi_t safi;
|
||||
|
||||
u_char nexthop_num;
|
||||
struct nexthop **nexthop;
|
||||
struct prefix prefix;
|
||||
struct prefix_ipv6 src_prefix;
|
||||
|
||||
u_int16_t nexthop_num;
|
||||
struct zapi_nexthop nexthops[MULTIPATH_NUM];
|
||||
|
||||
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_router_id_update_read(struct stream *s, struct prefix *rid);
|
||||
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 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,
|
||||
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 *,
|
||||
struct prefix_ipv4 *,
|
||||
struct zapi_ipv6 *);
|
||||
extern int zapi_route(u_char cmd, struct zclient *zclient, struct prefix *p,
|
||||
struct prefix_ipv6 *src_p, struct zapi_route *api);
|
||||
struct zapi_ipv6 *)
|
||||
__attribute__((deprecated));
|
||||
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 */
|
||||
|
@ -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)
|
||||
{
|
||||
int flags = 0;
|
||||
struct zapi_route api;
|
||||
struct zapi_nexthop *api_nh;
|
||||
|
||||
if (zclient->sock < 0)
|
||||
return;
|
||||
|
||||
memset(&api, 0, sizeof(api));
|
||||
api.type = ZEBRA_ROUTE_NHRP;
|
||||
api.safi = SAFI_UNICAST;
|
||||
api.prefix = *p;
|
||||
|
||||
switch (type) {
|
||||
case NHRP_CACHE_NEGATIVE:
|
||||
SET_FLAG(flags, ZEBRA_FLAG_REJECT);
|
||||
SET_FLAG(api.flags, ZEBRA_FLAG_REJECT);
|
||||
break;
|
||||
case NHRP_CACHE_DYNAMIC:
|
||||
case NHRP_CACHE_NHS:
|
||||
@ -102,30 +108,42 @@ void nhrp_route_announce(int add, enum nhrp_cache_type type, const struct prefix
|
||||
* to other routing daemons */
|
||||
break;
|
||||
default:
|
||||
SET_FLAG(flags, ZEBRA_FLAG_FIB_OVERRIDE);
|
||||
SET_FLAG(api.flags, ZEBRA_FLAG_FIB_OVERRIDE);
|
||||
break;
|
||||
}
|
||||
SET_FLAG(flags, ZEBRA_FLAG_INTERNAL);
|
||||
|
||||
if (p->family == AF_INET) {
|
||||
struct in_addr *nexthop_ipv4;
|
||||
struct zapi_ipv4 api;
|
||||
|
||||
memset(&api, 0, sizeof(api));
|
||||
api.flags = flags;
|
||||
api.type = ZEBRA_ROUTE_NHRP;
|
||||
api.safi = SAFI_UNICAST;
|
||||
SET_FLAG(api.flags, ZEBRA_FLAG_INTERNAL);
|
||||
|
||||
SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
|
||||
if (nexthop) {
|
||||
nexthop_ipv4 = (struct in_addr *) sockunion_get_addr(nexthop);
|
||||
api.nexthop_num = 1;
|
||||
api.nexthop = &nexthop_ipv4;
|
||||
api_nh = &api.nexthops[0];
|
||||
|
||||
switch (api.prefix.family) {
|
||||
case AF_INET:
|
||||
if (nexthop) {
|
||||
api_nh->gate.ipv4 = nexthop->sin.sin_addr;
|
||||
api_nh->type = NEXTHOP_TYPE_IPV4;
|
||||
}
|
||||
if (ifp) {
|
||||
SET_FLAG(api.message, ZAPI_MESSAGE_IFINDEX);
|
||||
api.ifindex_num = 1;
|
||||
api.ifindex = &ifp->ifindex;
|
||||
api_nh->ifindex = ifp->ifindex;
|
||||
if (api_nh->type == NEXTHOP_TYPE_IPV4)
|
||||
api_nh->type = NEXTHOP_TYPE_IPV4_IFINDEX;
|
||||
else
|
||||
api_nh->type = NEXTHOP_TYPE_IFINDEX;
|
||||
}
|
||||
break;
|
||||
case AF_INET6:
|
||||
if (nexthop) {
|
||||
api_nh->gate.ipv6 = nexthop->sin6.sin6_addr;
|
||||
api_nh->type = NEXTHOP_TYPE_IPV6;
|
||||
}
|
||||
if (ifp) {
|
||||
api_nh->ifindex = ifp->ifindex;
|
||||
if (api_nh->type == NEXTHOP_TYPE_IPV6)
|
||||
api_nh->type = NEXTHOP_TYPE_IPV6_IFINDEX;
|
||||
else
|
||||
api_nh->type = NEXTHOP_TYPE_IFINDEX;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (mtu) {
|
||||
SET_FLAG(api.message, ZAPI_MESSAGE_MTU);
|
||||
@ -133,127 +151,63 @@ void nhrp_route_announce(int add, enum nhrp_cache_type type, const struct prefix
|
||||
}
|
||||
|
||||
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"
|
||||
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",
|
||||
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>",
|
||||
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);
|
||||
}
|
||||
|
||||
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) {
|
||||
nexthop_ipv6 = (struct in6_addr *) sockunion_get_addr(nexthop);
|
||||
api.nexthop_num = 1;
|
||||
api.nexthop = &nexthop_ipv6;
|
||||
}
|
||||
if (ifp) {
|
||||
SET_FLAG(api.message, ZAPI_MESSAGE_IFINDEX);
|
||||
api.ifindex_num = 1;
|
||||
api.ifindex = &ifp->ifindex;
|
||||
}
|
||||
if (mtu) {
|
||||
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);
|
||||
}
|
||||
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)
|
||||
{
|
||||
struct stream *s;
|
||||
struct zapi_route api;
|
||||
struct zapi_nexthop *api_nh;
|
||||
struct interface *ifp = NULL;
|
||||
struct prefix prefix;
|
||||
union sockunion nexthop_addr;
|
||||
unsigned char message, nexthop_num, ifindex_num;
|
||||
unsigned ifindex;
|
||||
char buf[2][PREFIX_STRLEN];
|
||||
int i, afaddrlen, added;
|
||||
int added;
|
||||
|
||||
s = zclient->ibuf;
|
||||
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:
|
||||
if (zapi_route_decode(zclient->ibuf, &api) < 0)
|
||||
return -1;
|
||||
}
|
||||
afaddrlen = family2addrsize(prefix.family);
|
||||
prefix.prefixlen = stream_getc(s);
|
||||
stream_get(&prefix.u.val, s, PSIZE(prefix.prefixlen));
|
||||
|
||||
/* Nexthop, ifindex, distance, metric. */
|
||||
if (CHECK_FLAG(message, ZAPI_MESSAGE_NEXTHOP|ZAPI_MESSAGE_IFINDEX)) {
|
||||
nexthop_num = stream_getc(s);
|
||||
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);
|
||||
/* we completely ignore srcdest routes for now. */
|
||||
if (CHECK_FLAG(api.message, ZAPI_MESSAGE_SRCPFX))
|
||||
return 0;
|
||||
|
||||
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",
|
||||
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]),
|
||||
ifp ? ifp->name : "(none)");
|
||||
|
||||
nhrp_route_update_zebra(&prefix, &nexthop_addr, ifp);
|
||||
nhrp_shortcut_prefix_change(&prefix, !added);
|
||||
nhrp_route_update_zebra(&api.prefix, &nexthop_addr, ifp);
|
||||
nhrp_shortcut_prefix_change(&api.prefix, !added);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -366,10 +320,8 @@ void nhrp_zebra_init(void)
|
||||
zclient->interface_down = nhrp_interface_down;
|
||||
zclient->interface_address_add = nhrp_interface_address_add;
|
||||
zclient->interface_address_delete = nhrp_interface_address_delete;
|
||||
zclient->redistribute_route_ipv4_add = nhrp_route_read;
|
||||
zclient->redistribute_route_ipv4_del = nhrp_route_read;
|
||||
zclient->redistribute_route_ipv6_add = nhrp_route_read;
|
||||
zclient->redistribute_route_ipv6_del = nhrp_route_read;
|
||||
zclient->redistribute_route_add = nhrp_route_read;
|
||||
zclient->redistribute_route_del = nhrp_route_read;
|
||||
|
||||
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_IP6]);
|
||||
}
|
||||
|
||||
|
@ -386,14 +386,8 @@ int ospf6_abr_originate_summary_to_area(struct ospf6_route *route,
|
||||
}
|
||||
|
||||
/* Check filter-list */
|
||||
if (PREFIX_NAME_OUT(area)) {
|
||||
if (PREFIX_LIST_OUT(area) == NULL)
|
||||
PREFIX_LIST_OUT(area) = prefix_list_lookup(
|
||||
AFI_IP6, PREFIX_NAME_OUT(area));
|
||||
|
||||
if (PREFIX_LIST_OUT(area))
|
||||
if (prefix_list_apply(PREFIX_LIST_OUT(area),
|
||||
&route->prefix)
|
||||
if (prefix_list_apply(PREFIX_LIST_OUT(area), &route->prefix)
|
||||
!= PREFIX_PERMIT) {
|
||||
if (is_debug) {
|
||||
inet_ntop(AF_INET,
|
||||
@ -406,7 +400,6 @@ int ospf6_abr_originate_summary_to_area(struct ospf6_route *route,
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* the route is going to be originated. store it in area's summary_table
|
||||
*/
|
||||
@ -873,11 +866,6 @@ void ospf6_abr_examin_summary(struct ospf6_lsa *lsa, struct ospf6_area *oa)
|
||||
}
|
||||
|
||||
/* Check input prefix-list */
|
||||
if (PREFIX_NAME_IN(oa)) {
|
||||
if (PREFIX_LIST_IN(oa) == NULL)
|
||||
PREFIX_LIST_IN(oa) =
|
||||
prefix_list_lookup(AFI_IP6, PREFIX_NAME_IN(oa));
|
||||
|
||||
if (PREFIX_LIST_IN(oa))
|
||||
if (prefix_list_apply(PREFIX_LIST_IN(oa), &prefix)
|
||||
!= PREFIX_PERMIT) {
|
||||
@ -888,7 +876,6 @@ void ospf6_abr_examin_summary(struct ospf6_lsa *lsa, struct ospf6_area *oa)
|
||||
ospf6_route_remove(old, table);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* (5),(6): the path preference is handled by the sorting
|
||||
in the routing table. Always install the path by substituting
|
||||
|
@ -45,6 +45,8 @@
|
||||
#include "ospf6_asbr.h"
|
||||
#include "ospf6d.h"
|
||||
|
||||
DEFINE_MTYPE_STATIC(OSPF6D, OSPF6_PLISTNAME, "Prefix list name")
|
||||
|
||||
int ospf6_area_cmp(void *va, void *vb)
|
||||
{
|
||||
struct ospf6_area *oa = (struct ospf6_area *)va;
|
||||
@ -579,17 +581,15 @@ DEFUN (area_filter_list,
|
||||
plist = prefix_list_lookup(AFI_IP6, plistname);
|
||||
if (strmatch(inout, "in")) {
|
||||
PREFIX_LIST_IN(area) = plist;
|
||||
if (PREFIX_NAME_IN(area))
|
||||
free(PREFIX_NAME_IN(area));
|
||||
|
||||
PREFIX_NAME_IN(area) = strdup(plistname);
|
||||
XFREE(MTYPE_OSPF6_PLISTNAME, PREFIX_NAME_IN(area));
|
||||
PREFIX_NAME_IN(area) = XSTRDUP(MTYPE_OSPF6_PLISTNAME,
|
||||
plistname);
|
||||
ospf6_abr_reimport(area);
|
||||
} else {
|
||||
PREFIX_LIST_OUT(area) = plist;
|
||||
if (PREFIX_NAME_OUT(area))
|
||||
free(PREFIX_NAME_OUT(area));
|
||||
|
||||
PREFIX_NAME_OUT(area) = strdup(plistname);
|
||||
XFREE(MTYPE_OSPF6_PLISTNAME, PREFIX_NAME_OUT(area));
|
||||
PREFIX_NAME_OUT(area) = XSTRDUP(MTYPE_OSPF6_PLISTNAME,
|
||||
plistname);
|
||||
ospf6_abr_enable_area(area);
|
||||
}
|
||||
|
||||
@ -622,27 +622,34 @@ DEFUN (no_area_filter_list,
|
||||
return CMD_SUCCESS;
|
||||
|
||||
PREFIX_LIST_IN(area) = NULL;
|
||||
if (PREFIX_NAME_IN(area))
|
||||
free(PREFIX_NAME_IN(area));
|
||||
|
||||
PREFIX_NAME_IN(area) = NULL;
|
||||
XFREE(MTYPE_OSPF6_PLISTNAME, PREFIX_NAME_IN(area));
|
||||
ospf6_abr_reimport(area);
|
||||
} else {
|
||||
if (PREFIX_NAME_OUT(area))
|
||||
if (!strmatch(PREFIX_NAME_OUT(area), plistname))
|
||||
return CMD_SUCCESS;
|
||||
|
||||
PREFIX_LIST_OUT(area) = NULL;
|
||||
if (PREFIX_NAME_OUT(area))
|
||||
free(PREFIX_NAME_OUT(area));
|
||||
|
||||
PREFIX_NAME_OUT(area) = NULL;
|
||||
XFREE(MTYPE_OSPF6_PLISTNAME, PREFIX_NAME_OUT(area));
|
||||
ospf6_abr_enable_area(area);
|
||||
}
|
||||
|
||||
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,
|
||||
area_import_list_cmd,
|
||||
"area A.B.C.D import-list NAME",
|
||||
|
@ -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_plist_update(struct prefix_list *plist, int add);
|
||||
extern void ospf6_area_config_write(struct vty *vty);
|
||||
extern void ospf6_area_init(void);
|
||||
|
||||
|
@ -1171,8 +1171,7 @@ DEFUN (ipv6_ospf6_cost,
|
||||
IP6_STR
|
||||
OSPF6_STR
|
||||
"Interface cost\n"
|
||||
"Outgoing metric of this interface\n"
|
||||
)
|
||||
"Outgoing metric of this interface\n")
|
||||
{
|
||||
VTY_DECLVAR_CONTEXT(interface, ifp);
|
||||
int idx_number = 3;
|
||||
@ -1206,12 +1205,12 @@ DEFUN (ipv6_ospf6_cost,
|
||||
|
||||
DEFUN (no_ipv6_ospf6_cost,
|
||||
no_ipv6_ospf6_cost_cmd,
|
||||
"no ipv6 ospf6 cost",
|
||||
"no ipv6 ospf6 cost [(1-65535)]",
|
||||
NO_STR
|
||||
IP6_STR
|
||||
OSPF6_STR
|
||||
"Calculate interface cost from bandwidth\n"
|
||||
)
|
||||
"Outgoing metric of this interface\n")
|
||||
{
|
||||
VTY_DECLVAR_CONTEXT(interface, ifp);
|
||||
struct ospf6_interface *oi;
|
||||
@ -1292,8 +1291,7 @@ DEFUN (ipv6_ospf6_hellointerval,
|
||||
IP6_STR
|
||||
OSPF6_STR
|
||||
"Time between HELLO packets\n"
|
||||
SECONDS_STR
|
||||
)
|
||||
SECONDS_STR)
|
||||
{
|
||||
VTY_DECLVAR_CONTEXT(interface, ifp);
|
||||
int idx_number = 3;
|
||||
@ -1305,10 +1303,21 @@ DEFUN (ipv6_ospf6_hellointerval,
|
||||
oi = ospf6_interface_create(ifp);
|
||||
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;
|
||||
}
|
||||
|
||||
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 */
|
||||
DEFUN (ipv6_ospf6_deadinterval,
|
||||
ipv6_ospf6_deadinterval_cmd,
|
||||
@ -1316,8 +1325,7 @@ DEFUN (ipv6_ospf6_deadinterval,
|
||||
IP6_STR
|
||||
OSPF6_STR
|
||||
"Interval time after which a neighbor is declared down\n"
|
||||
SECONDS_STR
|
||||
)
|
||||
SECONDS_STR)
|
||||
{
|
||||
VTY_DECLVAR_CONTEXT(interface, ifp);
|
||||
int idx_number = 3;
|
||||
@ -1329,10 +1337,21 @@ DEFUN (ipv6_ospf6_deadinterval,
|
||||
oi = ospf6_interface_create(ifp);
|
||||
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;
|
||||
}
|
||||
|
||||
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 */
|
||||
DEFUN (ipv6_ospf6_transmitdelay,
|
||||
ipv6_ospf6_transmitdelay_cmd,
|
||||
@ -1352,10 +1371,21 @@ DEFUN (ipv6_ospf6_transmitdelay,
|
||||
oi = ospf6_interface_create(ifp);
|
||||
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;
|
||||
}
|
||||
|
||||
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 */
|
||||
DEFUN (ipv6_ospf6_retransmitinterval,
|
||||
ipv6_ospf6_retransmitinterval_cmd,
|
||||
@ -1363,8 +1393,7 @@ DEFUN (ipv6_ospf6_retransmitinterval,
|
||||
IP6_STR
|
||||
OSPF6_STR
|
||||
"Time between retransmitting lost link state advertisements\n"
|
||||
SECONDS_STR
|
||||
)
|
||||
SECONDS_STR)
|
||||
{
|
||||
VTY_DECLVAR_CONTEXT(interface, ifp);
|
||||
int idx_number = 3;
|
||||
@ -1376,10 +1405,21 @@ DEFUN (ipv6_ospf6_retransmitinterval,
|
||||
oi = ospf6_interface_create(ifp);
|
||||
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;
|
||||
}
|
||||
|
||||
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 */
|
||||
DEFUN (ipv6_ospf6_priority,
|
||||
ipv6_ospf6_priority_cmd,
|
||||
@ -1387,8 +1427,7 @@ DEFUN (ipv6_ospf6_priority,
|
||||
IP6_STR
|
||||
OSPF6_STR
|
||||
"Router priority\n"
|
||||
"Priority value\n"
|
||||
)
|
||||
"Priority value\n")
|
||||
{
|
||||
VTY_DECLVAR_CONTEXT(interface, ifp);
|
||||
int idx_number = 3;
|
||||
@ -1400,7 +1439,9 @@ DEFUN (ipv6_ospf6_priority,
|
||||
oi = ospf6_interface_create(ifp);
|
||||
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
|
||||
|| oi->state == OSPF6_INTERFACE_BDR
|
||||
@ -1410,14 +1451,22 @@ DEFUN (ipv6_ospf6_priority,
|
||||
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,
|
||||
ipv6_ospf6_instance_cmd,
|
||||
"ipv6 ospf6 instance-id (0-255)",
|
||||
IP6_STR
|
||||
OSPF6_STR
|
||||
"Instance ID for this interface\n"
|
||||
"Instance ID value\n"
|
||||
)
|
||||
"Instance ID value\n")
|
||||
{
|
||||
VTY_DECLVAR_CONTEXT(interface, ifp);
|
||||
int idx_number = 3;
|
||||
@ -1429,10 +1478,21 @@ DEFUN (ipv6_ospf6_instance,
|
||||
oi = ospf6_interface_create(ifp);
|
||||
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;
|
||||
}
|
||||
|
||||
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,
|
||||
ipv6_ospf6_passive_cmd,
|
||||
"ipv6 ospf6 passive",
|
||||
@ -1576,13 +1636,13 @@ DEFUN (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",
|
||||
"no ipv6 ospf6 advertise prefix-list [WORD]",
|
||||
NO_STR
|
||||
IP6_STR
|
||||
OSPF6_STR
|
||||
"Advertising options\n"
|
||||
"Filter prefix using prefix-list\n"
|
||||
)
|
||||
"Prefix list name\n")
|
||||
{
|
||||
VTY_DECLVAR_CONTEXT(interface, ifp);
|
||||
struct ospf6_interface *oi;
|
||||
@ -1593,10 +1653,8 @@ DEFUN (no_ipv6_ospf6_advertise_prefix_list,
|
||||
oi = ospf6_interface_create(ifp);
|
||||
assert(oi);
|
||||
|
||||
if (oi->plist_name) {
|
||||
if (oi->plist_name)
|
||||
XFREE(MTYPE_CFG_PLIST_NAME, oi->plist_name);
|
||||
oi->plist_name = NULL;
|
||||
}
|
||||
|
||||
ospf6_interface_connected_route_update(oi->interface);
|
||||
|
||||
@ -1654,11 +1712,13 @@ DEFUN (ipv6_ospf6_network,
|
||||
|
||||
DEFUN (no_ipv6_ospf6_network,
|
||||
no_ipv6_ospf6_network_cmd,
|
||||
"no ipv6 ospf6 network",
|
||||
"no ipv6 ospf6 network [<broadcast|point-to-point>]",
|
||||
NO_STR
|
||||
IP6_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);
|
||||
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, &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_hellointerval_cmd);
|
||||
install_element(INTERFACE_NODE, &ipv6_ospf6_priority_cmd);
|
||||
install_element(INTERFACE_NODE, &ipv6_ospf6_retransmitinterval_cmd);
|
||||
install_element(INTERFACE_NODE, &ipv6_ospf6_transmitdelay_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, &no_ipv6_ospf6_passive_cmd);
|
||||
|
@ -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,
|
||||
ifindex_t *ifindexes,
|
||||
struct in6_addr **nexthop_addr,
|
||||
struct zapi_nexthop nexthops[],
|
||||
int entries)
|
||||
{
|
||||
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,
|
||||
IFNAMSIZ, ifname, nh->ifindex);
|
||||
}
|
||||
if (i < entries) {
|
||||
nexthop_addr[i] = &nh->address;
|
||||
ifindexes[i] = nh->ifindex;
|
||||
i++;
|
||||
} else {
|
||||
if (i >= entries)
|
||||
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++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -22,6 +22,7 @@
|
||||
#define OSPF6_ROUTE_H
|
||||
|
||||
#include "command.h"
|
||||
#include "zclient.h"
|
||||
|
||||
#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,
|
||||
struct ospf6_route *b);
|
||||
extern void ospf6_route_zebra_copy_nexthops(struct ospf6_route *route,
|
||||
ifindex_t *ifindices,
|
||||
struct in6_addr **addr,
|
||||
struct zapi_nexthop nexthops[],
|
||||
int entries);
|
||||
extern int ospf6_route_get_first_nh_index(struct ospf6_route *route);
|
||||
|
||||
|
@ -207,75 +207,30 @@ static int ospf6_zebra_if_address_update_delete(int command,
|
||||
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)
|
||||
{
|
||||
struct stream *s;
|
||||
struct zapi_ipv6 api;
|
||||
struct zapi_route api;
|
||||
unsigned long ifindex;
|
||||
struct prefix p, src_p;
|
||||
struct in6_addr *nexthop;
|
||||
|
||||
if (ospf6 == NULL)
|
||||
return 0;
|
||||
|
||||
s = zclient->ibuf;
|
||||
ifindex = 0;
|
||||
nexthop = NULL;
|
||||
memset(&api, 0, sizeof(api));
|
||||
if (zapi_route_decode(zclient->ibuf, &api) < 0)
|
||||
return -1;
|
||||
|
||||
/* 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));
|
||||
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. */
|
||||
if (CHECK_FLAG(api.message, ZAPI_MESSAGE_SRCPFX))
|
||||
return 0;
|
||||
|
||||
/* Nexthop, ifindex, distance, metric. */
|
||||
if (CHECK_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP)) {
|
||||
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;
|
||||
ifindex = api.nexthops[0].ifindex;
|
||||
nexthop = &api.nexthops[0].gate.ipv6;
|
||||
|
||||
if (IS_OSPF6_DEBUG_ZEBRA(RECV)) {
|
||||
char prefixstr[PREFIX2STR_BUFFER], nexthopstr[128];
|
||||
prefix2str((struct prefix *)&p, prefixstr, sizeof(prefixstr));
|
||||
prefix2str((struct prefix *)&api.prefix, prefixstr,
|
||||
sizeof(prefixstr));
|
||||
if (nexthop)
|
||||
inet_ntop(AF_INET6, nexthop, nexthopstr,
|
||||
sizeof(nexthopstr));
|
||||
@ -284,20 +239,17 @@ static int ospf6_zebra_read_ipv6(int command, struct zclient *zclient,
|
||||
|
||||
zlog_debug(
|
||||
"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"),
|
||||
zebra_route_string(api.type), prefixstr, nexthopstr,
|
||||
ifindex, api.tag);
|
||||
}
|
||||
|
||||
if (command == ZEBRA_REDISTRIBUTE_IPV6_ADD)
|
||||
ospf6_asbr_redistribute_add(api.type, ifindex, &p,
|
||||
if (command == ZEBRA_REDISTRIBUTE_ROUTE_ADD)
|
||||
ospf6_asbr_redistribute_add(api.type, ifindex, &api.prefix,
|
||||
api.nexthop_num, nexthop, api.tag);
|
||||
else
|
||||
ospf6_asbr_redistribute_remove(api.type, ifindex, &p);
|
||||
|
||||
if (CHECK_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP))
|
||||
free(nexthop);
|
||||
ospf6_asbr_redistribute_remove(api.type, ifindex, &api.prefix);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -317,7 +269,7 @@ DEFUN (show_zebra,
|
||||
}
|
||||
|
||||
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",
|
||||
vrf_bitmap_check(zclient->default_information, VRF_DEFAULT));
|
||||
vty_out(vty, " redistribute:");
|
||||
@ -329,38 +281,15 @@ DEFUN (show_zebra,
|
||||
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 REM 1
|
||||
static void ospf6_zebra_route_update(int type, struct ospf6_route *request)
|
||||
{
|
||||
struct zapi_ipv6 api;
|
||||
struct zapi_route api;
|
||||
char buf[PREFIX2STR_BUFFER];
|
||||
int nhcount;
|
||||
struct in6_addr **nexthops;
|
||||
ifindex_t *ifindexes;
|
||||
int ret = 0;
|
||||
struct prefix_ipv6 *dest;
|
||||
struct prefix *dest;
|
||||
|
||||
if (IS_OSPF6_DEBUG_ZEBRA(SEND)) {
|
||||
prefix2str(&request->prefix, buf, sizeof(buf));
|
||||
@ -408,36 +337,16 @@ static void ospf6_zebra_route_update(int type, struct ospf6_route *request)
|
||||
return;
|
||||
}
|
||||
|
||||
/* allocate memory for nexthop_list */
|
||||
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);
|
||||
dest = &request->prefix;
|
||||
|
||||
memset(&api, 0, sizeof(api));
|
||||
api.vrf_id = VRF_DEFAULT;
|
||||
api.type = ZEBRA_ROUTE_OSPF6;
|
||||
api.instance = 0;
|
||||
api.flags = 0;
|
||||
api.message = 0;
|
||||
api.safi = SAFI_UNICAST;
|
||||
api.prefix = *dest;
|
||||
SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
|
||||
api.nexthop_num = nhcount;
|
||||
api.nexthop = nexthops;
|
||||
SET_FLAG(api.message, ZAPI_MESSAGE_IFINDEX);
|
||||
api.ifindex_num = nhcount;
|
||||
api.ifindex = ifindexes;
|
||||
ospf6_route_zebra_copy_nexthops(request, api.nexthops, nhcount);
|
||||
SET_FLAG(api.message, ZAPI_MESSAGE_METRIC);
|
||||
api.metric = (request->path.metric_type == 2 ? request->path.u.cost_e2
|
||||
: request->path.cost);
|
||||
@ -446,194 +355,98 @@ static void ospf6_zebra_route_update(int type, struct ospf6_route *request)
|
||||
api.tag = request->path.tag;
|
||||
}
|
||||
|
||||
dest = (struct prefix_ipv6 *)&request->prefix;
|
||||
|
||||
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)
|
||||
ret = zapi_ipv6_route(ZEBRA_IPV6_ROUTE_DELETE, zclient, dest,
|
||||
NULL, &api);
|
||||
ret = zclient_route_send(ZEBRA_ROUTE_DELETE, zclient, &api);
|
||||
else
|
||||
ret = zapi_ipv6_route(ZEBRA_IPV6_ROUTE_ADD, zclient, dest, NULL,
|
||||
&api);
|
||||
ret = zclient_route_send(ZEBRA_ROUTE_ADD, zclient, &api);
|
||||
|
||||
if (ret < 0)
|
||||
zlog_err("zapi_ipv6_route() %s failed: %s",
|
||||
zlog_err("zclient_route_send() %s failed: %s",
|
||||
(type == REM ? "delete" : "add"),
|
||||
safe_strerror(errno));
|
||||
|
||||
XFREE(MTYPE_OSPF6_OTHER, nexthops);
|
||||
XFREE(MTYPE_OSPF6_OTHER, ifindexes);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
void ospf6_zebra_add_discard(struct ospf6_route *request)
|
||||
{
|
||||
struct zapi_ipv6 api;
|
||||
struct zapi_route api;
|
||||
char buf[INET6_ADDRSTRLEN];
|
||||
struct prefix_ipv6 *dest;
|
||||
struct prefix *dest = &request->prefix;
|
||||
|
||||
if (vrf_bitmap_check(zclient->redist[AFI_IP6][ZEBRA_ROUTE_OSPF6],
|
||||
VRF_DEFAULT)) {
|
||||
if (!CHECK_FLAG(request->flag, OSPF6_ROUTE_BLACKHOLE_ADDED)) {
|
||||
memset(&api, 0, sizeof(api));
|
||||
api.vrf_id = VRF_DEFAULT;
|
||||
api.type = ZEBRA_ROUTE_OSPF6;
|
||||
api.flags = ZEBRA_FLAG_BLACKHOLE;
|
||||
api.instance = 0;
|
||||
api.message = 0;
|
||||
api.safi = SAFI_UNICAST;
|
||||
SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
|
||||
api.nexthop_num = 0;
|
||||
api.ifindex_num = 0;
|
||||
api.prefix = *dest;
|
||||
|
||||
dest = (struct prefix_ipv6 *)&request->prefix;
|
||||
|
||||
zapi_ipv6_route(ZEBRA_IPV6_ROUTE_ADD, zclient, dest,
|
||||
NULL, &api);
|
||||
zclient_route_send(ZEBRA_ROUTE_ADD, zclient, &api);
|
||||
|
||||
if (IS_OSPF6_DEBUG_ZEBRA(SEND))
|
||||
zlog_debug("Zebra: Route add discard %s/%d",
|
||||
inet_ntop(AF_INET6, &dest->prefix,
|
||||
buf, INET6_ADDRSTRLEN),
|
||||
inet_ntop(AF_INET6, &dest->u.prefix6, buf,
|
||||
INET6_ADDRSTRLEN),
|
||||
dest->prefixlen);
|
||||
|
||||
SET_FLAG(request->flag, OSPF6_ROUTE_BLACKHOLE_ADDED);
|
||||
} else {
|
||||
dest = (struct prefix_ipv6 *)&request->prefix;
|
||||
|
||||
if (IS_OSPF6_DEBUG_ZEBRA(SEND))
|
||||
zlog_debug(
|
||||
"Zebra: Blackhole route present already %s/%d",
|
||||
inet_ntop(AF_INET6, &dest->prefix, buf,
|
||||
inet_ntop(AF_INET6, &dest->u.prefix6, buf,
|
||||
INET6_ADDRSTRLEN),
|
||||
dest->prefixlen);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ospf6_zebra_delete_discard(struct ospf6_route *request)
|
||||
{
|
||||
struct zapi_ipv6 api;
|
||||
struct zapi_route api;
|
||||
char buf[INET6_ADDRSTRLEN];
|
||||
struct prefix_ipv6 *dest;
|
||||
struct prefix *dest = &request->prefix;
|
||||
|
||||
if (vrf_bitmap_check(zclient->redist[AFI_IP6][ZEBRA_ROUTE_OSPF6],
|
||||
VRF_DEFAULT)) {
|
||||
if (CHECK_FLAG(request->flag, OSPF6_ROUTE_BLACKHOLE_ADDED)) {
|
||||
memset(&api, 0, sizeof(api));
|
||||
api.vrf_id = VRF_DEFAULT;
|
||||
api.type = ZEBRA_ROUTE_OSPF6;
|
||||
api.flags = ZEBRA_FLAG_BLACKHOLE;
|
||||
api.instance = 0;
|
||||
api.message = 0;
|
||||
api.safi = SAFI_UNICAST;
|
||||
SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
|
||||
api.nexthop_num = 0;
|
||||
api.ifindex_num = 0;
|
||||
api.prefix = *dest;
|
||||
|
||||
dest = (struct prefix_ipv6 *)&request->prefix;
|
||||
|
||||
zapi_ipv6_route(ZEBRA_IPV6_ROUTE_DELETE, zclient, dest,
|
||||
NULL, &api);
|
||||
zclient_route_send(ZEBRA_ROUTE_DELETE, zclient, &api);
|
||||
|
||||
if (IS_OSPF6_DEBUG_ZEBRA(SEND))
|
||||
zlog_debug("Zebra: Route delete discard %s/%d",
|
||||
inet_ntop(AF_INET6, &dest->prefix,
|
||||
buf, INET6_ADDRSTRLEN),
|
||||
inet_ntop(AF_INET6, &dest->u.prefix6, buf,
|
||||
INET6_ADDRSTRLEN),
|
||||
dest->prefixlen);
|
||||
|
||||
UNSET_FLAG(request->flag, OSPF6_ROUTE_BLACKHOLE_ADDED);
|
||||
} else {
|
||||
dest = (struct prefix_ipv6 *)&request->prefix;
|
||||
if (IS_OSPF6_DEBUG_ZEBRA(SEND))
|
||||
zlog_debug(
|
||||
"Zebra: Blackhole route already deleted %s/%d",
|
||||
inet_ntop(AF_INET6, &dest->prefix, buf,
|
||||
inet_ntop(AF_INET6, &dest->u.prefix6, 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)
|
||||
{
|
||||
@ -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_delete =
|
||||
ospf6_zebra_if_address_update_delete;
|
||||
zclient->redistribute_route_ipv4_add = NULL;
|
||||
zclient->redistribute_route_ipv4_del = NULL;
|
||||
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);
|
||||
zclient->redistribute_route_add = ospf6_zebra_read_route;
|
||||
zclient->redistribute_route_del = ospf6_zebra_read_route;
|
||||
|
||||
/* Install command element for zebra node. */
|
||||
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 */
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include "linklist.h"
|
||||
#include "vty.h"
|
||||
#include "command.h"
|
||||
#include "plist.h"
|
||||
|
||||
#include "ospf6_proto.h"
|
||||
#include "ospf6_network.h"
|
||||
@ -1139,6 +1140,20 @@ DEFUN (show_ipv6_ospf6_linkstate_detail,
|
||||
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. */
|
||||
void ospf6_init(void)
|
||||
{
|
||||
@ -1154,6 +1169,9 @@ void ospf6_init(void)
|
||||
ospf6_asbr_init();
|
||||
ospf6_abr_init();
|
||||
|
||||
prefix_list_add_hook(ospf6_plist_add);
|
||||
prefix_list_delete_hook(ospf6_plist_del);
|
||||
|
||||
ospf6_bfd_init();
|
||||
install_node(&debug_node, config_write_ospf6_debug);
|
||||
|
||||
|
@ -1897,7 +1897,8 @@ DEFUN (no_ospf_area_filter_list,
|
||||
|
||||
DEFUN (ospf_area_authentication_message_digest,
|
||||
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 ID in IP address format\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);
|
||||
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;
|
||||
}
|
||||
@ -6887,10 +6888,12 @@ DEFUN (no_ip_ospf_transmit_delay,
|
||||
|
||||
DEFUN_HIDDEN (no_ospf_transmit_delay,
|
||||
no_ospf_transmit_delay_cmd,
|
||||
"no ospf transmit-delay",
|
||||
"no ospf transmit-delay [(1-65535) [A.B.C.D]]",
|
||||
NO_STR
|
||||
"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);
|
||||
}
|
||||
|
@ -333,95 +333,68 @@ static int ospf_interface_link_params(int command, struct zclient *zclient,
|
||||
|
||||
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_int32_t flags;
|
||||
int psize;
|
||||
struct stream *s;
|
||||
struct ospf_path *path;
|
||||
struct listnode *node;
|
||||
struct ospf *ospf = ospf_lookup();
|
||||
int count = 0;
|
||||
|
||||
if ((ospf->instance
|
||||
&& redist_check_instance(
|
||||
&zclient->mi_redist[AFI_IP][ZEBRA_ROUTE_OSPF],
|
||||
ospf->instance))
|
||||
|| vrf_bitmap_check(zclient->redist[AFI_IP][ZEBRA_ROUTE_OSPF],
|
||||
VRF_DEFAULT)) {
|
||||
message = 0;
|
||||
flags = 0;
|
||||
memset(&api, 0, sizeof(api));
|
||||
api.vrf_id = VRF_DEFAULT;
|
||||
api.type = ZEBRA_ROUTE_OSPF;
|
||||
api.instance = ospf->instance;
|
||||
api.safi = SAFI_UNICAST;
|
||||
|
||||
/* OSPF pass nexthop and metric */
|
||||
SET_FLAG(message, ZAPI_MESSAGE_NEXTHOP);
|
||||
SET_FLAG(message, ZAPI_MESSAGE_METRIC);
|
||||
memcpy(&api.prefix, p, sizeof(*p));
|
||||
SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
|
||||
api.nexthop_num = or->paths->count;
|
||||
|
||||
/* Distance value. */
|
||||
distance = ospf_distance_apply(p, or);
|
||||
if (distance)
|
||||
SET_FLAG(message, ZAPI_MESSAGE_DISTANCE);
|
||||
/* Metric value. */
|
||||
SET_FLAG(api.message, ZAPI_MESSAGE_METRIC);
|
||||
if (or->path_type == OSPF_PATH_TYPE1_EXTERNAL)
|
||||
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 */
|
||||
if (((or->path_type == OSPF_PATH_TYPE1_EXTERNAL)
|
||||
|| (or->path_type == OSPF_PATH_TYPE2_EXTERNAL))
|
||||
&& (or->u.ext.tag > 0) && (or->u.ext.tag <= ROUTE_TAG_MAX))
|
||||
SET_FLAG(message, ZAPI_MESSAGE_TAG);
|
||||
&& (or->u.ext.tag > 0) && (or->u.ext.tag <= ROUTE_TAG_MAX)) {
|
||||
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);
|
||||
/* 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
|
||||
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);
|
||||
}
|
||||
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];
|
||||
@ -429,177 +402,76 @@ void ospf_zebra_add(struct prefix_ipv4 *p, struct ospf_route * or)
|
||||
"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,
|
||||
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);
|
||||
}
|
||||
zclient_route_send(ZEBRA_ROUTE_ADD, zclient, &api);
|
||||
}
|
||||
|
||||
void ospf_zebra_delete(struct prefix_ipv4 *p, struct ospf_route * or)
|
||||
{
|
||||
u_char message;
|
||||
u_char distance;
|
||||
u_int32_t flags;
|
||||
int psize;
|
||||
struct stream *s;
|
||||
struct ospf_path *path;
|
||||
struct listnode *node;
|
||||
struct zapi_route api;
|
||||
struct ospf *ospf = ospf_lookup();
|
||||
|
||||
if ((ospf->instance
|
||||
&& redist_check_instance(
|
||||
&zclient->mi_redist[AFI_IP][ZEBRA_ROUTE_OSPF],
|
||||
ospf->instance))
|
||||
|| vrf_bitmap_check(zclient->redist[AFI_IP][ZEBRA_ROUTE_OSPF],
|
||||
VRF_DEFAULT)) {
|
||||
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. */
|
||||
zclient_create_header(s, ZEBRA_IPV4_ROUTE_DELETE, 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)) {
|
||||
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);
|
||||
}
|
||||
memset(&api, 0, sizeof(api));
|
||||
api.vrf_id = VRF_DEFAULT;
|
||||
api.type = ZEBRA_ROUTE_OSPF;
|
||||
api.instance = ospf->instance;
|
||||
api.safi = SAFI_UNICAST;
|
||||
memcpy(&api.prefix, p, sizeof(*p));
|
||||
|
||||
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])));
|
||||
}
|
||||
char buf[INET_ADDRSTRLEN];
|
||||
zlog_debug("Zebra: Route delete %s/%d",
|
||||
inet_ntop(AF_INET, &p->prefix, buf, sizeof(buf[0])),
|
||||
p->prefixlen);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
struct zapi_ipv4 api;
|
||||
struct zapi_route api;
|
||||
struct ospf *ospf = ospf_lookup();
|
||||
|
||||
if ((ospf->instance
|
||||
&& redist_check_instance(
|
||||
&zclient->mi_redist[AFI_IP][ZEBRA_ROUTE_OSPF],
|
||||
ospf->instance))
|
||||
|| vrf_bitmap_check(zclient->redist[AFI_IP][ZEBRA_ROUTE_OSPF],
|
||||
VRF_DEFAULT)) {
|
||||
memset(&api, 0, sizeof(api));
|
||||
api.vrf_id = VRF_DEFAULT;
|
||||
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;
|
||||
memcpy(&api.prefix, p, sizeof(*p));
|
||||
|
||||
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))
|
||||
zlog_debug("Zebra: Route add discard %s/%d",
|
||||
inet_ntoa(p->prefix), p->prefixlen);
|
||||
}
|
||||
}
|
||||
|
||||
void ospf_zebra_delete_discard(struct prefix_ipv4 *p)
|
||||
{
|
||||
struct zapi_ipv4 api;
|
||||
struct zapi_route api;
|
||||
struct ospf *ospf = ospf_lookup();
|
||||
|
||||
if ((ospf->instance
|
||||
&& redist_check_instance(
|
||||
&zclient->mi_redist[AFI_IP][ZEBRA_ROUTE_OSPF],
|
||||
ospf->instance))
|
||||
|| vrf_bitmap_check(zclient->redist[AFI_IP][ZEBRA_ROUTE_OSPF],
|
||||
VRF_DEFAULT)) {
|
||||
memset(&api, 0, sizeof(api));
|
||||
api.vrf_id = VRF_DEFAULT;
|
||||
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;
|
||||
memcpy(&api.prefix, p, sizeof(*p));
|
||||
|
||||
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))
|
||||
zlog_debug("Zebra: Route delete discard %s/%d",
|
||||
inet_ntoa(p->prefix), p->prefixlen);
|
||||
}
|
||||
}
|
||||
|
||||
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. */
|
||||
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)
|
||||
{
|
||||
struct stream *s;
|
||||
struct zapi_ipv4 api;
|
||||
struct zapi_route api;
|
||||
struct prefix_ipv4 p;
|
||||
unsigned long ifindex;
|
||||
struct in_addr nexthop;
|
||||
struct prefix_ipv4 p;
|
||||
struct external_info *ei;
|
||||
struct ospf *ospf;
|
||||
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();
|
||||
if (ospf == NULL)
|
||||
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:
|
||||
* Maybe we should ignore reject/blackhole routes? Testing shows
|
||||
* that
|
||||
@ -1070,7 +913,7 @@ static int ospf_zebra_read_ipv4(int command, struct zclient *zclient,
|
||||
* 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)
|
||||
api.tag = ospf->dtag[api.type];
|
||||
|
||||
@ -1112,7 +955,7 @@ static int ospf_zebra_read_ipv4(int command, struct zclient *zclient,
|
||||
zebra,
|
||||
ZEBRA_REDISTRIBUTE))
|
||||
zlog_debug(
|
||||
"ospf_zebra_read_ipv4() : %s refreshing LSA",
|
||||
"ospf_zebra_read_route() : %s refreshing LSA",
|
||||
inet_ntoa(
|
||||
p.prefix));
|
||||
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);
|
||||
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_link_params = ospf_interface_link_params;
|
||||
|
||||
zclient->redistribute_route_ipv4_add = ospf_zebra_read_ipv4;
|
||||
zclient->redistribute_route_ipv4_del = ospf_zebra_read_ipv4;
|
||||
zclient->redistribute_route_add = ospf_zebra_read_route;
|
||||
zclient->redistribute_route_del = ospf_zebra_read_route;
|
||||
|
||||
access_list_add_hook(ospf_filter_update);
|
||||
access_list_delete_hook(ospf_filter_update);
|
||||
|
@ -1666,7 +1666,7 @@ static void pim_show_join_helper(struct vty *vty,
|
||||
json_row);
|
||||
} else {
|
||||
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_src_str, ch_grp_str,
|
||||
pim_ifchannel_ifjoin_name(ch->ifjoin_state,
|
||||
|
@ -42,6 +42,7 @@
|
||||
#include "pim_oil.h"
|
||||
#include "pim_upstream.h"
|
||||
#include "pim_ssm.h"
|
||||
#include "pim_rp.h"
|
||||
|
||||
RB_GENERATE(pim_ifchannel_rb, pim_ifchannel,
|
||||
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) {
|
||||
case PIM_IFJOIN_NOINFO:
|
||||
if (PIM_IF_FLAG_TEST_S_G_RPT(flags))
|
||||
return "SGRpt";
|
||||
return "SGRpt(NI)";
|
||||
else
|
||||
return "NOINFO";
|
||||
break;
|
||||
@ -356,15 +357,27 @@ const char *pim_ifchannel_ifjoin_name(enum pim_ifjoin_state ifjoin_state,
|
||||
return "JOIN";
|
||||
break;
|
||||
case PIM_IFJOIN_PRUNE:
|
||||
if (PIM_IF_FLAG_TEST_S_G_RPT(flags))
|
||||
return "SGRpt(P)";
|
||||
else
|
||||
return "PRUNE";
|
||||
break;
|
||||
case PIM_IFJOIN_PRUNE_PENDING:
|
||||
if (PIM_IF_FLAG_TEST_S_G_RPT(flags))
|
||||
return "SGRpt(PP)";
|
||||
else
|
||||
return "PRUNEP";
|
||||
break;
|
||||
case PIM_IFJOIN_PRUNE_TMP:
|
||||
if (PIM_IF_FLAG_TEST_S_G_RPT(flags))
|
||||
return "SGRpt(P')";
|
||||
else
|
||||
return "PRUNET";
|
||||
break;
|
||||
case PIM_IFJOIN_PRUNE_PENDING_TMP:
|
||||
if (PIM_IF_FLAG_TEST_S_G_RPT(flags))
|
||||
return "SGRpt(PP')";
|
||||
else
|
||||
return "PRUNEPT";
|
||||
break;
|
||||
}
|
||||
@ -628,33 +641,34 @@ static int on_ifjoin_prune_pending_timer(struct thread *t)
|
||||
ch = THREAD_ARG(t);
|
||||
|
||||
if (ch->ifjoin_state == PIM_IFJOIN_PRUNE_PENDING) {
|
||||
/* Send PruneEcho(S,G) ? */
|
||||
ifp = ch->interface;
|
||||
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) {
|
||||
struct pim_rpf rpf;
|
||||
|
||||
rpf.source_nexthop.interface = ifp;
|
||||
rpf.rpf_addr.u.prefix4 = pim_ifp->primary_address;
|
||||
pim_jp_agg_single_upstream_send(&rpf, ch->upstream, 0);
|
||||
rpf.rpf_addr.u.prefix4 =
|
||||
pim_ifp->primary_address;
|
||||
pim_jp_agg_single_upstream_send(&rpf,
|
||||
ch->upstream,
|
||||
0);
|
||||
}
|
||||
|
||||
ifjoin_to_noinfo(ch, true);
|
||||
} else {
|
||||
/* If SGRpt flag is set on ifchannel, Trigger SGRpt
|
||||
message on RP path upon prune timer expiry.
|
||||
* message on RP path upon prune timer expiry.
|
||||
*/
|
||||
if (PIM_IF_FLAG_TEST_S_G_RPT(ch->flags)) {
|
||||
ch->ifjoin_state = PIM_IFJOIN_PRUNE;
|
||||
if (ch->upstream)
|
||||
pim_upstream_update_join_desired(pim_ifp->pim,
|
||||
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 */
|
||||
} else {
|
||||
zlog_warn(
|
||||
@ -1104,7 +1118,6 @@ void pim_ifchannel_local_membership_del(struct interface *ifp,
|
||||
orig = ch = pim_ifchannel_find(ifp, sg);
|
||||
if (!ch)
|
||||
return;
|
||||
|
||||
ifmembership_set(ch, PIM_IFMEMBERSHIP_NOINFO);
|
||||
|
||||
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
|
||||
*/
|
||||
void pim_ifchannel_set_star_g_join_state(struct pim_ifchannel *ch, int eom,
|
||||
uint8_t source_flags, uint8_t join,
|
||||
uint8_t starg_alone)
|
||||
uint8_t join)
|
||||
{
|
||||
struct pim_ifchannel *child;
|
||||
struct listnode *ch_node;
|
||||
struct pim_instance *pim =
|
||||
((struct pim_interface *)ch->interface->info)->pim;
|
||||
|
||||
if (PIM_DEBUG_PIM_TRACE)
|
||||
zlog_debug(
|
||||
@ -1326,33 +1340,6 @@ void pim_ifchannel_set_star_g_join_state(struct pim_ifchannel *ch, int eom,
|
||||
return;
|
||||
|
||||
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))
|
||||
continue;
|
||||
|
||||
@ -1371,8 +1358,30 @@ void pim_ifchannel_set_star_g_join_state(struct pim_ifchannel *ch, int eom,
|
||||
break;
|
||||
case PIM_IFJOIN_PRUNE_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;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
@ -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_set_star_g_join_state(struct pim_ifchannel *ch, int eom,
|
||||
uint8_t source_flags, uint8_t join,
|
||||
uint8_t starg_alone);
|
||||
uint8_t join);
|
||||
|
||||
int pim_ifchannel_compare(const struct pim_ifchannel *ch1,
|
||||
const struct pim_ifchannel *ch2);
|
||||
|
@ -231,7 +231,6 @@ int pim_joinprune_recv(struct interface *ifp, struct pim_neighbor *neigh,
|
||||
uint16_t msg_num_pruned_sources;
|
||||
int source;
|
||||
struct pim_ifchannel *starg_ch = NULL, *sg_ch = NULL;
|
||||
uint8_t starg_alone = 0;
|
||||
|
||||
memset(&sg, 0, sizeof(struct prefix_sg));
|
||||
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);
|
||||
|
||||
if (sg.src.s_addr == INADDR_ANY) {
|
||||
starg_alone = 1;
|
||||
starg_ch = pim_ifchannel_find(ifp, &sg);
|
||||
if (starg_ch)
|
||||
pim_ifchannel_set_star_g_join_state(
|
||||
starg_ch, 0, msg_source_flags,
|
||||
1, starg_alone);
|
||||
starg_ch, 0, 1);
|
||||
}
|
||||
}
|
||||
|
||||
@ -307,7 +304,6 @@ int pim_joinprune_recv(struct interface *ifp, struct pim_neighbor *neigh,
|
||||
}
|
||||
|
||||
buf += addr_offset;
|
||||
starg_alone = 0;
|
||||
recv_prune(ifp, neigh, msg_holdtime,
|
||||
msg_upstream_addr.u.prefix4, &sg,
|
||||
msg_source_flags);
|
||||
@ -340,8 +336,7 @@ int pim_joinprune_recv(struct interface *ifp, struct pim_neighbor *neigh,
|
||||
}
|
||||
}
|
||||
if (starg_ch)
|
||||
pim_ifchannel_set_star_g_join_state(
|
||||
starg_ch, 1, msg_source_flags, 0, starg_alone);
|
||||
pim_ifchannel_set_star_g_join_state(starg_ch, 1, 0);
|
||||
starg_ch = NULL;
|
||||
} /* 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_interface *pim_ifp = NULL;
|
||||
struct pim_jp_groups *grp = NULL;
|
||||
struct pim_jp *msg;
|
||||
struct pim_jp *msg = NULL;
|
||||
struct listnode *node, *nnode;
|
||||
uint8_t pim_msg[10000];
|
||||
uint8_t *curr_ptr = pim_msg;
|
||||
|
@ -1624,8 +1624,9 @@ static void pim_upstream_sg_running(void *arg)
|
||||
// No packet can have arrived here if this is the case
|
||||
if (!up->channel_oil->installed) {
|
||||
if (PIM_DEBUG_TRACE)
|
||||
zlog_debug("%s: %s is not installed in mroute",
|
||||
__PRETTY_FUNCTION__, up->sg_str);
|
||||
zlog_debug("%s: %s[%s] is not installed in mroute",
|
||||
__PRETTY_FUNCTION__,
|
||||
up->sg_str, pim->vrf->name);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -36,12 +36,14 @@ class RenderHandler(object):
|
||||
|
||||
deref = ''
|
||||
drop_str = False
|
||||
canfail = True
|
||||
|
||||
class StringHandler(RenderHandler):
|
||||
argtype = 'const char *'
|
||||
decl = Template('const char *$varname = NULL;')
|
||||
code = Template('$varname = argv[_i]->arg;')
|
||||
drop_str = True
|
||||
canfail = False
|
||||
|
||||
class LongHandler(RenderHandler):
|
||||
argtype = 'long'
|
||||
@ -130,6 +132,10 @@ handlers = {
|
||||
}
|
||||
|
||||
# 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" */
|
||||
DEFUN_CMD_FUNC_DECL($fnname)
|
||||
#define funcdecl_$fnname static int ${fnname}_magic(\\
|
||||
@ -140,20 +146,31 @@ DEFUN_CMD_FUNC_DECL($fnname)
|
||||
funcdecl_$fnname;
|
||||
DEFUN_CMD_FUNC_TEXT($fnname)
|
||||
{
|
||||
#if $nonempty /* anything to parse? */
|
||||
int _i;
|
||||
#if $canfail /* anything that can fail? */
|
||||
unsigned _fail = 0, _failcnt = 0;
|
||||
#endif
|
||||
$argdecls
|
||||
for (_i = 0; _i < argc; _i++) {
|
||||
if (!argv[_i]->varname)
|
||||
continue;
|
||||
_fail = 0;$argblocks
|
||||
#if $canfail /* anything that can fail? */
|
||||
_fail = 0;
|
||||
#endif
|
||||
$argblocks
|
||||
#if $canfail /* anything that can fail? */
|
||||
if (_fail)
|
||||
vty_out (vty, "%% invalid input for %s: %s\\n",
|
||||
argv[_i]->varname, argv[_i]->arg);
|
||||
_failcnt += _fail;
|
||||
#endif
|
||||
}
|
||||
#if $canfail /* anything that can fail? */
|
||||
if (_failcnt)
|
||||
return CMD_WARNING;
|
||||
#endif
|
||||
#endif
|
||||
return ${fnname}_magic(self, vty, argc, argv$arglist);
|
||||
}
|
||||
|
||||
@ -196,6 +213,7 @@ def process_file(fn, ofd, dumpfd, all_defun):
|
||||
arglist = []
|
||||
argblocks = []
|
||||
doc = []
|
||||
canfail = 0
|
||||
|
||||
def do_add(handler, 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
|
||||
do_add(handler, varname)
|
||||
code = handler.code.substitute({'varname': varname}).replace('\n', '\n\t\t\t')
|
||||
if handler.canfail:
|
||||
canfail = 1
|
||||
strblock = ''
|
||||
if not handler.drop_str:
|
||||
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['arglist'] = ''.join(arglist)
|
||||
params['argblocks'] = ''.join(argblocks)
|
||||
params['canfail'] = canfail
|
||||
params['nonempty'] = len(argblocks)
|
||||
ofd.write(templ.substitute(params))
|
||||
|
||||
if __name__ == '__main__':
|
||||
@ -257,4 +279,4 @@ if __name__ == '__main__':
|
||||
process_file(args.cfile, ofd, dumpfd, args.all_defun)
|
||||
|
||||
if args.o is not None:
|
||||
clippy.wrdiff(args.o, ofd)
|
||||
clippy.wrdiff(args.o, ofd, [args.cfile, os.path.realpath(__file__)])
|
||||
|
@ -16,6 +16,7 @@
|
||||
# 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
|
||||
|
||||
import os, stat
|
||||
import _clippy
|
||||
from _clippy import parse, Graph, GraphNode
|
||||
|
||||
@ -47,7 +48,7 @@ def dump(graph):
|
||||
for i, depth in graph_iterate(graph):
|
||||
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'''
|
||||
|
||||
expl = ''
|
||||
@ -57,8 +58,16 @@ def wrdiff(filename, buf):
|
||||
try: old = open(filename, 'r').read()
|
||||
except: pass
|
||||
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))
|
||||
return
|
||||
with open('.new.' + filename, 'w') as out:
|
||||
|
||||
newname = '%s.new-%d' % (filename, os.getpid())
|
||||
with open(newname, 'w') as out:
|
||||
out.write(buf)
|
||||
os.rename('.new.' + filename, filename)
|
||||
os.rename(newname, filename)
|
||||
|
203
ripd/rip_zebra.c
203
ripd/rip_zebra.c
@ -39,51 +39,39 @@ struct zclient *zclient = NULL;
|
||||
/* Send ECMP routes to zebra. */
|
||||
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 zapi_ipv4 api;
|
||||
struct zapi_route api;
|
||||
struct zapi_nexthop *api_nh;
|
||||
struct listnode *listnode = NULL;
|
||||
struct rip_info *rinfo = NULL;
|
||||
int count = 0;
|
||||
|
||||
if (vrf_bitmap_check(zclient->redist[AFI_IP][ZEBRA_ROUTE_RIP],
|
||||
VRF_DEFAULT)) {
|
||||
memset(&api, 0, sizeof(api));
|
||||
api.vrf_id = VRF_DEFAULT;
|
||||
api.type = ZEBRA_ROUTE_RIP;
|
||||
api.instance = 0;
|
||||
api.flags = 0;
|
||||
api.message = 0;
|
||||
api.safi = SAFI_UNICAST;
|
||||
|
||||
if (nexthops_len < listcount(list)) {
|
||||
nexthops_len = listcount(list);
|
||||
nexthops = XREALLOC(MTYPE_TMP, nexthops,
|
||||
nexthops_len
|
||||
* sizeof(struct in_addr *));
|
||||
}
|
||||
|
||||
SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
|
||||
for (ALL_LIST_ELEMENTS_RO(list, listnode, rinfo)) {
|
||||
nexthops[count++] = &rinfo->nexthop;
|
||||
if (cmd == ZEBRA_IPV4_ROUTE_ADD)
|
||||
api_nh = &api.nexthops[count];
|
||||
api_nh->gate.ipv4 = rinfo->nexthop;
|
||||
api_nh->type = NEXTHOP_TYPE_IPV4;
|
||||
if (cmd == ZEBRA_ROUTE_ADD)
|
||||
SET_FLAG(rinfo->flags, RIP_RTF_FIB);
|
||||
else
|
||||
UNSET_FLAG(rinfo->flags, RIP_RTF_FIB);
|
||||
count++;
|
||||
}
|
||||
|
||||
api.nexthop = nexthops;
|
||||
api.prefix = rp->p;
|
||||
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) {
|
||||
if (rinfo->distance && rinfo->distance != ZEBRA_RIP_DISTANCE_DEFAULT) {
|
||||
SET_FLAG(api.message, ZAPI_MESSAGE_DISTANCE);
|
||||
api.distance = rinfo->distance;
|
||||
}
|
||||
@ -93,101 +81,65 @@ static void rip_zebra_ipv4_send(struct route_node *rp, u_char cmd)
|
||||
api.tag = rinfo->tag;
|
||||
}
|
||||
|
||||
zapi_ipv4_route(cmd, zclient, (struct prefix_ipv4 *)&rp->p,
|
||||
&api);
|
||||
zclient_route_send(cmd, zclient, &api);
|
||||
|
||||
if (IS_RIP_DEBUG_ZEBRA) {
|
||||
if (rip->ecmp)
|
||||
zlog_debug("%s: %s/%d nexthops %d",
|
||||
(cmd == ZEBRA_IPV4_ROUTE_ADD)
|
||||
(cmd == ZEBRA_ROUTE_ADD)
|
||||
? "Install into zebra"
|
||||
: "Delete from zebra",
|
||||
inet_ntoa(rp->p.u.prefix4),
|
||||
rp->p.prefixlen, count);
|
||||
inet_ntoa(rp->p.u.prefix4), rp->p.prefixlen,
|
||||
count);
|
||||
else
|
||||
zlog_debug("%s: %s/%d",
|
||||
(cmd == ZEBRA_IPV4_ROUTE_ADD)
|
||||
(cmd == ZEBRA_ROUTE_ADD)
|
||||
? "Install into zebra"
|
||||
: "Delete from zebra",
|
||||
inet_ntoa(rp->p.u.prefix4),
|
||||
rp->p.prefixlen);
|
||||
inet_ntoa(rp->p.u.prefix4), rp->p.prefixlen);
|
||||
}
|
||||
|
||||
rip_global_route_changes++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Add/update ECMP routes to zebra. */
|
||||
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. */
|
||||
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. */
|
||||
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)
|
||||
{
|
||||
struct stream *s;
|
||||
struct zapi_ipv4 api;
|
||||
unsigned long ifindex;
|
||||
struct zapi_route api;
|
||||
struct in_addr nexthop;
|
||||
struct prefix_ipv4 p;
|
||||
unsigned long ifindex;
|
||||
|
||||
if (!rip)
|
||||
return 0;
|
||||
|
||||
s = zclient->ibuf;
|
||||
ifindex = 0;
|
||||
nexthop.s_addr = 0;
|
||||
if (zapi_route_decode(zclient->ibuf, &api) < 0)
|
||||
return -1;
|
||||
|
||||
/* 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));
|
||||
|
||||
/* 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;
|
||||
nexthop = api.nexthops[0].gate.ipv4;
|
||||
ifindex = api.nexthops[0].ifindex;
|
||||
|
||||
/* Then fetch IPv4 prefixes. */
|
||||
if (command == ZEBRA_REDISTRIBUTE_IPV4_ADD)
|
||||
rip_redistribute_add(api.type, RIP_ROUTE_REDISTRIBUTE, &p,
|
||||
ifindex, &nexthop, api.metric,
|
||||
api.distance, api.tag);
|
||||
else if (command == ZEBRA_REDISTRIBUTE_IPV4_DEL)
|
||||
rip_redistribute_delete(api.type, RIP_ROUTE_REDISTRIBUTE, &p,
|
||||
if (command == ZEBRA_REDISTRIBUTE_ROUTE_ADD)
|
||||
rip_redistribute_add(api.type, RIP_ROUTE_REDISTRIBUTE,
|
||||
(struct prefix_ipv4 *)&api.prefix, ifindex,
|
||||
&nexthop, api.metric, api.distance,
|
||||
api.tag);
|
||||
else if (command == ZEBRA_REDISTRIBUTE_ROUTE_DEL)
|
||||
rip_redistribute_delete(api.type, RIP_ROUTE_REDISTRIBUTE,
|
||||
(struct prefix_ipv4 *)&api.prefix,
|
||||
ifindex);
|
||||
|
||||
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,
|
||||
rip_redistribute_type_cmd,
|
||||
"redistribute " FRR_REDIST_STR_RIPD,
|
||||
@ -604,65 +535,45 @@ DEFUN (no_rip_default_information_originate,
|
||||
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 i;
|
||||
|
||||
for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
|
||||
if (i != zclient->redist_default
|
||||
&& vrf_bitmap_check(zclient->redist[AFI_IP][i],
|
||||
VRF_DEFAULT)) {
|
||||
if (config_mode) {
|
||||
for (i = 0; i < ZEBRA_ROUTE_MAX; i++) {
|
||||
if (i == zclient->redist_default
|
||||
|| !vrf_bitmap_check(zclient->redist[AFI_IP][i],
|
||||
VRF_DEFAULT))
|
||||
continue;
|
||||
|
||||
if (!config_mode) {
|
||||
vty_out(vty, " %s", zebra_route_string(i));
|
||||
continue;
|
||||
}
|
||||
|
||||
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].metric,
|
||||
rip->route_map[i].name);
|
||||
else
|
||||
vty_out(vty,
|
||||
" redistribute %s metric %d\n",
|
||||
vty_out(vty, " redistribute %s metric %d\n",
|
||||
zebra_route_string(i),
|
||||
rip->route_map[i]
|
||||
.metric);
|
||||
rip->route_map[i].metric);
|
||||
} else {
|
||||
if (rip->route_map[i].name)
|
||||
vty_out(vty,
|
||||
" redistribute %s route-map %s\n",
|
||||
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",
|
||||
vty_out(vty, " redistribute %s\n",
|
||||
zebra_route_string(i));
|
||||
}
|
||||
} else
|
||||
vty_out(vty, " %s", zebra_route_string(i));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Zebra node structure. */
|
||||
static struct cmd_node zebra_node = {
|
||||
ZEBRA_NODE, "%s(config-router)# ",
|
||||
};
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void rip_zebra_connected(struct zclient *zclient)
|
||||
{
|
||||
@ -681,16 +592,8 @@ void rip_zclient_init(struct thread_master *master)
|
||||
zclient->interface_address_delete = rip_interface_address_delete;
|
||||
zclient->interface_up = rip_interface_up;
|
||||
zclient->interface_down = rip_interface_down;
|
||||
zclient->redistribute_route_ipv4_add = rip_zebra_read_ipv4;
|
||||
zclient->redistribute_route_ipv4_del = rip_zebra_read_ipv4;
|
||||
|
||||
/* 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);
|
||||
zclient->redistribute_route_add = rip_zebra_read_route;
|
||||
zclient->redistribute_route_del = rip_zebra_read_route;
|
||||
|
||||
/* Install command elements to rip node. */
|
||||
install_element(RIP_NODE, &rip_redistribute_type_cmd);
|
||||
|
@ -39,51 +39,33 @@ struct zclient *zclient = NULL;
|
||||
/* Send ECMP routes to zebra. */
|
||||
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 zapi_ipv6 api;
|
||||
struct zapi_route api;
|
||||
struct zapi_nexthop *api_nh;
|
||||
struct listnode *listnode = NULL;
|
||||
struct ripng_info *rinfo = NULL;
|
||||
int count = 0;
|
||||
|
||||
if (vrf_bitmap_check(zclient->redist[AFI_IP6][ZEBRA_ROUTE_RIPNG],
|
||||
VRF_DEFAULT)) {
|
||||
memset(&api, 0, sizeof(api));
|
||||
api.vrf_id = VRF_DEFAULT;
|
||||
api.type = ZEBRA_ROUTE_RIPNG;
|
||||
api.instance = 0;
|
||||
api.flags = 0;
|
||||
api.message = 0;
|
||||
api.safi = SAFI_UNICAST;
|
||||
|
||||
if (nexthops_len < listcount(list)) {
|
||||
nexthops_len = listcount(list);
|
||||
nexthops = XREALLOC(
|
||||
MTYPE_TMP, nexthops,
|
||||
nexthops_len * sizeof(struct in6_addr *));
|
||||
ifindexes =
|
||||
XREALLOC(MTYPE_TMP, ifindexes,
|
||||
nexthops_len * sizeof(unsigned int));
|
||||
}
|
||||
api.prefix = rp->p;
|
||||
|
||||
SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
|
||||
SET_FLAG(api.message, ZAPI_MESSAGE_IFINDEX);
|
||||
for (ALL_LIST_ELEMENTS_RO(list, listnode, rinfo)) {
|
||||
nexthops[count] = &rinfo->nexthop;
|
||||
ifindexes[count] = rinfo->ifindex;
|
||||
api_nh = &api.nexthops[count];
|
||||
api_nh->gate.ipv6 = rinfo->nexthop;
|
||||
api_nh->ifindex = rinfo->ifindex;
|
||||
api_nh->type = NEXTHOP_TYPE_IPV6_IFINDEX;
|
||||
count++;
|
||||
if (cmd == ZEBRA_IPV6_ROUTE_ADD)
|
||||
if (cmd == ZEBRA_ROUTE_ADD)
|
||||
SET_FLAG(rinfo->flags, RIPNG_RTF_FIB);
|
||||
else
|
||||
UNSET_FLAG(rinfo->flags, RIPNG_RTF_FIB);
|
||||
}
|
||||
|
||||
api.nexthop = nexthops;
|
||||
api.nexthop_num = count;
|
||||
api.ifindex = ifindexes;
|
||||
api.ifindex_num = count;
|
||||
|
||||
rinfo = listgetdata(listhead(list));
|
||||
|
||||
@ -95,106 +77,63 @@ static void ripng_zebra_ipv6_send(struct route_node *rp, u_char cmd)
|
||||
api.tag = rinfo->tag;
|
||||
}
|
||||
|
||||
zapi_ipv6_route(cmd, zclient, (struct prefix_ipv6 *)&rp->p,
|
||||
NULL, &api);
|
||||
zclient_route_send(cmd, zclient, &api);
|
||||
|
||||
if (IS_RIPNG_DEBUG_ZEBRA) {
|
||||
if (ripng->ecmp)
|
||||
zlog_debug("%s: %s/%d nexthops %d",
|
||||
(cmd == ZEBRA_IPV6_ROUTE_ADD)
|
||||
(cmd == ZEBRA_ROUTE_ADD)
|
||||
? "Install into zebra"
|
||||
: "Delete from zebra",
|
||||
inet6_ntoa(rp->p.u.prefix6),
|
||||
rp->p.prefixlen, count);
|
||||
inet6_ntoa(rp->p.u.prefix6), rp->p.prefixlen,
|
||||
count);
|
||||
else
|
||||
zlog_debug("%s: %s/%d",
|
||||
(cmd == ZEBRA_IPV6_ROUTE_ADD)
|
||||
? "Install into zebra"
|
||||
zlog_debug(
|
||||
"%s: %s/%d",
|
||||
(cmd == ZEBRA_ROUTE_ADD) ? "Install into zebra"
|
||||
: "Delete from zebra",
|
||||
inet6_ntoa(rp->p.u.prefix6),
|
||||
rp->p.prefixlen);
|
||||
}
|
||||
inet6_ntoa(rp->p.u.prefix6), rp->p.prefixlen);
|
||||
}
|
||||
}
|
||||
|
||||
/* Add/update ECMP routes to zebra. */
|
||||
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. */
|
||||
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. */
|
||||
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)
|
||||
{
|
||||
struct stream *s;
|
||||
struct zapi_ipv6 api;
|
||||
unsigned long ifindex;
|
||||
struct zapi_route api;
|
||||
struct in6_addr nexthop;
|
||||
struct prefix_ipv6 p, src_p;
|
||||
unsigned long ifindex;
|
||||
|
||||
s = zclient->ibuf;
|
||||
ifindex = 0;
|
||||
memset(&nexthop, 0, sizeof(struct in6_addr));
|
||||
if (zapi_route_decode(zclient->ibuf, &api) < 0)
|
||||
return -1;
|
||||
|
||||
/* 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. */
|
||||
if (CHECK_FLAG(api.message, ZAPI_MESSAGE_SRCPFX))
|
||||
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);
|
||||
}
|
||||
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;
|
||||
nexthop = api.nexthops[0].gate.ipv6;
|
||||
ifindex = api.nexthops[0].ifindex;
|
||||
|
||||
if (CHECK_FLAG(api.message, ZAPI_MESSAGE_TAG))
|
||||
api.tag = stream_getl(s);
|
||||
else
|
||||
api.tag = 0;
|
||||
|
||||
if (command == ZEBRA_REDISTRIBUTE_IPV6_ADD)
|
||||
ripng_redistribute_add(api.type, RIPNG_ROUTE_REDISTRIBUTE, &p,
|
||||
if (command == ZEBRA_REDISTRIBUTE_ROUTE_ADD)
|
||||
ripng_redistribute_add(api.type, RIPNG_ROUTE_REDISTRIBUTE,
|
||||
(struct prefix_ipv6 *)&api.prefix,
|
||||
ifindex, &nexthop, api.tag);
|
||||
else
|
||||
ripng_redistribute_delete(api.type, RIPNG_ROUTE_REDISTRIBUTE,
|
||||
&p, ifindex);
|
||||
(struct prefix_ipv6 *)&api.prefix,
|
||||
ifindex);
|
||||
|
||||
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,
|
||||
ripng_redistribute_type_cmd,
|
||||
"redistribute " FRR_REDIST_STR_RIPNGD,
|
||||
@ -452,64 +368,40 @@ void ripng_redistribute_write(struct vty *vty, int config_mode)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
|
||||
if (i != zclient->redist_default
|
||||
&& vrf_bitmap_check(zclient->redist[AFI_IP6][i],
|
||||
VRF_DEFAULT)) {
|
||||
if (config_mode) {
|
||||
for (i = 0; i < ZEBRA_ROUTE_MAX; i++) {
|
||||
if (i == zclient->redist_default
|
||||
|| !vrf_bitmap_check(zclient->redist[AFI_IP6][i],
|
||||
VRF_DEFAULT))
|
||||
continue;
|
||||
|
||||
if (!config_mode) {
|
||||
vty_out(vty, " %s", zebra_route_string(i));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ripng->route_map[i].metric_config) {
|
||||
if (ripng->route_map[i].name)
|
||||
vty_out(vty,
|
||||
" redistribute %s metric %d route-map %s\n",
|
||||
zebra_route_string(i),
|
||||
ripng->route_map[i]
|
||||
.metric,
|
||||
ripng->route_map[i]
|
||||
.name);
|
||||
ripng->route_map[i].metric,
|
||||
ripng->route_map[i].name);
|
||||
else
|
||||
vty_out(vty,
|
||||
" redistribute %s metric %d\n",
|
||||
vty_out(vty, " redistribute %s metric %d\n",
|
||||
zebra_route_string(i),
|
||||
ripng->route_map[i]
|
||||
.metric);
|
||||
ripng->route_map[i].metric);
|
||||
} else {
|
||||
if (ripng->route_map[i].name)
|
||||
vty_out(vty,
|
||||
" redistribute %s route-map %s\n",
|
||||
vty_out(vty, " redistribute %s route-map %s\n",
|
||||
zebra_route_string(i),
|
||||
ripng->route_map[i]
|
||||
.name);
|
||||
ripng->route_map[i].name);
|
||||
else
|
||||
vty_out(vty,
|
||||
" redistribute %s\n",
|
||||
vty_out(vty, " redistribute %s\n",
|
||||
zebra_route_string(i));
|
||||
}
|
||||
} else
|
||||
vty_out(vty, " %s", zebra_route_string(i));
|
||||
}
|
||||
}
|
||||
|
||||
/* RIPng configuration write function. */
|
||||
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_IP6][ZEBRA_ROUTE_RIPNG],
|
||||
VRF_DEFAULT)) {
|
||||
vty_out(vty, "router zebra\n");
|
||||
vty_out(vty, " no redistribute ripng\n");
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Zebra node structure. */
|
||||
static struct cmd_node zebra_node = {
|
||||
ZEBRA_NODE, "%s(config-router)# ",
|
||||
};
|
||||
|
||||
static void ripng_zebra_connected(struct zclient *zclient)
|
||||
{
|
||||
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_address_add = ripng_interface_address_add;
|
||||
zclient->interface_address_delete = ripng_interface_address_delete;
|
||||
zclient->redistribute_route_ipv6_add = ripng_zebra_read_ipv6;
|
||||
zclient->redistribute_route_ipv6_del = ripng_zebra_read_ipv6;
|
||||
|
||||
/* 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);
|
||||
zclient->redistribute_route_add = ripng_zebra_read_route;
|
||||
zclient->redistribute_route_del = ripng_zebra_read_route;
|
||||
|
||||
/* Install command elements to ripng node */
|
||||
install_element(RIPNG_NODE, &ripng_redistribute_type_cmd);
|
||||
|
@ -23,7 +23,7 @@ static bool atexit_registered;
|
||||
|
||||
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)
|
||||
|
@ -53,7 +53,7 @@ static void vty_do_exit(int isexit)
|
||||
thread_master_free(master);
|
||||
closezlog();
|
||||
|
||||
log_memstats_stderr("testcli");
|
||||
log_memstats(stderr, "testcli");
|
||||
if (!isexit)
|
||||
exit(0);
|
||||
}
|
||||
|
@ -88,13 +88,10 @@ extern struct zebra_privs_t zserv_privs;
|
||||
#if !defined(ROUNDUP)
|
||||
|
||||
/*
|
||||
* It's a bug for a platform not to define rounding/alignment for
|
||||
* sockaddrs on the routing socket. This warning really is
|
||||
* intentional, to provoke filing bug reports with operating systems
|
||||
* that don't define RT_ROUNDUP or equivalent.
|
||||
* If you're porting to a platform that changed RT_ROUNDUP but doesn't
|
||||
* have it in its headers, this will break rather obviously and you'll
|
||||
* have to fix it here.
|
||||
*/
|
||||
#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 */
|
||||
#ifdef __APPLE__
|
||||
|
@ -95,8 +95,8 @@ static void zebra_redistribute_default(struct zserv *client, vrf_id_t vrf_id)
|
||||
RNODE_FOREACH_RE(rn, newre)
|
||||
if (CHECK_FLAG(newre->flags, ZEBRA_FLAG_SELECTED)
|
||||
&& newre->distance != DISTANCE_INFINITY)
|
||||
zsend_redistribute_route(1, client, &rn->p, NULL,
|
||||
newre);
|
||||
zsend_redistribute_route(ZEBRA_REDISTRIBUTE_ROUTE_ADD,
|
||||
client, &rn->p, NULL, newre);
|
||||
|
||||
route_unlock_node(rn);
|
||||
}
|
||||
@ -114,7 +114,7 @@ static void zebra_redistribute(struct zserv *client, int type, u_short instance,
|
||||
if (!table)
|
||||
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)
|
||||
{
|
||||
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))
|
||||
continue;
|
||||
|
||||
zsend_redistribute_route(1, client, dst_p, src_p,
|
||||
newre);
|
||||
zsend_redistribute_route(ZEBRA_REDISTRIBUTE_ROUTE_ADD,
|
||||
client, dst_p, src_p, newre);
|
||||
}
|
||||
}
|
||||
|
||||
@ -191,7 +191,8 @@ void redistribute_update(struct prefix *p, struct prefix *src_p,
|
||||
send_redistribute = 1;
|
||||
|
||||
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
|
||||
&& ((re->instance
|
||||
&& redist_check_instance(
|
||||
@ -201,7 +202,8 @@ void redistribute_update(struct prefix *p, struct prefix *src_p,
|
||||
|| vrf_bitmap_check(
|
||||
client->redist[afi][prev_re->type],
|
||||
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))
|
||||
|| vrf_bitmap_check(client->redist[afi][re->type],
|
||||
re->vrf_id)) {
|
||||
zsend_redistribute_route(0, client, p, src_p, re);
|
||||
zsend_redistribute_route(ZEBRA_REDISTRIBUTE_ROUTE_DEL,
|
||||
client, p, src_p, re);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -71,6 +71,27 @@ static int sin_masklen(struct in_addr mask)
|
||||
}
|
||||
#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. */
|
||||
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__
|
||||
if (nexthop->nh_label) {
|
||||
memset(&smpls, 0, sizeof(smpls));
|
||||
smpls.smpls_len = sizeof(smpls);
|
||||
smpls.smpls_family = AF_MPLS;
|
||||
smpls.smpls_label =
|
||||
htonl(nexthop->nh_label->label[0]
|
||||
<< MPLS_LABEL_OFFSET);
|
||||
if (nexthop->nh_label
|
||||
&& !kernel_rtm_add_labels(nexthop->nh_label,
|
||||
&smpls))
|
||||
continue;
|
||||
smplsp = (union sockunion *)&smpls;
|
||||
}
|
||||
#endif
|
||||
|
||||
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 sin_dest, sin_mask, sin_gate;
|
||||
#ifdef __OpenBSD__
|
||||
struct sockaddr_mpls smpls;
|
||||
#endif
|
||||
union sockunion *smplsp = NULL;
|
||||
struct nexthop *nexthop;
|
||||
int nexthop_num = 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;
|
||||
}
|
||||
|
||||
#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,
|
||||
(union sockunion *)mask,
|
||||
gate ? (union sockunion *)&sin_gate : NULL,
|
||||
NULL, ifindex, re->flags, re->metric);
|
||||
smplsp, ifindex, re->flags, re->metric);
|
||||
|
||||
#if 0
|
||||
if (error)
|
||||
|
@ -1589,8 +1589,10 @@ static int fpm_remote_srv_write(struct vty *vty)
|
||||
|
||||
in.s_addr = zfpm_g->fpm_server;
|
||||
|
||||
if (zfpm_g->fpm_server != FPM_DEFAULT_IP
|
||||
|| zfpm_g->fpm_port != FPM_DEFAULT_PORT)
|
||||
if ((zfpm_g->fpm_server != FPM_DEFAULT_IP
|
||||
&& 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),
|
||||
zfpm_g->fpm_port);
|
||||
|
||||
|
@ -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,
|
||||
int len, int pretty)
|
||||
{
|
||||
char *buf_ptr = buf;
|
||||
char label_buf[BUFSIZ];
|
||||
int i;
|
||||
|
||||
buf[0] = '\0';
|
||||
|
||||
if (pretty) {
|
||||
if (num_labels == 1) {
|
||||
label2str(labels[0], buf, len);
|
||||
} else if (num_labels == 2) {
|
||||
label2str(labels[0], buf, len);
|
||||
buf_ptr += strlen(buf);
|
||||
|
||||
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]);
|
||||
for (i = 0; i < num_labels; i++) {
|
||||
if (i != 0)
|
||||
strlcat(buf, "/", len);
|
||||
if (pretty)
|
||||
label2str(labels[i], label_buf, sizeof(label_buf));
|
||||
else
|
||||
snprintf(label_buf, sizeof(label_buf), "%u", labels[i]);
|
||||
strlcat(buf, label_buf, len);
|
||||
}
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
|
@ -37,8 +37,6 @@
|
||||
|
||||
/* Definitions and macros. */
|
||||
|
||||
#define MPLS_MAX_LABELS 2 /* Maximum # labels that can be pushed. */
|
||||
|
||||
#define NHLFE_FAMILY(nhlfe) \
|
||||
(((nhlfe)->nexthop->type == NEXTHOP_TYPE_IPV6 \
|
||||
|| (nhlfe)->nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX) \
|
||||
|
@ -256,6 +256,15 @@ static int kernel_lsp_cmd(int action, zebra_lsp_t *lsp)
|
||||
|| (action == RTM_DELETE
|
||||
&& (CHECK_FLAG(nhlfe->flags, NHLFE_FLAG_INSTALLED)
|
||||
&& 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++;
|
||||
|
||||
switch (NHLFE_FAMILY(nhlfe)) {
|
||||
|
@ -22,11 +22,13 @@
|
||||
#ifndef __ZEBRA_STATIC_H__
|
||||
#define __ZEBRA_STATIC_H__
|
||||
|
||||
#include "zebra/zebra_mpls.h"
|
||||
|
||||
/* Static route label information */
|
||||
struct static_nh_label {
|
||||
u_int8_t num_labels;
|
||||
u_int8_t reserved[3];
|
||||
mpls_label_t label[2];
|
||||
mpls_label_t label[MPLS_MAX_LABELS];
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
|
@ -1705,16 +1705,14 @@ static int static_config(struct vty *vty, afi_t afi, safi_t safi,
|
||||
inet_ntop(AF_INET,
|
||||
&si->addr.ipv4, buf,
|
||||
sizeof buf),
|
||||
ifindex2ifname(si->ifindex,
|
||||
si->vrf_id));
|
||||
si->ifname);
|
||||
break;
|
||||
case STATIC_IPV6_GATEWAY_IFNAME:
|
||||
vty_out(vty, " %s %s",
|
||||
inet_ntop(AF_INET6,
|
||||
&si->addr.ipv6, buf,
|
||||
sizeof buf),
|
||||
ifindex2ifname(si->ifindex,
|
||||
si->vrf_id));
|
||||
si->ifname);
|
||||
break;
|
||||
}
|
||||
|
||||
|
519
zebra/zserv.c
519
zebra/zserv.c
@ -592,193 +592,76 @@ int zsend_interface_update(int cmd, struct zserv *client, struct interface *ifp)
|
||||
return zebra_server_send_message(client);
|
||||
}
|
||||
|
||||
/*
|
||||
* 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,
|
||||
int zsend_redistribute_route(int cmd, struct zserv *client, struct prefix *p,
|
||||
struct prefix *src_p, struct route_entry *re)
|
||||
{
|
||||
afi_t afi;
|
||||
int cmd;
|
||||
int psize;
|
||||
struct stream *s;
|
||||
struct zapi_route api;
|
||||
struct zapi_nexthop *api_nh;
|
||||
struct nexthop *nexthop;
|
||||
unsigned long nhnummark = 0, messmark = 0;
|
||||
int nhnum = 0;
|
||||
u_char zapi_flags = 0;
|
||||
struct nexthop dummy_nh;
|
||||
int count = 0;
|
||||
|
||||
afi = family2afi(p->family);
|
||||
if (add) {
|
||||
switch (afi) {
|
||||
case AFI_IP:
|
||||
cmd = ZEBRA_REDISTRIBUTE_IPV4_ADD;
|
||||
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);
|
||||
memset(&api, 0, sizeof(api));
|
||||
api.vrf_id = VRF_DEFAULT;
|
||||
api.type = re->type;
|
||||
api.instance = re->instance;
|
||||
api.flags = re->flags;
|
||||
|
||||
/* Prefix. */
|
||||
psize = PSIZE(p->prefixlen);
|
||||
stream_putc(s, p->prefixlen);
|
||||
stream_write(s, (u_char *)&p->u.prefix, psize);
|
||||
|
||||
api.prefix = *p;
|
||||
if (src_p) {
|
||||
SET_FLAG(zapi_flags, ZAPI_MESSAGE_SRCPFX);
|
||||
psize = PSIZE(src_p->prefixlen);
|
||||
stream_putc(s, src_p->prefixlen);
|
||||
stream_write(s, (u_char *)&src_p->u.prefix, psize);
|
||||
SET_FLAG(api.message, ZAPI_MESSAGE_SRCPFX);
|
||||
memcpy(&api.src_prefix, src_p, sizeof(api.src_prefix));
|
||||
}
|
||||
|
||||
/* 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) {
|
||||
/* We don't send any nexthops when there's a multipath */
|
||||
if (re->nexthop_active_num > 1
|
||||
&& client->proto != ZEBRA_ROUTE_LDP) {
|
||||
SET_FLAG(zapi_flags, ZAPI_MESSAGE_NEXTHOP);
|
||||
SET_FLAG(zapi_flags, ZAPI_MESSAGE_IFINDEX);
|
||||
|
||||
stream_putc(s, 1);
|
||||
if (p->family == AF_INET) {
|
||||
stream_put_in_addr(s, &dummy_nh.gate.ipv4);
|
||||
} else if (p->family == AF_INET6) {
|
||||
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;
|
||||
}
|
||||
|
||||
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++;
|
||||
if (!CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE))
|
||||
continue;
|
||||
|
||||
api_nh = &api.nexthops[count];
|
||||
api_nh->type = nexthop->type;
|
||||
switch (nexthop->type) {
|
||||
case NEXTHOP_TYPE_BLACKHOLE:
|
||||
break;
|
||||
case NEXTHOP_TYPE_IPV4:
|
||||
api_nh->gate.ipv4 = nexthop->gate.ipv4;
|
||||
break;
|
||||
case NEXTHOP_TYPE_IPV4_IFINDEX:
|
||||
stream_put_in_addr(s, &nexthop->gate.ipv4);
|
||||
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:
|
||||
/* 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);
|
||||
api_nh->gate.ipv6 = nexthop->gate.ipv6;
|
||||
api_nh->ifindex = nexthop->ifindex;
|
||||
}
|
||||
count++;
|
||||
}
|
||||
|
||||
/* Interface index. */
|
||||
stream_putc(s, 1);
|
||||
stream_putl(s, nexthop->ifindex);
|
||||
|
||||
/* ldpd needs all nexthops */
|
||||
if (client->proto != ZEBRA_ROUTE_LDP)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Distance */
|
||||
SET_FLAG(zapi_flags, ZAPI_MESSAGE_DISTANCE);
|
||||
stream_putc(s, re->distance);
|
||||
|
||||
/* Metric */
|
||||
SET_FLAG(zapi_flags, ZAPI_MESSAGE_METRIC);
|
||||
stream_putl(s, re->metric);
|
||||
|
||||
/* Tag */
|
||||
/* Attributes. */
|
||||
SET_FLAG(api.message, ZAPI_MESSAGE_DISTANCE);
|
||||
api.distance = re->distance;
|
||||
SET_FLAG(api.message, ZAPI_MESSAGE_METRIC);
|
||||
api.metric = re->metric;
|
||||
if (re->tag) {
|
||||
SET_FLAG(zapi_flags, ZAPI_MESSAGE_TAG);
|
||||
stream_putl(s, re->tag);
|
||||
SET_FLAG(api.message, ZAPI_MESSAGE_TAG);
|
||||
api.tag = re->tag;
|
||||
}
|
||||
SET_FLAG(api.message, ZAPI_MESSAGE_MTU);
|
||||
api.mtu = re->mtu;
|
||||
|
||||
/* MTU */
|
||||
SET_FLAG(zapi_flags, ZAPI_MESSAGE_MTU);
|
||||
stream_putl(s, re->mtu);
|
||||
|
||||
/* 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));
|
||||
|
||||
/* Encode route and send. */
|
||||
if (zapi_route_encode(cmd, client->obuf, &api) < 0)
|
||||
return -1;
|
||||
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. */
|
||||
/*
|
||||
* 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;
|
||||
safi_t safi;
|
||||
int ret;
|
||||
enum lsp_types_t label_type = ZEBRA_LSP_NONE;
|
||||
mpls_label_t label;
|
||||
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,
|
||||
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++) {
|
||||
nexthop_type = stream_getc(s);
|
||||
|
||||
@ -1224,8 +1250,7 @@ static int zread_ipv4_add(struct zserv *client, u_short length,
|
||||
* by label. */
|
||||
if (CHECK_FLAG(message, ZAPI_MESSAGE_LABEL)) {
|
||||
label = (mpls_label_t)stream_getl(s);
|
||||
nexthop_add_labels(
|
||||
nexthop, nexthop->nh_label_type,
|
||||
nexthop_add_labels(nexthop, label_type,
|
||||
1, &label);
|
||||
}
|
||||
break;
|
||||
@ -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,
|
||||
struct zebra_vrf *zvrf)
|
||||
{
|
||||
int i;
|
||||
struct stream *s;
|
||||
struct zapi_ipv4 api;
|
||||
struct in_addr nexthop;
|
||||
union g_addr *nexthop_p;
|
||||
unsigned long ifindex;
|
||||
struct prefix p;
|
||||
u_char nexthop_num;
|
||||
u_char nexthop_type;
|
||||
u_int32_t table_id;
|
||||
|
||||
s = client->ibuf;
|
||||
ifindex = 0;
|
||||
nexthop.s_addr = 0;
|
||||
nexthop_p = NULL;
|
||||
|
||||
/* Type, flags, message. */
|
||||
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);
|
||||
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;
|
||||
|
||||
rib_delete(AFI_IP, api.safi, zvrf_id(zvrf), api.type, api.instance,
|
||||
api.flags, &p, NULL, nexthop_p, ifindex, table_id,
|
||||
api.metric);
|
||||
api.flags, &p, NULL, NULL, 0, table_id, 0);
|
||||
client->v4_route_del_cnt++;
|
||||
return 0;
|
||||
}
|
||||
@ -1401,6 +1364,7 @@ static int zread_ipv4_route_ipv6_nexthop_add(struct zserv *client,
|
||||
static unsigned int ifindices[MULTIPATH_NUM];
|
||||
int ret;
|
||||
static mpls_label_t labels[MULTIPATH_NUM];
|
||||
enum lsp_types_t label_type = ZEBRA_LSP_NONE;
|
||||
mpls_label_t label;
|
||||
struct nexthop *nexthop;
|
||||
|
||||
@ -1441,6 +1405,10 @@ static int zread_ipv4_route_ipv6_nexthop_add(struct zserv *client,
|
||||
nexthop_num = stream_getc(s);
|
||||
zserv_nexthop_num_warn(__func__, (const struct prefix *)&p,
|
||||
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++) {
|
||||
nexthop_type = stream_getc(s);
|
||||
|
||||
@ -1485,8 +1453,7 @@ static int zread_ipv4_route_ipv6_nexthop_add(struct zserv *client,
|
||||
re, &nexthops[i]);
|
||||
|
||||
if (CHECK_FLAG(message, ZAPI_MESSAGE_LABEL))
|
||||
nexthop_add_labels(
|
||||
nexthop, nexthop->nh_label_type,
|
||||
nexthop_add_labels(nexthop, label_type,
|
||||
1, &labels[i]);
|
||||
} else {
|
||||
if ((i < if_count) && ifindices[i])
|
||||
@ -1534,6 +1501,7 @@ static int zread_ipv6_add(struct zserv *client, u_short length,
|
||||
unsigned int i;
|
||||
struct stream *s;
|
||||
struct in6_addr nhop_addr;
|
||||
ifindex_t ifindex;
|
||||
struct route_entry *re;
|
||||
u_char message;
|
||||
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];
|
||||
int ret;
|
||||
static mpls_label_t labels[MULTIPATH_NUM];
|
||||
enum lsp_types_t label_type = ZEBRA_LSP_NONE;
|
||||
mpls_label_t label;
|
||||
struct nexthop *nexthop;
|
||||
|
||||
@ -1591,6 +1560,10 @@ static int zread_ipv6_add(struct zserv *client, u_short length,
|
||||
nexthop_num = stream_getc(s);
|
||||
zserv_nexthop_num_warn(__func__, (const struct prefix *)&p,
|
||||
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++) {
|
||||
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;
|
||||
}
|
||||
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:
|
||||
if (if_count < multipath_num) {
|
||||
ifindices[if_count++] = stream_getl(s);
|
||||
@ -1633,8 +1612,7 @@ static int zread_ipv6_add(struct zserv *client, u_short length,
|
||||
nexthop = route_entry_nexthop_ipv6_add(
|
||||
re, &nexthops[i]);
|
||||
if (CHECK_FLAG(message, ZAPI_MESSAGE_LABEL))
|
||||
nexthop_add_labels(
|
||||
nexthop, nexthop->nh_label_type,
|
||||
nexthop_add_labels(nexthop, label_type,
|
||||
1, &labels[i]);
|
||||
} else {
|
||||
if ((i < if_count) && ifindices[i])
|
||||
@ -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,
|
||||
struct zebra_vrf *zvrf)
|
||||
{
|
||||
int i;
|
||||
struct stream *s;
|
||||
struct zapi_ipv6 api;
|
||||
struct in6_addr nexthop;
|
||||
union g_addr *pnexthop = NULL;
|
||||
unsigned long ifindex;
|
||||
struct prefix p;
|
||||
struct prefix_ipv6 src_p, *src_pp;
|
||||
|
||||
s = client->ibuf;
|
||||
ifindex = 0;
|
||||
memset(&nexthop, 0, sizeof(struct in6_addr));
|
||||
|
||||
/* Type, flags, message. */
|
||||
api.type = stream_getc(s);
|
||||
@ -1716,59 +1688,8 @@ static int zread_ipv6_delete(struct zserv *client, u_short length,
|
||||
} else
|
||||
src_pp = NULL;
|
||||
|
||||
/* Nexthop, ifindex, distance, metric. */
|
||||
if (CHECK_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP)) {
|
||||
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);
|
||||
rib_delete(AFI_IP6, api.safi, zvrf_id(zvrf), api.type, api.instance,
|
||||
api.flags, &p, src_pp, NULL, 0, client->rtm_table, 0);
|
||||
|
||||
client->v6_route_del_cnt++;
|
||||
return 0;
|
||||
@ -2435,6 +2356,12 @@ static int zebra_client_read(struct thread *thread)
|
||||
case ZEBRA_INTERFACE_DELETE:
|
||||
zread_interface_delete(client, length, zvrf);
|
||||
break;
|
||||
case ZEBRA_ROUTE_ADD:
|
||||
zread_route_add(client, length, zvrf);
|
||||
break;
|
||||
case ZEBRA_ROUTE_DELETE:
|
||||
zread_route_del(client, length, zvrf);
|
||||
break;
|
||||
case ZEBRA_IPV4_ROUTE_ADD:
|
||||
zread_ipv4_add(client, length, zvrf);
|
||||
break;
|
||||
@ -2444,14 +2371,6 @@ static int zebra_client_read(struct thread *thread)
|
||||
case ZEBRA_IPV4_ROUTE_IPV6_NEXTHOP_ADD:
|
||||
zread_ipv4_route_ipv6_nexthop_add(client, length, zvrf);
|
||||
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:
|
||||
zread_ipv6_add(client, length, zvrf);
|
||||
break;
|
||||
|
Loading…
Reference in New Issue
Block a user