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

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

View File

@ -5,7 +5,7 @@ include common.am
AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/lib -I$(top_builddir) -I$(top_builddir)/lib
AM_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

View File

@ -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)
{

View File

@ -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);

View File

@ -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

View File

@ -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.",

View File

@ -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;
}

View File

@ -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);

View File

@ -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

View File

@ -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);
}

View File

@ -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);

View File

@ -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);

View File

@ -7081,26 +7081,6 @@ static int bgp_show_summary(struct vty *vty, struct bgp *bgp, int afi, int safi,
return CMD_SUCCESS;
}
/*
* Return 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) {
/*

View File

@ -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);

View File

@ -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))

View File

@ -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);

View File

@ -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)

View File

@ -13,8 +13,7 @@ CLIPPY_DEPS = $(HOSTTOOLS)lib/clippy $(top_srcdir)/python/clidef.py
SUFFIXES = _clippy.c .proto .pb-c.c .pb-c.h .pb.h
.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:

View File

@ -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);

View File

@ -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;

View File

@ -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 */

View File

@ -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;

View File

@ -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);
}

View File

@ -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 */

View File

@ -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);

View File

@ -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 *);

View File

@ -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)
{

View File

@ -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);

View File

@ -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;

View File

@ -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);

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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_ */

View File

@ -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);
}
}

View File

@ -49,7 +49,7 @@ extern void eigrp_neighbor_entry_delete(struct eigrp_prefix_entry *,
extern void eigrp_topology_delete_all(struct list *);
extern 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,

View File

@ -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

View File

@ -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);

View File

@ -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;

View File

@ -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);

View File

@ -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')

View File

@ -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 */

View File

@ -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);

View File

@ -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;
}

View File

@ -347,14 +347,14 @@ int area_net_title(struct vty *vty, const char *net_title)
"area address must be at least 8..20 octets long (%d)\n",
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);

View File

@ -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;
}

View File

@ -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);

View File

@ -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
View File

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

View File

@ -404,7 +404,8 @@ DEFUN (grammar_findambig,
nodegraph = cnode->cmdgraph;
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);

View File

@ -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);
}
}

View File

@ -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 */

View File

@ -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),

View File

@ -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;
}

View File

@ -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);

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -48,6 +48,7 @@ extern void prefix_list_add_hook(void (*func)(struct prefix_list *));
extern void prefix_list_delete_hook(void (*func)(struct prefix_list *));
extern 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 *);

View File

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

View File

@ -33,28 +33,13 @@
#endif
#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)));

View File

@ -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();
}

View File

@ -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);
}

View File

@ -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 \

View File

@ -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);

View File

@ -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 */

View File

@ -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.")

View File

@ -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)

View File

@ -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 */

View File

@ -86,14 +86,20 @@ void nhrp_route_update_nhrp(const struct prefix *p, struct interface *ifp)
void nhrp_route_announce(int add, enum nhrp_cache_type type, const struct prefix *p, struct interface *ifp, const union sockunion *nexthop, uint32_t mtu)
{
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]);
}

View File

@ -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

View File

@ -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",

View File

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

View File

@ -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);

View File

@ -285,8 +285,7 @@ void ospf6_add_nexthop(struct list *nh_list, int ifindex, struct in6_addr *addr)
}
void ospf6_route_zebra_copy_nexthops(struct ospf6_route *route,
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++;
}
}
}

View File

@ -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);

View File

@ -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 */

View File

@ -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);

View File

@ -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);
}

View File

@ -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);

View File

@ -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,

View File

@ -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;
}
}

View File

@ -151,8 +151,7 @@ void pim_ifchannel_update_assert_tracking_desired(struct pim_ifchannel *ch);
void pim_ifchannel_scan_forward_start(struct interface *new_ifp);
void pim_ifchannel_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);

View File

@ -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;

View File

@ -1624,8 +1624,9 @@ static void pim_upstream_sg_running(void *arg)
// No packet can have arrived here if this is the case
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;
}

View File

@ -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__)])

View 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)

View File

@ -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);

View File

@ -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);

View File

@ -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)

View File

@ -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);
}

View File

@ -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__

View File

@ -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);
}
}
}

View File

@ -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)

View File

@ -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);

View File

@ -1671,27 +1671,20 @@ int mpls_str2label(const char *label_str, u_int8_t *num_labels,
char *mpls_label2str(u_int8_t num_labels, mpls_label_t *labels, char *buf,
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;
}

View File

@ -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) \

View File

@ -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)) {

View File

@ -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 {

View File

@ -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;
}

View File

@ -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;