merge with upstream

This commit is contained in:
tmartiro 2017-07-17 17:23:20 +03:00
commit a8a4fa8954
739 changed files with 269781 additions and 267777 deletions

25
.clang-format Normal file
View File

@ -0,0 +1,25 @@
---
BasedOnStyle: LLVM
Language: Cpp
IndentWidth: 8
UseTab: Always
BreakBeforeBraces: Linux
AlwaysBreakBeforeMultilineStrings: true
AllowShortIfStatementsOnASingleLine: false
AllowShortLoopsOnASingleLine: false
AllowShortFunctionsOnASingleLine: false
IndentCaseLabels: false
AlignEscapedNewlinesLeft: false
AlignTrailingComments: true
AllowAllParametersOfDeclarationOnNextLine: false
AlignAfterOpenBracket: true
SpaceAfterCStyleCast: false
MaxEmptyLinesToKeep: 2
BreakBeforeBinaryOperators: NonAssignment
BreakStringLiterals: false
SortIncludes: false
IncludeCategories:
- Regex: '^(<|lib)'
Priority: 0
CommentPragmas: '\$(FRR|clippy)'
ContinuationIndentWidth: 8

24
.gitignore vendored
View File

@ -48,18 +48,18 @@ m4/*.m4
debian/autoreconf.after
debian/autoreconf.before
debian/files
debian/quagga-dbg.debhelper.log
debian/quagga-dbg.substvars
debian/quagga-dbg/
debian/quagga-doc.debhelper.log
debian/quagga-doc.substvars
debian/quagga-doc/
debian/quagga.debhelper.log
debian/quagga.postinst.debhelper
debian/quagga.postrm.debhelper
debian/quagga.prerm.debhelper
debian/quagga.substvars
debian/quagga/
debian/frr-dbg.debhelper.log
debian/frr-dbg.substvars
debian/frr-dbg/
debian/frr-doc.debhelper.log
debian/frr-doc.substvars
debian/frr-doc/
debian/frr.debhelper.log
debian/frr.postinst.debhelper
debian/frr.postrm.debhelper
debian/frr.prerm.debhelper
debian/frr.substvars
debian/frr/
debian/tmp/
*.pyc
*.swp

View File

@ -380,3 +380,36 @@ CLI's are a complicated ugly beast. Additions or changes to the CLI
should use a DEFUN to encapsulate one setting as much as is possible.
Additionally as new DEFUN's are added to the system, documentation
should be provided for the new commands.
### Backwards Compatibility
As a general principle, changes to CLI and code in the lib/ directory
should be made in a backwards compatible fashion. This means that
changes that are purely stylistic in nature should be avoided, e.g.,
renaming an existing macro or library function name without any
functional change. When adding new parameters to common functions, it is
also good to consider if this too should be done in a backward
compatible fashion, e.g., by preserving the old form in addition to
adding the new form.
This is not to say that minor or even major functional changes to CLI
and common code should be avoided, but rather that the benefit gained
from a change should be weighed against the added cost/complexity to
existing code. Also, that when making such changes, it is good to
preserve compatibility when possible to do so without introducing
maintenance overhead/cost. It is also important to keep in mind,
existing code includes code that may reside in private repositories (and
is yet to be submitted) or code that has yet to be migrated from Quagga
to FRR.
That said, compatibility measures can (and should) be removed when either:
* they become a significant burden, e.g. when data structures change and
the compatibility measure would need a complex adaptation layer or becomes
flat-out impossible
* some measure of time (dependent on the specific case) has passed, so that
the compatibility grace period is considered expired.
In all cases, compatibility pieces should be marked with compiler/preprocessor
annotations to print warnings at compile time, pointing to the appropriate
update path. A `-Werror` build should fail if compatibility bits are used.

View File

@ -8,9 +8,8 @@ SUBDIRS = lib qpb fpm @ZEBRA@ @LIBRFP@ @RFPTEST@ \
DIST_SUBDIRS = lib qpb fpm zebra bgpd ripd ripngd ospfd ospf6d ldpd \
isisd watchfrr vtysh ospfclient doc m4 pkgsrc redhat tests \
solaris pimd nhrpd eigrpd @LIBRFP@ @RFPTEST@ tools snapcraft \
babeld \
python \
solaris pimd nhrpd eigrpd bgpd/rfp-example/librfp \
bgpd/rfp-example/rfptest tools snapcraft babeld python \
# end
EXTRA_DIST = aclocal.m4 SERVICES REPORTING-BUGS \

View File

@ -1,18 +1,18 @@
#!/bin/sh
# This file is helpful for building quagga from cvs on NetBSD, and
# This file is helpful for building FRR from cvs on NetBSD, and
# probably on any system using pkgsrc.
# One should have readline installed already (pkgsrc/devel/readline).
MAKE=make
# Quagga is currently documented not to require GNU make, but sometimes
# FRR is currently documented not to require GNU make, but sometimes
# BSD make fails. Enable this if statement as a workaround.
if false; then
MAKE=gmake
echo "WARNING: using gmake to work around nonportable makefiles"
fi
# Use /usr/quagga to be independent, and /usr/pkg to overwrite pkgsrc.
# Use /usr/frr to be independent, and /usr/pkg to overwrite pkgsrc.
PREFIX=/usr/pkg
case $1 in

View File

@ -16,7 +16,7 @@ Please supply the following information:
1. Your FRRouting version or if it is from git then the commit reference.
Please try to report bugs against git master or the latest release.
2. FRR daemons you run e.g. bgpd or ripd and full name of your OS. Any
specific options you compiled Quagga with.
specific options you compiled FRR with.
3. Problem description. Copy and paste relative commands and their output to
describe your network setup e.g. "zebra>show ip route".
Please, also give your simple network layout and output of relative OS

View File

@ -290,9 +290,9 @@ DEFUN (babel_network,
ret = babel_enable_if_add (argv[1]->arg);
if (ret < 0) {
vty_outln (vty, "There is same network configuration %s",
vty_out (vty, "There is same network configuration %s\n",
argv[1]->arg);
return CMD_WARNING;
return CMD_WARNING_CONFIG_FAILED;
}
return CMD_SUCCESS;
@ -318,8 +318,8 @@ DEFUN (no_babel_network,
ret = babel_enable_if_delete (argv[2]->arg);
if (ret < 0) {
vty_outln (vty, "can't find network %s",argv[2]->arg);
return CMD_WARNING;
vty_out (vty, "can't find network %s\n",argv[2]->arg);
return CMD_WARNING_CONFIG_FAILED;
}
return CMD_SUCCESS;
@ -861,31 +861,31 @@ show_babel_interface_sub (struct vty *vty, struct interface *ifp)
int is_up;
babel_interface_nfo *babel_ifp;
vty_outln (vty, "%s is %s", ifp->name,
vty_out (vty, "%s is %s\n", ifp->name,
((is_up = if_is_operative(ifp)) ? "up" : "down"));
vty_outln (vty, " ifindex %u, MTU %u bytes %s",
vty_out (vty, " ifindex %u, MTU %u bytes %s\n",
ifp->ifindex, MIN(ifp->mtu, ifp->mtu6), if_flag_dump(ifp->flags));
if (!IS_ENABLE(ifp))
{
vty_outln (vty, " Babel protocol is not enabled on this interface");
vty_out (vty, " Babel protocol is not enabled on this interface\n");
return;
}
if (!is_up)
{
vty_outln (vty,
" Babel protocol is enabled, but not running on this interface");
vty_out (vty,
" Babel protocol is enabled, but not running on this interface\n");
return;
}
babel_ifp = babel_get_if_nfo (ifp);
vty_outln (vty, " Babel protocol is running on this interface");
vty_outln (vty, " Operating mode is \"%s\"",
vty_out (vty, " Babel protocol is running on this interface\n");
vty_out (vty, " Operating mode is \"%s\"\n",
CHECK_FLAG(babel_ifp->flags, BABEL_IF_WIRED) ? "wired" : "wireless");
vty_outln (vty, " Split horizon mode is %s",
vty_out (vty, " Split horizon mode is %s\n",
CHECK_FLAG(babel_ifp->flags, BABEL_IF_SPLIT_HORIZON) ? "On" : "Off");
vty_outln (vty, " Hello interval is %u ms", babel_ifp->hello_interval);
vty_outln (vty, " Update interval is %u ms", babel_ifp->update_interval);
vty_outln (vty, " Rxcost multiplier is %u", babel_ifp->cost);
vty_out (vty, " Hello interval is %u ms\n", babel_ifp->hello_interval);
vty_out (vty, " Update interval is %u ms\n", babel_ifp->update_interval);
vty_out (vty, " Rxcost multiplier is %u\n", babel_ifp->cost);
}
DEFUN (show_babel_interface,
@ -907,7 +907,7 @@ DEFUN (show_babel_interface,
}
if ((ifp = if_lookup_by_name (argv[3]->arg, VRF_DEFAULT)) == NULL)
{
vty_outln (vty, "No such interface name");
vty_out (vty, "No such interface name\n");
return CMD_WARNING;
}
show_babel_interface_sub (vty, ifp);
@ -917,9 +917,9 @@ DEFUN (show_babel_interface,
static void
show_babel_neighbour_sub (struct vty *vty, struct neighbour *neigh)
{
vty_outln (vty,
vty_out (vty,
"Neighbour %s dev %s reach %04x rxcost %d txcost %d "
"rtt %s rttcost %d%s.",
"rtt %s rttcost %d%s.\n",
format_address(neigh->address),
neigh->ifp->name,
neigh->reach,
@ -949,7 +949,7 @@ DEFUN (show_babel_neighbour,
}
if ((ifp = if_lookup_by_name (argv[3]->arg, VRF_DEFAULT)) == NULL)
{
vty_outln (vty, "No such interface name");
vty_out (vty, "No such interface name\n");
return CMD_WARNING;
}
FOR_ALL_NEIGHBOURS(neigh) {
@ -1009,9 +1009,9 @@ show_babel_routes_sub(struct babel_route *route, struct vty *vty,
channels[0] = '\0';
}
vty_outln (vty,
vty_out (vty,
"%s metric %d refmetric %d id %s seqno %d%s age %d "
"via %s neigh %s%s%s%s",
"via %s neigh %s%s%s%s\n",
format_prefix(route->src->prefix, route->src->plen),
route_metric(route), route->refmetric,
format_eui64(route->src->id),
@ -1032,7 +1032,7 @@ show_babel_xroutes_sub (struct xroute *xroute, struct vty *vty,
if(prefix && !babel_prefix_eq(prefix, xroute->prefix, xroute->plen))
return;
vty_outln (vty, "%s metric %d (exported)",
vty_out (vty, "%s metric %d (exported)\n",
format_prefix(xroute->prefix, xroute->plen),
xroute->metric);
}
@ -1089,7 +1089,7 @@ DEFUN (show_babel_route_prefix,
ret = str2prefix(argv[3]->arg, &prefix);
if(ret == 0) {
vty_outln (vty, "%% Malformed address");
vty_out (vty, "%% Malformed address\n");
return CMD_WARNING;
}
@ -1138,7 +1138,7 @@ DEFUN (show_babel_route_addr,
ret = inet_aton (argv[3]->arg, &addr);
if (ret <= 0) {
vty_outln (vty, "%% Malformed address");
vty_out (vty, "%% Malformed address\n");
return CMD_WARNING;
}
@ -1147,7 +1147,7 @@ DEFUN (show_babel_route_addr,
ret = str2prefix(buf, &prefix);
if (ret == 0) {
vty_outln (vty, "%% Parse error -- this shouldn't happen");
vty_out (vty, "%% Parse error -- this shouldn't happen\n");
return CMD_WARNING;
}
@ -1196,7 +1196,7 @@ DEFUN (show_babel_route_addr6,
ret = inet_pton (AF_INET6, argv[3]->arg, &addr);
if (ret <= 0) {
vty_outln (vty, "%% Malformed address");
vty_out (vty, "%% Malformed address\n");
return CMD_WARNING;
}
@ -1206,7 +1206,7 @@ DEFUN (show_babel_route_addr6,
ret = str2prefix(buf, &prefix);
if (ret == 0) {
vty_outln (vty, "%% Parse error -- this shouldn't happen");
vty_out (vty, "%% Parse error -- this shouldn't happen\n");
return CMD_WARNING;
}
@ -1244,9 +1244,9 @@ DEFUN (show_babel_parameters,
"Babel information\n"
"Configuration information\n")
{
vty_outln (vty, " -- Babel running configuration --");
vty_out (vty, " -- Babel running configuration --\n");
show_babel_main_configuration(vty);
vty_outln (vty, " -- distribution lists --");
vty_out (vty, " -- distribution lists --\n");
config_show_distribute(vty);
return CMD_SUCCESS;
@ -1321,63 +1321,63 @@ interface_config_write (struct vty *vty)
int write = 0;
for (ALL_LIST_ELEMENTS_RO (vrf_iflist(VRF_DEFAULT), node, ifp)) {
vty_outln (vty, "interface %s",ifp->name);
vty_out (vty, "interface %s\n",ifp->name);
if (ifp->desc)
vty_outln (vty, " description %s",ifp->desc);
vty_out (vty, " description %s\n",ifp->desc);
babel_interface_nfo *babel_ifp = babel_get_if_nfo (ifp);
/* wireless is the default*/
if (CHECK_FLAG (babel_ifp->flags, BABEL_IF_WIRED))
{
vty_outln (vty, " babel wired");
vty_out (vty, " babel wired\n");
write++;
}
if (babel_ifp->hello_interval != BABEL_DEFAULT_HELLO_INTERVAL)
{
vty_outln (vty, " babel hello-interval %u",
vty_out (vty, " babel hello-interval %u\n",
babel_ifp->hello_interval);
write++;
}
if (babel_ifp->update_interval != BABEL_DEFAULT_UPDATE_INTERVAL)
{
vty_outln (vty, " babel update-interval %u",
vty_out (vty, " babel update-interval %u\n",
babel_ifp->update_interval);
write++;
}
/* Some parameters have different defaults for wired/wireless. */
if (CHECK_FLAG (babel_ifp->flags, BABEL_IF_WIRED)) {
if (!CHECK_FLAG (babel_ifp->flags, BABEL_IF_SPLIT_HORIZON)) {
vty_outln (vty, " no babel split-horizon");
vty_out (vty, " no babel split-horizon\n");
write++;
}
if (babel_ifp->cost != BABEL_DEFAULT_RXCOST_WIRED) {
vty_outln (vty, " babel rxcost %u", babel_ifp->cost);
vty_out (vty, " babel rxcost %u\n", babel_ifp->cost);
write++;
}
if (babel_ifp->channel == BABEL_IF_CHANNEL_INTERFERING) {
vty_outln (vty, " babel channel interfering");
vty_out (vty, " babel channel interfering\n");
write++;
} else if(babel_ifp->channel != BABEL_IF_CHANNEL_NONINTERFERING) {
vty_outln (vty, " babel channel %d",babel_ifp->channel);
vty_out (vty, " babel channel %d\n",babel_ifp->channel);
write++;
}
} else {
if (CHECK_FLAG (babel_ifp->flags, BABEL_IF_SPLIT_HORIZON)) {
vty_outln (vty, " babel split-horizon");
vty_out (vty, " babel split-horizon\n");
write++;
}
if (babel_ifp->cost != BABEL_DEFAULT_RXCOST_WIRELESS) {
vty_outln (vty, " babel rxcost %u", babel_ifp->cost);
vty_out (vty, " babel rxcost %u\n", babel_ifp->cost);
write++;
}
if (babel_ifp->channel == BABEL_IF_CHANNEL_NONINTERFERING) {
vty_outln (vty, " babel channel noninterfering");
vty_out (vty, " babel channel noninterfering\n");
write++;
} else if(babel_ifp->channel != BABEL_IF_CHANNEL_INTERFERING) {
vty_outln (vty, " babel channel %d",babel_ifp->channel);
vty_out (vty, " babel channel %d\n",babel_ifp->channel);
write++;
}
}
vty_outln (vty, "!");
vty_out (vty, "!\n");
write++;
}
return write;
@ -1393,7 +1393,7 @@ babel_enable_if_config_write (struct vty * vty)
for (i = 0; i < vector_active (babel_enable_if); i++)
if ((str = vector_slot (babel_enable_if, i)) != NULL)
{
vty_outln (vty, " network %s", str);
vty_out (vty, " network %s\n", str);
lines++;
}
return lines;

View File

@ -377,25 +377,22 @@ babel_save_state_file(void)
void
show_babel_main_configuration (struct vty *vty)
{
vty_outln (vty,
"state file = %s%s"
"configuration file = %s%s"
"protocol informations:%s"
" multicast address = %s%s"
" port = %d%s"
"vty address = %s%s"
"vty port = %d%s"
"id = %s%s"
"kernel_metric = %d",
state_file, VTYNL,
vty_out (vty,
"state file = %s\n"
"configuration file = %s\n"
"protocol informations:\n"
" multicast address = %s\n"
" port = %d\n"
"vty address = %s\n"
"vty port = %d\n"
"id = %s\n"
"kernel_metric = %d\n",
state_file,
babel_config_file ? babel_config_file : babel_config_default,
VTYNL,
VTYNL,
format_address(protocol_group), VTYNL,
protocol_port, VTYNL,
format_address(protocol_group),
protocol_port,
babel_vty_addr ? babel_vty_addr : "None",
VTYNL,
babel_vty_port, VTYNL,
format_eui64(myid), VTYNL,
babel_vty_port,
format_eui64(myid),
kernel_metric);
}

View File

@ -222,11 +222,12 @@ DEFUN (babel_redistribute_type,
type = babel_proto_redistnum(argv[1]->arg);
if (type < 0) {
vty_outln (vty, "Invalid type %s", argv[1]->arg);
return CMD_WARNING;
vty_out (vty, "Invalid type %s\n", argv[1]->arg);
return CMD_WARNING_CONFIG_FAILED;
}
zclient_redistribute (ZEBRA_REDISTRIBUTE_ADD, zclient, AFI_IP, type, 0, VRF_DEFAULT);
zclient_redistribute (ZEBRA_REDISTRIBUTE_ADD, zclient, AFI_IP6, type, 0, VRF_DEFAULT);
return CMD_SUCCESS;
}
@ -243,11 +244,12 @@ DEFUN (no_babel_redistribute_type,
type = babel_proto_redistnum(argv[2]->arg);
if (type < 0) {
vty_outln (vty, "Invalid type %s", argv[2]->arg);
return CMD_WARNING;
vty_out (vty, "Invalid type %s\n", argv[2]->arg);
return CMD_WARNING_CONFIG_FAILED;
}
zclient_redistribute (ZEBRA_REDISTRIBUTE_DELETE, zclient, AFI_IP, type, 0, VRF_DEFAULT);
zclient_redistribute (ZEBRA_REDISTRIBUTE_DELETE, zclient, AFI_IP6, type, 0, VRF_DEFAULT);
/* perhaps should we remove xroutes having the same type... */
return CMD_SUCCESS;
}
@ -277,9 +279,9 @@ DEFUN (debug_babel,
}
}
vty_outln (vty, "Invalid type %s", argv[2]->arg);
vty_out (vty, "Invalid type %s\n", argv[2]->arg);
return CMD_WARNING;
return CMD_WARNING_CONFIG_FAILED;
}
/* [Babel Command] */
@ -307,9 +309,9 @@ DEFUN (no_debug_babel,
}
}
vty_outln (vty, "Invalid type %s", argv[3]->arg);
vty_out (vty, "Invalid type %s\n", argv[3]->arg);
return CMD_WARNING;
return CMD_WARNING_CONFIG_FAILED;
}
#endif /* NO_DEBUG */
@ -324,7 +326,7 @@ debug_babel_config_write (struct vty * vty)
if (debug == BABEL_DEBUG_ALL)
{
vty_outln (vty, "debug babel all");
vty_out (vty, "debug babel all\n");
lines++;
}
else
@ -335,12 +337,12 @@ debug_babel_config_write (struct vty * vty)
&& CHECK_FLAG (debug, debug_type[i].type)
)
{
vty_outln (vty, "debug babel %s", debug_type[i].str);
vty_out (vty, "debug babel %s\n", debug_type[i].str);
lines++;
}
if (lines)
{
vty_outln (vty, "!");
vty_out (vty, "!\n");
lines++;
}
return lines;
@ -384,13 +386,13 @@ zebra_config_write (struct vty *vty)
{
if (! zclient->enable)
{
vty_outln (vty, "no router zebra");
vty_out (vty, "no router zebra\n");
return 1;
}
else if (! vrf_bitmap_check (zclient->redist[AFI_IP][ZEBRA_ROUTE_BABEL], VRF_DEFAULT))
{
vty_outln (vty, "router zebra");
vty_outln (vty, " no redistribute babel");
vty_out (vty, "router zebra\n");
vty_out (vty, " no redistribute babel\n");
return 1;
}
return 0;

View File

@ -83,25 +83,25 @@ babel_config_write (struct vty *vty)
if (!babel_routing_process)
return lines;
vty_outln (vty, "router babel");
vty_out (vty, "router babel\n");
if (diversity_kind != DIVERSITY_NONE)
{
vty_outln (vty, " babel diversity");
vty_out (vty, " babel diversity\n");
lines++;
}
if (diversity_factor != BABEL_DEFAULT_DIVERSITY_FACTOR)
{
vty_outln (vty, " babel diversity-factor %d",diversity_factor);
vty_out (vty, " babel diversity-factor %d\n",diversity_factor);
lines++;
}
if (resend_delay != BABEL_DEFAULT_RESEND_DELAY)
{
vty_outln (vty, " babel resend-delay %u", resend_delay);
vty_out (vty, " babel resend-delay %u\n", resend_delay);
lines++;
}
if (smoothing_half_life != BABEL_DEFAULT_SMOOTHING_HALF_LIFE)
{
vty_outln (vty, " babel smoothing-half-life %u",
vty_out (vty, " babel smoothing-half-life %u\n",
smoothing_half_life);
lines++;
}
@ -112,7 +112,7 @@ babel_config_write (struct vty *vty)
if (i != zclient->redist_default &&
vrf_bitmap_check (zclient->redist[AFI_IP][i], VRF_DEFAULT))
{
vty_outln (vty, " redistribute %s", zebra_route_string(i));
vty_out (vty, " redistribute %s\n", zebra_route_string(i));
lines++;
}
@ -617,8 +617,7 @@ DEFUN (no_router_babel,
"no router babel",
NO_STR
"Disable a routing process\n"
"Remove Babel instance command\n"
"No attributes\n")
"Remove Babel instance command\n")
{
if(babel_routing_process)
babel_clean_routing_process();

View File

@ -83,7 +83,7 @@ libbgp_a_SOURCES = \
bgp_damp.c bgp_table.c bgp_advertise.c bgp_vty.c bgp_mpath.c \
bgp_nht.c bgp_updgrp.c bgp_updgrp_packet.c bgp_updgrp_adv.c bgp_bfd.c \
bgp_encap_tlv.c $(BGP_VNC_RFAPI_SRC) bgp_attr_evpn.c \
bgp_evpn.c bgp_evpn_vty.c bgp_vpn.c bgp_label.c
bgp_evpn.c bgp_evpn_vty.c bgp_vpn.c bgp_label.c bgp_rd.c
noinst_HEADERS = \
bgp_memory.h \
@ -95,7 +95,7 @@ noinst_HEADERS = \
bgp_advertise.h bgp_vty.h bgp_mpath.h bgp_nht.h \
bgp_updgrp.h bgp_bfd.h bgp_encap_tlv.h bgp_encap_types.h \
$(BGP_VNC_RFAPI_HD) bgp_attr_evpn.h bgp_evpn.h bgp_evpn_vty.h \
bgp_vpn.h bgp_label.h
bgp_vpn.h bgp_label.h bgp_rd.h bgp_evpn_private.h
bgpd_SOURCES = bgp_main.c
bgpd_LDADD = libbgp.a $(BGP_VNC_RFP_LIB) ../lib/libfrr.la @LIBCAP@ @LIBM@

View File

@ -43,249 +43,227 @@
/* BGP advertise attribute is used for pack same attribute update into
one packet. To do that we maintain attribute hash in struct
peer. */
struct bgp_advertise_attr *
baa_new (void)
struct bgp_advertise_attr *baa_new(void)
{
return (struct bgp_advertise_attr *)
XCALLOC (MTYPE_BGP_ADVERTISE_ATTR, sizeof (struct bgp_advertise_attr));
return (struct bgp_advertise_attr *)XCALLOC(
MTYPE_BGP_ADVERTISE_ATTR, sizeof(struct bgp_advertise_attr));
}
static void
baa_free (struct bgp_advertise_attr *baa)
static void baa_free(struct bgp_advertise_attr *baa)
{
XFREE (MTYPE_BGP_ADVERTISE_ATTR, baa);
XFREE(MTYPE_BGP_ADVERTISE_ATTR, baa);
}
static void *
baa_hash_alloc (void *p)
static void *baa_hash_alloc(void *p)
{
struct bgp_advertise_attr * ref = (struct bgp_advertise_attr *) p;
struct bgp_advertise_attr *baa;
struct bgp_advertise_attr *ref = (struct bgp_advertise_attr *)p;
struct bgp_advertise_attr *baa;
baa = baa_new ();
baa->attr = ref->attr;
return baa;
baa = baa_new();
baa->attr = ref->attr;
return baa;
}
unsigned int
baa_hash_key (void *p)
unsigned int baa_hash_key(void *p)
{
struct bgp_advertise_attr * baa = (struct bgp_advertise_attr *) p;
struct bgp_advertise_attr *baa = (struct bgp_advertise_attr *)p;
return attrhash_key_make (baa->attr);
return attrhash_key_make(baa->attr);
}
int
baa_hash_cmp (const void *p1, const void *p2)
int baa_hash_cmp(const void *p1, const void *p2)
{
const struct bgp_advertise_attr * baa1 = p1;
const struct bgp_advertise_attr * baa2 = p2;
const struct bgp_advertise_attr *baa1 = p1;
const struct bgp_advertise_attr *baa2 = p2;
return attrhash_cmp (baa1->attr, baa2->attr);
return attrhash_cmp(baa1->attr, baa2->attr);
}
/* BGP update and withdraw information is stored in BGP advertise
structure. This structure is referred from BGP adjacency
information. */
struct bgp_advertise *
bgp_advertise_new (void)
struct bgp_advertise *bgp_advertise_new(void)
{
return (struct bgp_advertise *)
XCALLOC (MTYPE_BGP_ADVERTISE, sizeof (struct bgp_advertise));
return (struct bgp_advertise *)XCALLOC(MTYPE_BGP_ADVERTISE,
sizeof(struct bgp_advertise));
}
void
bgp_advertise_free (struct bgp_advertise *adv)
void bgp_advertise_free(struct bgp_advertise *adv)
{
if (adv->binfo)
bgp_info_unlock (adv->binfo); /* bgp_advertise bgp_info reference */
XFREE (MTYPE_BGP_ADVERTISE, adv);
if (adv->binfo)
bgp_info_unlock(
adv->binfo); /* bgp_advertise bgp_info reference */
XFREE(MTYPE_BGP_ADVERTISE, adv);
}
void
bgp_advertise_add (struct bgp_advertise_attr *baa,
struct bgp_advertise *adv)
void bgp_advertise_add(struct bgp_advertise_attr *baa,
struct bgp_advertise *adv)
{
adv->next = baa->adv;
if (baa->adv)
baa->adv->prev = adv;
baa->adv = adv;
adv->next = baa->adv;
if (baa->adv)
baa->adv->prev = adv;
baa->adv = adv;
}
void
bgp_advertise_delete (struct bgp_advertise_attr *baa,
struct bgp_advertise *adv)
void bgp_advertise_delete(struct bgp_advertise_attr *baa,
struct bgp_advertise *adv)
{
if (adv->next)
adv->next->prev = adv->prev;
if (adv->prev)
adv->prev->next = adv->next;
else
baa->adv = adv->next;
if (adv->next)
adv->next->prev = adv->prev;
if (adv->prev)
adv->prev->next = adv->next;
else
baa->adv = adv->next;
}
struct bgp_advertise_attr *
bgp_advertise_intern (struct hash *hash, struct attr *attr)
struct bgp_advertise_attr *bgp_advertise_intern(struct hash *hash,
struct attr *attr)
{
struct bgp_advertise_attr ref;
struct bgp_advertise_attr *baa;
struct bgp_advertise_attr ref;
struct bgp_advertise_attr *baa;
ref.attr = bgp_attr_intern (attr);
baa = (struct bgp_advertise_attr *) hash_get (hash, &ref, baa_hash_alloc);
baa->refcnt++;
ref.attr = bgp_attr_intern(attr);
baa = (struct bgp_advertise_attr *)hash_get(hash, &ref, baa_hash_alloc);
baa->refcnt++;
return baa;
return baa;
}
void
bgp_advertise_unintern (struct hash *hash, struct bgp_advertise_attr *baa)
void bgp_advertise_unintern(struct hash *hash, struct bgp_advertise_attr *baa)
{
if (baa->refcnt)
baa->refcnt--;
if (baa->refcnt)
baa->refcnt--;
if (baa->refcnt && baa->attr)
bgp_attr_unintern (&baa->attr);
else
{
if (baa->attr)
{
hash_release (hash, baa);
bgp_attr_unintern (&baa->attr);
if (baa->refcnt && baa->attr)
bgp_attr_unintern(&baa->attr);
else {
if (baa->attr) {
hash_release(hash, baa);
bgp_attr_unintern(&baa->attr);
}
baa_free(baa);
}
baa_free (baa);
}
}
int
bgp_adj_out_lookup (struct peer *peer, struct bgp_node *rn,
u_int32_t addpath_tx_id)
int bgp_adj_out_lookup(struct peer *peer, struct bgp_node *rn,
u_int32_t addpath_tx_id)
{
struct bgp_adj_out *adj;
struct peer_af *paf;
afi_t afi;
safi_t safi;
int addpath_capable;
struct bgp_adj_out *adj;
struct peer_af *paf;
afi_t afi;
safi_t safi;
int addpath_capable;
for (adj = rn->adj_out; adj; adj = adj->next)
SUBGRP_FOREACH_PEER(adj->subgroup, paf)
if (paf->peer == peer)
{
afi = SUBGRP_AFI (adj->subgroup);
safi = SUBGRP_SAFI (adj->subgroup);
addpath_capable = bgp_addpath_encode_tx (peer, afi, safi);
for (adj = rn->adj_out; adj; adj = adj->next)
SUBGRP_FOREACH_PEER(adj->subgroup, paf)
if (paf->peer == peer) {
afi = SUBGRP_AFI(adj->subgroup);
safi = SUBGRP_SAFI(adj->subgroup);
addpath_capable = bgp_addpath_encode_tx(peer, afi, safi);
/* Match on a specific addpath_tx_id if we are using addpath for this
* peer and if an addpath_tx_id was specified */
if (addpath_capable && addpath_tx_id && adj->addpath_tx_id != addpath_tx_id)
continue;
/* Match on a specific addpath_tx_id if we are using addpath for
* this
* peer and if an addpath_tx_id was specified */
if (addpath_capable && addpath_tx_id
&& adj->addpath_tx_id != addpath_tx_id)
continue;
return (adj->adv
? (adj->adv->baa ? 1 : 0)
: (adj->attr ? 1 : 0));
return (adj->adv ? (adj->adv->baa ? 1 : 0)
: (adj->attr ? 1 : 0));
}
return 0;
return 0;
}
void
bgp_adj_in_set (struct bgp_node *rn, struct peer *peer, struct attr *attr,
u_int32_t addpath_id)
void bgp_adj_in_set(struct bgp_node *rn, struct peer *peer, struct attr *attr,
u_int32_t addpath_id)
{
struct bgp_adj_in *adj;
struct bgp_adj_in *adj;
for (adj = rn->adj_in; adj; adj = adj->next)
{
if (adj->peer == peer && adj->addpath_rx_id == addpath_id)
{
if (adj->attr != attr)
{
bgp_attr_unintern (&adj->attr);
adj->attr = bgp_attr_intern (attr);
}
return;
for (adj = rn->adj_in; adj; adj = adj->next) {
if (adj->peer == peer && adj->addpath_rx_id == addpath_id) {
if (adj->attr != attr) {
bgp_attr_unintern(&adj->attr);
adj->attr = bgp_attr_intern(attr);
}
return;
}
}
}
adj = XCALLOC (MTYPE_BGP_ADJ_IN, sizeof (struct bgp_adj_in));
adj->peer = peer_lock (peer); /* adj_in peer reference */
adj->attr = bgp_attr_intern (attr);
adj->addpath_rx_id = addpath_id;
BGP_ADJ_IN_ADD (rn, adj);
bgp_lock_node (rn);
adj = XCALLOC(MTYPE_BGP_ADJ_IN, sizeof(struct bgp_adj_in));
adj->peer = peer_lock(peer); /* adj_in peer reference */
adj->attr = bgp_attr_intern(attr);
adj->addpath_rx_id = addpath_id;
BGP_ADJ_IN_ADD(rn, adj);
bgp_lock_node(rn);
}
void
bgp_adj_in_remove (struct bgp_node *rn, struct bgp_adj_in *bai)
void bgp_adj_in_remove(struct bgp_node *rn, struct bgp_adj_in *bai)
{
bgp_attr_unintern (&bai->attr);
BGP_ADJ_IN_DEL (rn, bai);
peer_unlock (bai->peer); /* adj_in peer reference */
XFREE (MTYPE_BGP_ADJ_IN, bai);
bgp_attr_unintern(&bai->attr);
BGP_ADJ_IN_DEL(rn, bai);
peer_unlock(bai->peer); /* adj_in peer reference */
XFREE(MTYPE_BGP_ADJ_IN, bai);
}
int
bgp_adj_in_unset (struct bgp_node *rn, struct peer *peer,
u_int32_t addpath_id)
int bgp_adj_in_unset(struct bgp_node *rn, struct peer *peer,
u_int32_t addpath_id)
{
struct bgp_adj_in *adj;
struct bgp_adj_in *adj_next;
struct bgp_adj_in *adj;
struct bgp_adj_in *adj_next;
adj = rn->adj_in;
adj = rn->adj_in;
if (!adj)
return 0;
if (!adj)
return 0;
while (adj)
{
adj_next = adj->next;
while (adj) {
adj_next = adj->next;
if (adj->peer == peer && adj->addpath_rx_id == addpath_id)
{
bgp_adj_in_remove (rn, adj);
bgp_unlock_node (rn);
}
if (adj->peer == peer && adj->addpath_rx_id == addpath_id) {
bgp_adj_in_remove(rn, adj);
bgp_unlock_node(rn);
}
adj = adj_next;
}
adj = adj_next;
}
return 1;
return 1;
}
void
bgp_sync_init (struct peer *peer)
void bgp_sync_init(struct peer *peer)
{
afi_t afi;
safi_t safi;
struct bgp_synchronize *sync;
afi_t afi;
safi_t safi;
struct bgp_synchronize *sync;
for (afi = AFI_IP; afi < AFI_MAX; afi++)
for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
{
sync = XCALLOC (MTYPE_BGP_SYNCHRONISE,
sizeof (struct bgp_synchronize));
BGP_ADV_FIFO_INIT (&sync->update);
BGP_ADV_FIFO_INIT (&sync->withdraw);
BGP_ADV_FIFO_INIT (&sync->withdraw_low);
peer->sync[afi][safi] = sync;
peer->hash[afi][safi] = hash_create (baa_hash_key, baa_hash_cmp, NULL);
}
for (afi = AFI_IP; afi < AFI_MAX; afi++)
for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) {
sync = XCALLOC(MTYPE_BGP_SYNCHRONISE,
sizeof(struct bgp_synchronize));
BGP_ADV_FIFO_INIT(&sync->update);
BGP_ADV_FIFO_INIT(&sync->withdraw);
BGP_ADV_FIFO_INIT(&sync->withdraw_low);
peer->sync[afi][safi] = sync;
peer->hash[afi][safi] =
hash_create(baa_hash_key, baa_hash_cmp, NULL);
}
}
void
bgp_sync_delete (struct peer *peer)
void bgp_sync_delete(struct peer *peer)
{
afi_t afi;
safi_t safi;
afi_t afi;
safi_t safi;
for (afi = AFI_IP; afi < AFI_MAX; afi++)
for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
{
if (peer->sync[afi][safi])
XFREE (MTYPE_BGP_SYNCHRONISE, peer->sync[afi][safi]);
peer->sync[afi][safi] = NULL;
if (peer->hash[afi][safi])
hash_free (peer->hash[afi][safi]);
peer->hash[afi][safi] = NULL;
}
for (afi = AFI_IP; afi < AFI_MAX; afi++)
for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) {
if (peer->sync[afi][safi])
XFREE(MTYPE_BGP_SYNCHRONISE,
peer->sync[afi][safi]);
peer->sync[afi][safi] = NULL;
if (peer->hash[afi][safi])
hash_free(peer->hash[afi][safi]);
peer->hash[afi][safi] = NULL;
}
}

View File

@ -26,172 +26,168 @@
struct update_subgroup;
/* BGP advertise FIFO. */
struct bgp_advertise_fifo
{
struct bgp_advertise *next;
struct bgp_advertise *prev;
u_int32_t count;
struct bgp_advertise_fifo {
struct bgp_advertise *next;
struct bgp_advertise *prev;
u_int32_t count;
};
/* BGP advertise attribute. */
struct bgp_advertise_attr
{
/* Head of advertisement pointer. */
struct bgp_advertise *adv;
struct bgp_advertise_attr {
/* Head of advertisement pointer. */
struct bgp_advertise *adv;
/* Reference counter. */
unsigned long refcnt;
/* Reference counter. */
unsigned long refcnt;
/* Attribute pointer to be announced. */
struct attr *attr;
/* Attribute pointer to be announced. */
struct attr *attr;
};
struct bgp_advertise
{
/* FIFO for advertisement. */
struct bgp_advertise_fifo fifo;
struct bgp_advertise {
/* FIFO for advertisement. */
struct bgp_advertise_fifo fifo;
/* Link list for same attribute advertise. */
struct bgp_advertise *next;
struct bgp_advertise *prev;
/* Link list for same attribute advertise. */
struct bgp_advertise *next;
struct bgp_advertise *prev;
/* Prefix information. */
struct bgp_node *rn;
/* Prefix information. */
struct bgp_node *rn;
/* Reference pointer. */
struct bgp_adj_out *adj;
/* Reference pointer. */
struct bgp_adj_out *adj;
/* Advertisement attribute. */
struct bgp_advertise_attr *baa;
/* Advertisement attribute. */
struct bgp_advertise_attr *baa;
/* BGP info. */
struct bgp_info *binfo;
/* BGP info. */
struct bgp_info *binfo;
};
/* BGP adjacency out. */
struct bgp_adj_out
{
/* Lined list pointer. */
struct bgp_adj_out *next;
struct bgp_adj_out *prev;
struct bgp_adj_out {
/* Lined list pointer. */
struct bgp_adj_out *next;
struct bgp_adj_out *prev;
/* Advertised subgroup. */
struct update_subgroup *subgroup;
/* Advertised subgroup. */
struct update_subgroup *subgroup;
/* Threading that makes the adj part of subgroup's adj queue */
TAILQ_ENTRY(bgp_adj_out) subgrp_adj_train;
/* Threading that makes the adj part of subgroup's adj queue */
TAILQ_ENTRY(bgp_adj_out) subgrp_adj_train;
/* Prefix information. */
struct bgp_node *rn;
/* Prefix information. */
struct bgp_node *rn;
u_int32_t addpath_tx_id;
u_int32_t addpath_tx_id;
/* Advertised attribute. */
struct attr *attr;
/* Advertised attribute. */
struct attr *attr;
/* Advertisement information. */
struct bgp_advertise *adv;
/* Advertisement information. */
struct bgp_advertise *adv;
};
/* BGP adjacency in. */
struct bgp_adj_in
{
/* Linked list pointer. */
struct bgp_adj_in *next;
struct bgp_adj_in *prev;
struct bgp_adj_in {
/* Linked list pointer. */
struct bgp_adj_in *next;
struct bgp_adj_in *prev;
/* Received peer. */
struct peer *peer;
/* Received peer. */
struct peer *peer;
/* Received attribute. */
struct attr *attr;
/* Received attribute. */
struct attr *attr;
/* Addpath identifier */
u_int32_t addpath_rx_id;
/* Addpath identifier */
u_int32_t addpath_rx_id;
};
/* BGP advertisement list. */
struct bgp_synchronize
{
struct bgp_advertise_fifo update;
struct bgp_advertise_fifo withdraw;
struct bgp_advertise_fifo withdraw_low;
struct bgp_synchronize {
struct bgp_advertise_fifo update;
struct bgp_advertise_fifo withdraw;
struct bgp_advertise_fifo withdraw_low;
};
/* BGP adjacency linked list. */
#define BGP_INFO_ADD(N,A,TYPE) \
do { \
(A)->prev = NULL; \
(A)->next = (N)->TYPE; \
if ((N)->TYPE) \
(N)->TYPE->prev = (A); \
(N)->TYPE = (A); \
} while (0)
#define BGP_INFO_ADD(N, A, TYPE) \
do { \
(A)->prev = NULL; \
(A)->next = (N)->TYPE; \
if ((N)->TYPE) \
(N)->TYPE->prev = (A); \
(N)->TYPE = (A); \
} while (0)
#define BGP_INFO_DEL(N,A,TYPE) \
do { \
if ((A)->next) \
(A)->next->prev = (A)->prev; \
if ((A)->prev) \
(A)->prev->next = (A)->next; \
else \
(N)->TYPE = (A)->next; \
} while (0)
#define BGP_INFO_DEL(N, A, TYPE) \
do { \
if ((A)->next) \
(A)->next->prev = (A)->prev; \
if ((A)->prev) \
(A)->prev->next = (A)->next; \
else \
(N)->TYPE = (A)->next; \
} while (0)
#define BGP_ADJ_IN_ADD(N,A) BGP_INFO_ADD(N,A,adj_in)
#define BGP_ADJ_IN_DEL(N,A) BGP_INFO_DEL(N,A,adj_in)
#define BGP_ADJ_OUT_ADD(N,A) BGP_INFO_ADD(N,A,adj_out)
#define BGP_ADJ_OUT_DEL(N,A) BGP_INFO_DEL(N,A,adj_out)
#define BGP_ADV_FIFO_ADD(F, N) \
do { \
FIFO_ADD((F), (N)); \
(F)->count++; \
} while (0)
#define BGP_ADV_FIFO_ADD(F, N) \
do { \
FIFO_ADD((F), (N)); \
(F)->count++; \
} while (0)
#define BGP_ADV_FIFO_DEL(F, N) \
do { \
FIFO_DEL((N)); \
(F)->count--; \
} while (0)
#define BGP_ADV_FIFO_DEL(F, N) \
do { \
FIFO_DEL((N)); \
(F)->count--; \
} while (0)
#define BGP_ADV_FIFO_INIT(F) \
do { \
FIFO_INIT((F)); \
(F)->count = 0; \
} while (0)
#define BGP_ADV_FIFO_INIT(F) \
do { \
FIFO_INIT((F)); \
(F)->count = 0; \
} while (0)
#define BGP_ADV_FIFO_COUNT(F) \
(F)->count
#define BGP_ADV_FIFO_COUNT(F) (F)->count
#define BGP_ADV_FIFO_EMPTY(F) \
(((struct bgp_advertise_fifo *)(F))->next == (struct bgp_advertise *)(F))
#define BGP_ADV_FIFO_EMPTY(F) \
(((struct bgp_advertise_fifo *)(F))->next \
== (struct bgp_advertise *)(F))
#define BGP_ADV_FIFO_HEAD(F) \
((((struct bgp_advertise_fifo *)(F))->next == (struct bgp_advertise *)(F)) \
? NULL : (F)->next)
#define BGP_ADV_FIFO_HEAD(F) \
((((struct bgp_advertise_fifo *)(F))->next \
== (struct bgp_advertise *)(F)) \
? NULL \
: (F)->next)
/* Prototypes. */
extern int bgp_adj_out_lookup (struct peer *, struct bgp_node *, u_int32_t);
extern void bgp_adj_in_set (struct bgp_node *, struct peer *, struct attr *, u_int32_t);
extern int bgp_adj_in_unset (struct bgp_node *, struct peer *, u_int32_t);
extern void bgp_adj_in_remove (struct bgp_node *, struct bgp_adj_in *);
extern int bgp_adj_out_lookup(struct peer *, struct bgp_node *, u_int32_t);
extern void bgp_adj_in_set(struct bgp_node *, struct peer *, struct attr *,
u_int32_t);
extern int bgp_adj_in_unset(struct bgp_node *, struct peer *, u_int32_t);
extern void bgp_adj_in_remove(struct bgp_node *, struct bgp_adj_in *);
extern void bgp_sync_init (struct peer *);
extern void bgp_sync_delete (struct peer *);
extern unsigned int baa_hash_key (void *p);
extern int baa_hash_cmp (const void *p1, const void *p2);
extern void bgp_advertise_add (struct bgp_advertise_attr *baa,
struct bgp_advertise *adv);
extern struct bgp_advertise *bgp_advertise_new (void);
extern void bgp_advertise_free (struct bgp_advertise *adv);
extern struct bgp_advertise_attr *
bgp_advertise_intern (struct hash *hash, struct attr *attr);
extern struct bgp_advertise_attr *baa_new (void);
extern void
bgp_advertise_delete (struct bgp_advertise_attr *baa,
struct bgp_advertise *adv);
extern void
bgp_advertise_unintern (struct hash *hash, struct bgp_advertise_attr *baa);
extern void bgp_sync_init(struct peer *);
extern void bgp_sync_delete(struct peer *);
extern unsigned int baa_hash_key(void *p);
extern int baa_hash_cmp(const void *p1, const void *p2);
extern void bgp_advertise_add(struct bgp_advertise_attr *baa,
struct bgp_advertise *adv);
extern struct bgp_advertise *bgp_advertise_new(void);
extern void bgp_advertise_free(struct bgp_advertise *adv);
extern struct bgp_advertise_attr *bgp_advertise_intern(struct hash *hash,
struct attr *attr);
extern struct bgp_advertise_attr *baa_new(void);
extern void bgp_advertise_delete(struct bgp_advertise_attr *baa,
struct bgp_advertise *adv);
extern void bgp_advertise_unintern(struct hash *hash,
struct bgp_advertise_attr *baa);
#endif /* _QUAGGA_BGP_ADVERTISE_H */

File diff suppressed because it is too large Load Diff

View File

@ -43,87 +43,89 @@
/* Transition 16Bit AS as defined by IANA */
#define BGP_AS_TRANS 23456U
#define BGP_AS_IS_PRIVATE(ASN) \
(((ASN) >= BGP_PRIVATE_AS_MIN && (ASN) <= BGP_PRIVATE_AS_MAX) || \
((ASN) >= BGP_PRIVATE_AS4_MIN && (ASN) <= BGP_PRIVATE_AS4_MAX))
#define BGP_AS_IS_PRIVATE(ASN) \
(((ASN) >= BGP_PRIVATE_AS_MIN && (ASN) <= BGP_PRIVATE_AS_MAX) \
|| ((ASN) >= BGP_PRIVATE_AS4_MIN && (ASN) <= BGP_PRIVATE_AS4_MAX))
/* AS_PATH segment data in abstracted form, no limit is placed on length */
struct assegment
{
struct assegment *next;
as_t *as;
u_short length;
u_char type;
struct assegment {
struct assegment *next;
as_t *as;
u_short length;
u_char type;
};
/* AS path may be include some AsSegments. */
struct aspath
{
/* Reference count to this aspath. */
unsigned long refcnt;
struct aspath {
/* Reference count to this aspath. */
unsigned long refcnt;
/* segment data */
struct assegment *segments;
/* AS path as a json object */
json_object *json;
/* segment data */
struct assegment *segments;
/* String expression of AS path. This string is used by vty output
and AS path regular expression match. */
char *str;
unsigned short str_len;
/* AS path as a json object */
json_object *json;
/* String expression of AS path. This string is used by vty output
and AS path regular expression match. */
char *str;
unsigned short str_len;
};
#define ASPATH_STR_DEFAULT_LEN 32
/* Prototypes. */
extern void aspath_init (void);
extern void aspath_finish (void);
extern struct aspath *aspath_parse (struct stream *, size_t, int);
extern struct aspath *aspath_dup (struct aspath *);
extern struct aspath *aspath_aggregate (struct aspath *, struct aspath *);
extern struct aspath *aspath_prepend (struct aspath *, struct aspath *);
extern struct aspath *aspath_filter_exclude (struct aspath *, struct aspath *);
extern struct aspath *aspath_add_seq_n (struct aspath *, as_t, unsigned);
extern struct aspath *aspath_add_seq (struct aspath *, as_t);
extern struct aspath *aspath_add_confed_seq (struct aspath *, as_t);
extern int aspath_cmp (const void *, const void *);
extern int aspath_cmp_left (const struct aspath *, const struct aspath *);
extern int aspath_cmp_left_confed (const struct aspath *, const struct aspath *);
extern struct aspath *aspath_delete_confed_seq (struct aspath *);
extern struct aspath *aspath_empty (void);
extern struct aspath *aspath_empty_get (void);
extern struct aspath *aspath_str2aspath (const char *);
extern void aspath_free (struct aspath *);
extern struct aspath *aspath_intern (struct aspath *);
extern void aspath_unintern (struct aspath **);
extern const char *aspath_print (struct aspath *);
extern void aspath_print_vty (struct vty *, const char *, struct aspath *, const char *);
extern void aspath_print_all_vty (struct vty *);
extern unsigned int aspath_key_make (void *);
extern unsigned int aspath_get_first_as (struct aspath *);
extern unsigned int aspath_get_last_as (struct aspath *);
extern int aspath_loop_check (struct aspath *, as_t);
extern int aspath_private_as_check (struct aspath *);
extern int aspath_single_asn_check (struct aspath *, as_t asn);
extern struct aspath *aspath_replace_specific_asn (struct aspath *aspath, as_t target_asn, as_t our_asn);
extern struct aspath *aspath_replace_private_asns(struct aspath *aspath, as_t asn);
extern struct aspath *aspath_remove_private_asns (struct aspath *aspath);
extern int aspath_firstas_check (struct aspath *, as_t);
extern int aspath_confed_check (struct aspath *);
extern int aspath_left_confed_check (struct aspath *);
extern unsigned long aspath_count (void);
extern unsigned int aspath_count_hops (const struct aspath *);
extern unsigned int aspath_count_confeds (struct aspath *);
extern unsigned int aspath_size (struct aspath *);
extern as_t aspath_highest (struct aspath *);
extern as_t aspath_leftmost (struct aspath *);
extern size_t aspath_put (struct stream *, struct aspath *, int);
extern void aspath_init(void);
extern void aspath_finish(void);
extern struct aspath *aspath_parse(struct stream *, size_t, int);
extern struct aspath *aspath_dup(struct aspath *);
extern struct aspath *aspath_aggregate(struct aspath *, struct aspath *);
extern struct aspath *aspath_prepend(struct aspath *, struct aspath *);
extern struct aspath *aspath_filter_exclude(struct aspath *, struct aspath *);
extern struct aspath *aspath_add_seq_n(struct aspath *, as_t, unsigned);
extern struct aspath *aspath_add_seq(struct aspath *, as_t);
extern struct aspath *aspath_add_confed_seq(struct aspath *, as_t);
extern int aspath_cmp(const void *, const void *);
extern int aspath_cmp_left(const struct aspath *, const struct aspath *);
extern int aspath_cmp_left_confed(const struct aspath *, const struct aspath *);
extern struct aspath *aspath_delete_confed_seq(struct aspath *);
extern struct aspath *aspath_empty(void);
extern struct aspath *aspath_empty_get(void);
extern struct aspath *aspath_str2aspath(const char *);
extern void aspath_free(struct aspath *);
extern struct aspath *aspath_intern(struct aspath *);
extern void aspath_unintern(struct aspath **);
extern const char *aspath_print(struct aspath *);
extern void aspath_print_vty(struct vty *, const char *, struct aspath *,
const char *);
extern void aspath_print_all_vty(struct vty *);
extern unsigned int aspath_key_make(void *);
extern unsigned int aspath_get_first_as(struct aspath *);
extern unsigned int aspath_get_last_as(struct aspath *);
extern int aspath_loop_check(struct aspath *, as_t);
extern int aspath_private_as_check(struct aspath *);
extern int aspath_single_asn_check(struct aspath *, as_t asn);
extern struct aspath *aspath_replace_specific_asn(struct aspath *aspath,
as_t target_asn,
as_t our_asn);
extern struct aspath *aspath_replace_private_asns(struct aspath *aspath,
as_t asn);
extern struct aspath *aspath_remove_private_asns(struct aspath *aspath);
extern int aspath_firstas_check(struct aspath *, as_t);
extern int aspath_confed_check(struct aspath *);
extern int aspath_left_confed_check(struct aspath *);
extern unsigned long aspath_count(void);
extern unsigned int aspath_count_hops(const struct aspath *);
extern unsigned int aspath_count_confeds(struct aspath *);
extern unsigned int aspath_size(struct aspath *);
extern as_t aspath_highest(struct aspath *);
extern as_t aspath_leftmost(struct aspath *);
extern size_t aspath_put(struct stream *, struct aspath *, int);
extern struct aspath *aspath_reconcile_as4 (struct aspath *, struct aspath *);
extern unsigned int aspath_has_as4 (struct aspath *);
extern struct aspath *aspath_reconcile_as4(struct aspath *, struct aspath *);
extern unsigned int aspath_has_as4(struct aspath *);
/* For SNMP BGP4PATHATTRASPATHSEGMENT, might be useful for debug */
extern u_char *aspath_snmp_pathseg (struct aspath *, size_t *);
extern u_char *aspath_snmp_pathseg(struct aspath *, size_t *);
#endif /* _QUAGGA_BGP_ASPATH_H */

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,4 @@
/* BGP attributes.
/* BGP attributes.
* Copyright (C) 1996, 97, 98 Kunihiro Ishiguro
*
* This file is part of GNU Zebra.
@ -21,20 +21,20 @@
#ifndef _QUAGGA_BGP_ATTR_H
#define _QUAGGA_BGP_ATTR_H
#include "mpls.h"
#include "bgp_attr_evpn.h"
/* Simple bit mapping. */
#define BITMAP_NBBY 8
#define SET_BITMAP(MAP, NUM) \
SET_FLAG (MAP[(NUM) / BITMAP_NBBY], 1 << ((NUM) % BITMAP_NBBY))
#define SET_BITMAP(MAP, NUM) \
SET_FLAG(MAP[(NUM) / BITMAP_NBBY], 1 << ((NUM) % BITMAP_NBBY))
#define CHECK_BITMAP(MAP, NUM) \
CHECK_FLAG (MAP[(NUM) / BITMAP_NBBY], 1 << ((NUM) % BITMAP_NBBY))
#define CHECK_BITMAP(MAP, NUM) \
CHECK_FLAG(MAP[(NUM) / BITMAP_NBBY], 1 << ((NUM) % BITMAP_NBBY))
#define BGP_MED_MAX UINT32_MAX
/* BGP Attribute type range. */
#define BGP_ATTR_TYPE_RANGE 256
#define BGP_ATTR_BITMAP_SIZE (BGP_ATTR_TYPE_RANGE / BITMAP_NBBY)
@ -67,12 +67,12 @@
#define BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH 6
struct bgp_attr_encap_subtlv {
struct bgp_attr_encap_subtlv *next; /* for chaining */
/* Reference count of this attribute. */
unsigned long refcnt;
uint16_t type;
uint16_t length;
uint8_t value[1]; /* will be extended */
struct bgp_attr_encap_subtlv *next; /* for chaining */
/* Reference count of this attribute. */
unsigned long refcnt;
uint16_t type;
uint16_t length;
uint8_t value[1]; /* will be extended */
};
#if ENABLE_BGP_VNC
@ -80,111 +80,108 @@ struct bgp_attr_encap_subtlv {
* old rfp<->rfapi representation
*/
struct bgp_tea_options {
struct bgp_tea_options *next;
uint8_t options_count;
uint16_t options_length; /* each TLV may be 256 in length */
uint8_t type;
uint8_t length;
void *value; /* pointer to data */
struct bgp_tea_options *next;
uint8_t options_count;
uint16_t options_length; /* each TLV may be 256 in length */
uint8_t type;
uint8_t length;
void *value; /* pointer to data */
};
#endif
/* Overlay Index Info */
struct overlay_index
{
struct eth_segment_id eth_s_id;
union gw_addr gw_ip;
};
/* Additional/uncommon BGP attributes.
* lazily allocated as and when a struct attr
* requires it.
*/
struct attr_extra
{
/* Multi-Protocol Nexthop, AFI IPv6 */
struct in6_addr mp_nexthop_global;
struct in6_addr mp_nexthop_local;
/* Extended Communities attribute. */
struct ecommunity *ecommunity;
/* Large Communities attribute. */
struct lcommunity *lcommunity;
/* Route-Reflector Cluster attribute */
struct cluster_list *cluster;
/* Unknown transitive attribute. */
struct transit *transit;
struct in_addr mp_nexthop_global_in;
/* Aggregator Router ID attribute */
struct in_addr aggregator_addr;
/* Route Reflector Originator attribute */
struct in_addr originator_id;
/* Local weight, not actually an attribute */
u_int32_t weight;
/* Aggregator ASN */
as_t aggregator_as;
/* MP Nexthop length */
u_char mp_nexthop_len;
/* MP Nexthop preference */
u_char mp_nexthop_prefer_global;
/* route tag */
route_tag_t tag;
/* Label index */
u_int32_t label_index;
uint16_t encap_tunneltype; /* grr */
struct bgp_attr_encap_subtlv *encap_subtlvs; /* rfc5512 */
#if ENABLE_BGP_VNC
struct bgp_attr_encap_subtlv *vnc_subtlvs; /* VNC-specific */
#endif
/* EVPN */
struct overlay_index evpn_overlay;
struct overlay_index {
struct eth_segment_id eth_s_id;
union gw_addr gw_ip;
};
/* BGP core attribute structure. */
struct attr
{
/* AS Path structure */
struct aspath *aspath;
struct attr {
/* AS Path structure */
struct aspath *aspath;
/* Community structure */
struct community *community;
/* Lazily allocated pointer to extra attributes */
struct attr_extra *extra;
/* Reference count of this attribute. */
unsigned long refcnt;
/* Community structure */
struct community *community;
/* Flag of attribute is set or not. */
uint64_t flag;
/* Apart from in6_addr, the remaining static attributes */
struct in_addr nexthop;
u_int32_t med;
u_int32_t local_pref;
ifindex_t nh_ifindex;
/* Path origin attribute */
u_char origin;
/* Reference count of this attribute. */
unsigned long refcnt;
/* has the route-map changed any attribute?
Used on the peer outbound side. */
u_int32_t rmap_change_flags;
/* Flag of attribute is set or not. */
uint64_t flag;
/* Apart from in6_addr, the remaining static attributes */
struct in_addr nexthop;
u_int32_t med;
u_int32_t local_pref;
ifindex_t nh_ifindex;
/* Path origin attribute */
u_char origin;
/* has the route-map changed any attribute?
Used on the peer outbound side. */
u_int32_t rmap_change_flags;
/* Multi-Protocol Nexthop, AFI IPv6 */
struct in6_addr mp_nexthop_global;
struct in6_addr mp_nexthop_local;
/* Extended Communities attribute. */
struct ecommunity *ecommunity;
/* Large Communities attribute. */
struct lcommunity *lcommunity;
/* Route-Reflector Cluster attribute */
struct cluster_list *cluster;
/* Unknown transitive attribute. */
struct transit *transit;
struct in_addr mp_nexthop_global_in;
/* Aggregator Router ID attribute */
struct in_addr aggregator_addr;
/* Route Reflector Originator attribute */
struct in_addr originator_id;
/* Local weight, not actually an attribute */
u_int32_t weight;
/* Aggregator ASN */
as_t aggregator_as;
/* MP Nexthop length */
u_char mp_nexthop_len;
/* MP Nexthop preference */
u_char mp_nexthop_prefer_global;
/* Static MAC for EVPN */
u_char sticky;
/* route tag */
route_tag_t tag;
/* Label index */
u_int32_t label_index;
/* MPLS label */
mpls_label_t label;
uint16_t encap_tunneltype; /* grr */
struct bgp_attr_encap_subtlv *encap_subtlvs; /* rfc5512 */
#if ENABLE_BGP_VNC
struct bgp_attr_encap_subtlv *vnc_subtlvs; /* VNC-specific */
#endif
/* EVPN */
struct overlay_index evpn_overlay;
/* EVPN MAC Mobility sequence number, if any. */
u_int32_t mm_seqnum;
};
/* rmap_change_flags definition */
@ -197,99 +194,97 @@ struct attr
#define BATTR_RMAP_IPV6_PREFER_GLOBAL_CHANGED (1 << 6)
/* Router Reflector related structure. */
struct cluster_list
{
unsigned long refcnt;
int length;
struct in_addr *list;
struct cluster_list {
unsigned long refcnt;
int length;
struct in_addr *list;
};
/* Unknown transit attribute. */
struct transit
{
unsigned long refcnt;
int length;
u_char *val;
struct transit {
unsigned long refcnt;
int length;
u_char *val;
};
#define ATTR_FLAG_BIT(X) (1ULL << ((X) - 1))
#define BGP_CLUSTER_LIST_LENGTH(attr) \
(((attr)->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST)) ? \
(attr)->extra->cluster->length : 0)
#define BGP_CLUSTER_LIST_LENGTH(attr) \
(((attr)->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST)) \
? (attr)->cluster->length \
: 0)
typedef enum {
BGP_ATTR_PARSE_PROCEED = 0,
BGP_ATTR_PARSE_ERROR = -1,
BGP_ATTR_PARSE_WITHDRAW = -2,
BGP_ATTR_PARSE_PROCEED = 0,
BGP_ATTR_PARSE_ERROR = -1,
BGP_ATTR_PARSE_WITHDRAW = -2,
/* only used internally, send notify + convert to BGP_ATTR_PARSE_ERROR */
BGP_ATTR_PARSE_ERROR_NOTIFYPLS = -3,
/* only used internally, send notify + convert to BGP_ATTR_PARSE_ERROR
*/
BGP_ATTR_PARSE_ERROR_NOTIFYPLS = -3,
} bgp_attr_parse_ret_t;
struct bpacket_attr_vec_arr;
/* Prototypes. */
extern void bgp_attr_init (void);
extern void bgp_attr_finish (void);
extern bgp_attr_parse_ret_t bgp_attr_parse (struct peer *, struct attr *,
bgp_size_t, struct bgp_nlri *,
struct bgp_nlri *);
extern struct attr_extra *bgp_attr_extra_get (struct attr *);
extern void bgp_attr_extra_free (struct attr *);
extern void bgp_attr_dup (struct attr *, struct attr *);
extern void bgp_attr_deep_dup (struct attr *, struct attr *);
extern void bgp_attr_deep_free (struct attr *);
extern struct attr *bgp_attr_intern (struct attr *attr);
extern struct attr *bgp_attr_refcount (struct attr *attr);
extern void bgp_attr_unintern_sub (struct attr *);
extern void bgp_attr_unintern (struct attr **);
extern void bgp_attr_flush (struct attr *);
extern struct attr *bgp_attr_default_set (struct attr *attr, u_char);
extern struct attr *bgp_attr_aggregate_intern (struct bgp *, u_char,
struct aspath *,
struct community *, int as_set, u_char);
extern bgp_size_t bgp_packet_attribute (struct bgp *bgp, struct peer *,
struct stream *, struct attr *,
struct bpacket_attr_vec_arr *vecarr,
struct prefix *, afi_t, safi_t,
struct peer *, struct prefix_rd *,
u_char *, int, u_int32_t);
extern void bgp_dump_routes_attr (struct stream *, struct attr *,
struct prefix *);
extern int attrhash_cmp (const void *, const void *);
extern unsigned int attrhash_key_make (void *);
extern void attr_show_all (struct vty *);
extern unsigned long int attr_count (void);
extern unsigned long int attr_unknown_count (void);
extern void bgp_attr_init(void);
extern void bgp_attr_finish(void);
extern bgp_attr_parse_ret_t bgp_attr_parse(struct peer *, struct attr *,
bgp_size_t, struct bgp_nlri *,
struct bgp_nlri *);
extern void bgp_attr_dup(struct attr *, struct attr *);
extern void bgp_attr_deep_dup(struct attr *, struct attr *);
extern void bgp_attr_deep_free(struct attr *);
extern struct attr *bgp_attr_intern(struct attr *attr);
extern struct attr *bgp_attr_refcount(struct attr *attr);
extern void bgp_attr_unintern_sub(struct attr *);
extern void bgp_attr_unintern(struct attr **);
extern void bgp_attr_flush(struct attr *);
extern struct attr *bgp_attr_default_set(struct attr *attr, u_char);
extern struct attr *bgp_attr_aggregate_intern(struct bgp *, u_char,
struct aspath *,
struct community *, int as_set,
u_char);
extern bgp_size_t bgp_packet_attribute(struct bgp *bgp, struct peer *,
struct stream *, struct attr *,
struct bpacket_attr_vec_arr *vecarr,
struct prefix *, afi_t, safi_t,
struct peer *, struct prefix_rd *,
mpls_label_t *, int, u_int32_t);
extern void bgp_dump_routes_attr(struct stream *, struct attr *,
struct prefix *);
extern int attrhash_cmp(const void *, const void *);
extern unsigned int attrhash_key_make(void *);
extern void attr_show_all(struct vty *);
extern unsigned long int attr_count(void);
extern unsigned long int attr_unknown_count(void);
/* Cluster list prototypes. */
extern int cluster_loop_check (struct cluster_list *, struct in_addr);
extern void cluster_unintern (struct cluster_list *);
extern int cluster_loop_check(struct cluster_list *, struct in_addr);
extern void cluster_unintern(struct cluster_list *);
/* Transit attribute prototypes. */
void transit_unintern (struct transit *);
void transit_unintern(struct transit *);
/* Below exported for unit-test purposes only */
struct bgp_attr_parser_args {
struct peer *peer;
bgp_size_t length; /* attribute data length; */
bgp_size_t total; /* total length, inc header */
struct attr *attr;
u_int8_t type;
u_int8_t flags;
u_char *startp;
struct peer *peer;
bgp_size_t length; /* attribute data length; */
bgp_size_t total; /* total length, inc header */
struct attr *attr;
u_int8_t type;
u_int8_t flags;
u_char *startp;
};
extern int bgp_mp_reach_parse (struct bgp_attr_parser_args *args,
struct bgp_nlri *);
extern int bgp_mp_unreach_parse (struct bgp_attr_parser_args *args,
struct bgp_nlri *);
extern int bgp_mp_reach_parse(struct bgp_attr_parser_args *args,
struct bgp_nlri *);
extern int bgp_mp_unreach_parse(struct bgp_attr_parser_args *args,
struct bgp_nlri *);
extern struct bgp_attr_encap_subtlv *
encap_tlv_dup(struct bgp_attr_encap_subtlv *orig);
extern void
bgp_attr_flush_encap(struct attr *attr);
extern void bgp_attr_flush_encap(struct attr *attr);
/**
* Set of functions to encode MP_REACH_NLRI and MP_UNREACH_NLRI attributes.
@ -298,35 +293,44 @@ bgp_attr_flush_encap(struct attr *attr);
* finally the _end() function.
*/
extern size_t bgp_packet_mpattr_start(struct stream *s, struct peer *peer,
afi_t afi, safi_t safi,
struct bpacket_attr_vec_arr *vecarr,
afi_t afi, safi_t safi,
struct bpacket_attr_vec_arr *vecarr,
struct attr *attr);
extern void bgp_packet_mpattr_prefix(struct stream *s, afi_t afi, safi_t safi,
struct prefix *p, struct prefix_rd *prd,
u_char *tag, int addpath_encode,
u_int32_t addpath_tx_id,
struct attr *);
mpls_label_t *label, int addpath_encode,
u_int32_t addpath_tx_id, struct attr *);
extern size_t bgp_packet_mpattr_prefix_size(afi_t afi, safi_t safi,
struct prefix *p);
struct prefix *p);
extern void bgp_packet_mpattr_end(struct stream *s, size_t sizep);
extern size_t bgp_packet_mpunreach_start (struct stream *s, afi_t afi,
safi_t safi);
extern void bgp_packet_mpunreach_prefix (struct stream *s, struct prefix *p,
afi_t afi, safi_t safi, struct prefix_rd *prd,
u_char *tag, int, u_int32_t, struct attr *);
extern void bgp_packet_mpunreach_end (struct stream *s, size_t attrlen_pnt);
extern size_t bgp_packet_mpunreach_start(struct stream *s, afi_t afi,
safi_t safi);
extern void bgp_packet_mpunreach_prefix(struct stream *s, struct prefix *p,
afi_t afi, safi_t safi,
struct prefix_rd *prd, mpls_label_t *,
int, u_int32_t, struct attr *);
extern void bgp_packet_mpunreach_end(struct stream *s, size_t attrlen_pnt);
static inline int
bgp_rmap_nhop_changed(u_int32_t out_rmap_flags, u_int32_t in_rmap_flags)
static inline int bgp_rmap_nhop_changed(u_int32_t out_rmap_flags,
u_int32_t in_rmap_flags)
{
return ((CHECK_FLAG(out_rmap_flags, BATTR_RMAP_NEXTHOP_PEER_ADDRESS) ||
CHECK_FLAG(out_rmap_flags, BATTR_RMAP_NEXTHOP_UNCHANGED) ||
CHECK_FLAG(out_rmap_flags, BATTR_RMAP_IPV4_NHOP_CHANGED) ||
CHECK_FLAG(out_rmap_flags, BATTR_RMAP_IPV6_GLOBAL_NHOP_CHANGED) ||
CHECK_FLAG(out_rmap_flags, BATTR_RMAP_IPV6_PREFER_GLOBAL_CHANGED) ||
CHECK_FLAG(out_rmap_flags, BATTR_RMAP_IPV6_LL_NHOP_CHANGED) ||
CHECK_FLAG(in_rmap_flags, BATTR_RMAP_NEXTHOP_UNCHANGED)) ? 1 : 0);
return ((CHECK_FLAG(out_rmap_flags, BATTR_RMAP_NEXTHOP_PEER_ADDRESS)
|| CHECK_FLAG(out_rmap_flags, BATTR_RMAP_NEXTHOP_UNCHANGED)
|| CHECK_FLAG(out_rmap_flags, BATTR_RMAP_IPV4_NHOP_CHANGED)
|| CHECK_FLAG(out_rmap_flags,
BATTR_RMAP_IPV6_GLOBAL_NHOP_CHANGED)
|| CHECK_FLAG(out_rmap_flags,
BATTR_RMAP_IPV6_PREFER_GLOBAL_CHANGED)
|| CHECK_FLAG(out_rmap_flags, BATTR_RMAP_IPV6_LL_NHOP_CHANGED)
|| CHECK_FLAG(in_rmap_flags, BATTR_RMAP_NEXTHOP_UNCHANGED))
? 1
: 0);
}
static inline u_int32_t mac_mobility_seqnum(struct attr *attr)
{
return (attr) ? attr->mm_seqnum : 0;
}
#endif /* _QUAGGA_BGP_ATTR_H */

View File

@ -33,21 +33,20 @@
#include "bgpd/bgp_attr_evpn.h"
#include "bgpd/bgp_ecommunity.h"
#include "bgpd/bgp_evpn.h"
#include "bgpd/bgp_evpn_private.h"
void bgp_add_routermac_ecom(struct attr *attr, struct ethaddr *routermac)
{
struct ecommunity_val routermac_ecom;
if (attr->extra) {
memset(&routermac_ecom, 0, sizeof(struct ecommunity_val));
routermac_ecom.val[0] = ECOMMUNITY_ENCODE_EVPN;
routermac_ecom.val[1] = ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC;
memcpy(&routermac_ecom.val[2], routermac->octet, ETHER_ADDR_LEN);
if (!attr->extra->ecommunity)
attr->extra->ecommunity = ecommunity_new();
ecommunity_add_val(attr->extra->ecommunity, &routermac_ecom);
ecommunity_str (attr->extra->ecommunity);
}
memset(&routermac_ecom, 0, sizeof(struct ecommunity_val));
routermac_ecom.val[0] = ECOMMUNITY_ENCODE_EVPN;
routermac_ecom.val[1] = ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC;
memcpy(&routermac_ecom.val[2], routermac->octet, ETHER_ADDR_LEN);
if (!attr->ecommunity)
attr->ecommunity = ecommunity_new();
ecommunity_add_val(attr->ecommunity, &routermac_ecom);
ecommunity_str(attr->ecommunity);
}
/* converts to an esi
@ -62,10 +61,9 @@ int str2esi(const char *str, struct eth_segment_id *id)
if (!str)
return 0;
if (sscanf (str, "%2x:%2x:%2x:%2x:%2x:%2x:%2x:%2x:%2x:%2x",
a + 0, a + 1, a + 2, a + 3, a + 4, a + 5,
a + 6, a + 7, a + 8, a + 9) != ESI_LEN)
{
if (sscanf(str, "%2x:%2x:%2x:%2x:%2x:%2x:%2x:%2x:%2x:%2x", a + 0, a + 1,
a + 2, a + 3, a + 4, a + 5, a + 6, a + 7, a + 8, a + 9)
!= ESI_LEN) {
/* error in incoming str length */
return 0;
}
@ -86,12 +84,13 @@ char *esi2str(struct eth_segment_id *id)
return NULL;
val = id->val;
ptr = (char *)XMALLOC(MTYPE_TMP, (ESI_LEN * 2 + ESI_LEN - 1 + 1) * sizeof(char));
ptr = (char *)XMALLOC(MTYPE_TMP,
(ESI_LEN * 2 + ESI_LEN - 1 + 1) * sizeof(char));
snprintf(ptr, (ESI_LEN * 2 + ESI_LEN - 1 + 1),
"%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
val[0], val[1], val[2], val[3], val[4],
val[5], val[6], val[7], val[8], val[9]);
"%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", val[0],
val[1], val[2], val[3], val[4], val[5], val[6], val[7], val[8],
val[9]);
return ptr;
}
@ -102,12 +101,63 @@ char *ecom_mac2str(char *ecom_mac)
en = ecom_mac;
en += 2;
return prefix_mac2str((struct ethaddr *)en, NULL, 0);
return prefix_mac2str((struct ethaddr *)en, NULL, 0);
}
/*
* Fetch and return the sequence number from MAC Mobility extended
* community, if present, else 0.
*/
u_int32_t bgp_attr_mac_mobility_seqnum(struct attr *attr, u_char *sticky)
{
struct ecommunity *ecom;
int i;
u_char flags = 0;
ecom = attr->ecommunity;
if (!ecom || !ecom->size)
return 0;
/* If there is a MAC Mobility extended community, return its
* sequence number.
* TODO: RFC is silent on handling of multiple MAC mobility extended
* communities for the same route. We will bail out upon the first
* one.
*/
for (i = 0; i < ecom->size; i++) {
u_char *pnt;
u_char type, sub_type;
u_int32_t seq_num;
pnt = (ecom->val + (i * ECOMMUNITY_SIZE));
type = *pnt++;
sub_type = *pnt++;
if (!(type == ECOMMUNITY_ENCODE_EVPN
&& sub_type == ECOMMUNITY_EVPN_SUBTYPE_MACMOBILITY))
continue;
flags = *pnt++;
if (flags & ECOMMUNITY_EVPN_SUBTYPE_MACMOBILITY_FLAG_STICKY)
*sticky = 1;
else
*sticky = 0;
pnt++;
seq_num = (*pnt++ << 24);
seq_num |= (*pnt++ << 16);
seq_num |= (*pnt++ << 8);
seq_num |= (*pnt++);
return seq_num;
}
return 0;
}
/* dst prefix must be AF_INET or AF_INET6 prefix, to forge EVPN prefix */
extern int
bgp_build_evpn_prefix(int evpn_type, uint32_t eth_tag, struct prefix *dst)
extern int bgp_build_evpn_prefix(int evpn_type, uint32_t eth_tag,
struct prefix *dst)
{
struct evpn_addr *p_evpn_p;
struct prefix p2;
@ -121,19 +171,19 @@ bgp_build_evpn_prefix(int evpn_type, uint32_t eth_tag, struct prefix *dst)
p_evpn_p = &(dst->u.prefix_evpn);
dst->family = AF_ETHERNET;
p_evpn_p->route_type = evpn_type;
if (evpn_type == EVPN_IP_PREFIX) {
if (evpn_type == BGP_EVPN_IP_PREFIX_ROUTE) {
p_evpn_p->eth_tag = eth_tag;
p_evpn_p->ip_prefix_length = p2.prefixlen;
if (src->family == AF_INET) {
p_evpn_p->flags = IP_PREFIX_V4;
memcpy(&p_evpn_p->ip.v4_addr, &src->u.prefix4,
SET_IPADDR_V4(&p_evpn_p->ip);
memcpy(&p_evpn_p->ip.ipaddr_v4, &src->u.prefix4,
sizeof(struct in_addr));
dst->prefixlen = (u_char) PREFIX_LEN_ROUTE_TYPE_5_IPV4;
dst->prefixlen = (u_char)PREFIX_LEN_ROUTE_TYPE_5_IPV4;
} else {
p_evpn_p->flags = IP_PREFIX_V6;
memcpy(&p_evpn_p->ip.v6_addr, &src->u.prefix6,
SET_IPADDR_V6(&p_evpn_p->ip);
memcpy(&p_evpn_p->ip.ipaddr_v6, &src->u.prefix6,
sizeof(struct in6_addr));
dst->prefixlen = (u_char) PREFIX_LEN_ROUTE_TYPE_5_IPV6;
dst->prefixlen = (u_char)PREFIX_LEN_ROUTE_TYPE_5_IPV6;
}
} else
return -1;

View File

@ -22,16 +22,18 @@
#define _QUAGGA_BGP_ATTR_EVPN_H
/* value of first byte of ESI */
#define ESI_TYPE_ARBITRARY 0 /* */
#define ESI_TYPE_LACP 1 /* <> */
#define ESI_TYPE_BRIDGE 2 /* <Root bridge Mac-6B>:<Root Br Priority-2B>:00 */
#define ESI_TYPE_MAC 3 /* <Syst Mac Add-6B>:<Local Discriminator Value-3B> */
#define ESI_TYPE_ROUTER 4 /* <RouterId-4B>:<Local Discriminator Value-4B> */
#define ESI_TYPE_AS 5 /* <AS-4B>:<Local Discriminator Value-4B> */
#define ESI_TYPE_ARBITRARY 0 /* */
#define ESI_TYPE_LACP 1 /* <> */
#define ESI_TYPE_BRIDGE 2 /* <Root bridge Mac-6B>:<Root Br Priority-2B>:00 */
#define ESI_TYPE_MAC 3 /* <Syst Mac Add-6B>:<Local Discriminator Value-3B> */
#define ESI_TYPE_ROUTER 4 /* <RouterId-4B>:<Local Discriminator Value-4B> */
#define ESI_TYPE_AS 5 /* <AS-4B>:<Local Discriminator Value-4B> */
#define MAX_ESI {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff}
#define ESI_LEN 10
#define MAX_ET 0xffffffff
u_long eth_tag_id;
struct attr;
@ -53,7 +55,12 @@ extern int str2esi(const char *str, struct eth_segment_id *id);
extern char *esi2str(struct eth_segment_id *id);
extern char *ecom_mac2str(char *ecom_mac);
extern void bgp_add_routermac_ecom(struct attr *attr, struct ethaddr *routermac);
extern void bgp_add_routermac_ecom(struct attr *attr,
struct ethaddr *routermac);
extern int bgp_build_evpn_prefix(int type, uint32_t eth_tag,
struct prefix *dst);
#endif /* _QUAGGA_BGP_ATTR_EVPN_H */
extern u_int32_t bgp_attr_mac_mobility_seqnum(struct attr *attr,
u_char *sticky);
#endif /* _QUAGGA_BGP_ATTR_EVPN_H */

File diff suppressed because it is too large Load Diff

View File

@ -23,25 +23,20 @@
#ifndef _QUAGGA_BGP_BFD_H
#define _QUAGGA_BGP_BFD_H
extern void
bgp_bfd_init(void);
extern void bgp_bfd_init(void);
extern void
bgp_bfd_peer_group2peer_copy(struct peer *conf, struct peer *peer);
extern void bgp_bfd_peer_group2peer_copy(struct peer *conf, struct peer *peer);
extern void
bgp_bfd_register_peer (struct peer *peer);
extern void bgp_bfd_register_peer(struct peer *peer);
extern void
bgp_bfd_deregister_peer (struct peer *peer);
extern void bgp_bfd_deregister_peer(struct peer *peer);
extern void
bgp_bfd_peer_config_write(struct vty *vty, struct peer *peer, char *addr);
extern void bgp_bfd_peer_config_write(struct vty *vty, struct peer *peer,
char *addr);
extern void
bgp_bfd_show_info(struct vty *vty, struct peer *peer, u_char use_json, json_object *json_neigh);
extern void bgp_bfd_show_info(struct vty *vty, struct peer *peer,
u_char use_json, json_object *json_neigh);
extern int
bgp_bfd_is_peer_multihop(struct peer *peer);
extern int bgp_bfd_is_peer_multihop(struct peer *peer);
#endif /* _QUAGGA_BGP_BFD_H */

View File

@ -35,280 +35,255 @@
#include "bgpd/bgp_aspath.h"
/* privileges */
static zebra_capabilities_t _caps_p [] =
{
ZCAP_BIND,
ZCAP_NET_RAW,
ZCAP_NET_ADMIN,
static zebra_capabilities_t _caps_p[] = {
ZCAP_BIND, ZCAP_NET_RAW, ZCAP_NET_ADMIN,
};
struct zebra_privs_t bgpd_privs =
{
struct zebra_privs_t bgpd_privs = {
#if defined(FRR_USER) && defined(FRR_GROUP)
.user = FRR_USER,
.group = FRR_GROUP,
.user = FRR_USER,
.group = FRR_GROUP,
#endif
#ifdef VTY_GROUP
.vty_group = VTY_GROUP,
.vty_group = VTY_GROUP,
#endif
.caps_p = _caps_p,
.cap_num_p = array_size(_caps_p),
.cap_num_i = 0,
.caps_p = _caps_p,
.cap_num_p = array_size(_caps_p),
.cap_num_i = 0,
};
enum MRT_MSG_TYPES {
MSG_NULL,
MSG_START, /* sender is starting up */
MSG_DIE, /* receiver should shut down */
MSG_I_AM_DEAD, /* sender is shutting down */
MSG_PEER_DOWN, /* sender's peer is down */
MSG_PROTOCOL_BGP, /* msg is a BGP packet */
MSG_PROTOCOL_RIP, /* msg is a RIP packet */
MSG_PROTOCOL_IDRP, /* msg is an IDRP packet */
MSG_PROTOCOL_RIPNG, /* msg is a RIPNG packet */
MSG_PROTOCOL_BGP4PLUS, /* msg is a BGP4+ packet */
MSG_PROTOCOL_BGP4PLUS_01, /* msg is a BGP4+ (draft 01) packet */
MSG_PROTOCOL_OSPF, /* msg is an OSPF packet */
MSG_TABLE_DUMP /* routing table dump */
MSG_NULL,
MSG_START, /* sender is starting up */
MSG_DIE, /* receiver should shut down */
MSG_I_AM_DEAD, /* sender is shutting down */
MSG_PEER_DOWN, /* sender's peer is down */
MSG_PROTOCOL_BGP, /* msg is a BGP packet */
MSG_PROTOCOL_RIP, /* msg is a RIP packet */
MSG_PROTOCOL_IDRP, /* msg is an IDRP packet */
MSG_PROTOCOL_RIPNG, /* msg is a RIPNG packet */
MSG_PROTOCOL_BGP4PLUS, /* msg is a BGP4+ packet */
MSG_PROTOCOL_BGP4PLUS_01, /* msg is a BGP4+ (draft 01) packet */
MSG_PROTOCOL_OSPF, /* msg is an OSPF packet */
MSG_TABLE_DUMP /* routing table dump */
};
static int
attr_parse (struct stream *s, u_int16_t len)
static int attr_parse(struct stream *s, u_int16_t len)
{
u_int flag;
u_int type;
u_int16_t length;
u_int16_t lim;
u_int flag;
u_int type;
u_int16_t length;
u_int16_t lim;
lim = s->getp + len;
lim = s->getp + len;
printf ("attr_parse s->getp %zd, len %d, lim %d\n", s->getp, len, lim);
printf("attr_parse s->getp %zd, len %d, lim %d\n", s->getp, len, lim);
while (s->getp < lim)
{
flag = stream_getc (s);
type = stream_getc (s);
while (s->getp < lim) {
flag = stream_getc(s);
type = stream_getc(s);
if (flag & BGP_ATTR_FLAG_EXTLEN)
length = stream_getw (s);
else
length = stream_getc (s);
if (flag & BGP_ATTR_FLAG_EXTLEN)
length = stream_getw(s);
else
length = stream_getc(s);
printf ("FLAG: %d\n", flag);
printf ("TYPE: %d\n", type);
printf ("Len: %d\n", length);
printf("FLAG: %d\n", flag);
printf("TYPE: %d\n", type);
printf("Len: %d\n", length);
switch (type)
{
case BGP_ATTR_ORIGIN:
{
u_char origin;
origin = stream_getc (s);
printf ("ORIGIN: %d\n", origin);
}
break;
case BGP_ATTR_AS_PATH:
{
struct aspath *aspath;
switch (type) {
case BGP_ATTR_ORIGIN: {
u_char origin;
origin = stream_getc(s);
printf("ORIGIN: %d\n", origin);
} break;
case BGP_ATTR_AS_PATH: {
struct aspath *aspath;
aspath = aspath_parse (s, length, 1);
printf ("ASPATH: %s\n", aspath->str);
aspath_free(aspath);
}
break;
case BGP_ATTR_NEXT_HOP:
{
struct in_addr nexthop;
nexthop.s_addr = stream_get_ipv4 (s);
printf ("NEXTHOP: %s\n", inet_ntoa (nexthop));
}
break;
default:
stream_getw_from (s, length);
break;
aspath = aspath_parse(s, length, 1);
printf("ASPATH: %s\n", aspath->str);
aspath_free(aspath);
} break;
case BGP_ATTR_NEXT_HOP: {
struct in_addr nexthop;
nexthop.s_addr = stream_get_ipv4(s);
printf("NEXTHOP: %s\n", inet_ntoa(nexthop));
} break;
default:
stream_getw_from(s, length);
break;
}
}
}
return 0;
return 0;
}
int
main (int argc, char **argv)
int main(int argc, char **argv)
{
int ret;
FILE *fp;
struct stream *s;
time_t now;
int type;
int subtype;
size_t len;
int source_as;
int dest_as;
ifindex_t ifindex;
int family;
struct in_addr sip;
struct in_addr dip;
u_int16_t viewno, seq_num;
struct prefix_ipv4 p;
int ret;
FILE *fp;
struct stream *s;
time_t now;
int type;
int subtype;
size_t len;
int source_as;
int dest_as;
ifindex_t ifindex;
int family;
struct in_addr sip;
struct in_addr dip;
u_int16_t viewno, seq_num;
struct prefix_ipv4 p;
s = stream_new (10000);
s = stream_new(10000);
if (argc != 2)
{
fprintf (stderr, "Usage: %s FILENAME\n", argv[0]);
exit (1);
}
fp = fopen (argv[1], "r");
if (!fp)
{
fprintf (stdout,"%% Can't open configuration file %s due to '%s'.\n",
argv[1], safe_strerror(errno));
exit (1);
}
while (1)
{
stream_reset (s);
ret = fread (s->data, 12, 1, fp);
if (!ret || feof (fp))
{
printf ("END OF FILE\n");
break;
if (argc != 2) {
fprintf(stderr, "Usage: %s FILENAME\n", argv[0]);
exit(1);
}
if (ferror (fp))
{
printf ("ERROR OF FREAD\n");
break;
fp = fopen(argv[1], "r");
if (!fp) {
fprintf(stdout,
"%% Can't open configuration file %s due to '%s'.\n",
argv[1], safe_strerror(errno));
exit(1);
}
/* Extract header. */
now = stream_getl (s);
type = stream_getw (s);
subtype = stream_getw (s);
len = stream_getl (s);
while (1) {
stream_reset(s);
printf ("TIME: %s", ctime (&now));
ret = fread(s->data, 12, 1, fp);
if (!ret || feof(fp)) {
printf("END OF FILE\n");
break;
}
if (ferror(fp)) {
printf("ERROR OF FREAD\n");
break;
}
/* printf ("TYPE: %d/%d\n", type, subtype); */
/* Extract header. */
now = stream_getl(s);
type = stream_getw(s);
subtype = stream_getw(s);
len = stream_getl(s);
if (type == MSG_PROTOCOL_BGP4MP)
printf ("TYPE: BGP4MP");
else if (type == MSG_PROTOCOL_BGP4MP_ET)
printf ("TYPE: BGP4MP_ET");
else if (type == MSG_TABLE_DUMP)
printf ("TYPE: MSG_TABLE_DUMP");
else
printf ("TYPE: Unknown %d", type);
printf("TIME: %s", ctime(&now));
if (type == MSG_TABLE_DUMP)
switch (subtype)
{
case AFI_IP:
printf ("/AFI_IP\n");
break;
case AFI_IP6:
printf ("/AFI_IP6\n");
break;
default:
printf ("/UNKNOWN %d", subtype);
break;
}
else
{
switch (subtype)
{
case BGP4MP_STATE_CHANGE:
printf ("/CHANGE\n");
break;
case BGP4MP_MESSAGE:
printf ("/MESSAGE\n");
break;
case BGP4MP_ENTRY:
printf ("/ENTRY\n");
break;
case BGP4MP_SNAPSHOT:
printf ("/SNAPSHOT\n");
break;
default:
printf ("/UNKNOWN %d", subtype);
break;
}
/* printf ("TYPE: %d/%d\n", type, subtype); */
if (type == MSG_PROTOCOL_BGP4MP)
printf("TYPE: BGP4MP");
else if (type == MSG_PROTOCOL_BGP4MP_ET)
printf("TYPE: BGP4MP_ET");
else if (type == MSG_TABLE_DUMP)
printf("TYPE: MSG_TABLE_DUMP");
else
printf("TYPE: Unknown %d", type);
if (type == MSG_TABLE_DUMP)
switch (subtype) {
case AFI_IP:
printf("/AFI_IP\n");
break;
case AFI_IP6:
printf("/AFI_IP6\n");
break;
default:
printf("/UNKNOWN %d", subtype);
break;
}
else {
switch (subtype) {
case BGP4MP_STATE_CHANGE:
printf("/CHANGE\n");
break;
case BGP4MP_MESSAGE:
printf("/MESSAGE\n");
break;
case BGP4MP_ENTRY:
printf("/ENTRY\n");
break;
case BGP4MP_SNAPSHOT:
printf("/SNAPSHOT\n");
break;
default:
printf("/UNKNOWN %d", subtype);
break;
}
}
printf("len: %zd\n", len);
fread(s->data + 12, len, 1, fp);
if (feof(fp)) {
printf("ENDOF FILE 2\n");
break;
}
if (ferror(fp)) {
printf("ERROR OF FREAD 2\n");
break;
}
/* printf ("now read %d\n", len); */
if (type == MSG_TABLE_DUMP) {
u_char status;
time_t originated;
struct in_addr peer;
u_int16_t attrlen;
viewno = stream_getw(s);
seq_num = stream_getw(s);
printf("VIEW: %d\n", viewno);
printf("SEQUENCE: %d\n", seq_num);
/* start */
while (s->getp < len - 16) {
p.prefix.s_addr = stream_get_ipv4(s);
p.prefixlen = stream_getc(s);
printf("PREFIX: %s/%d\n", inet_ntoa(p.prefix),
p.prefixlen);
status = stream_getc(s);
originated = stream_getl(s);
peer.s_addr = stream_get_ipv4(s);
source_as = stream_getw(s);
printf("FROM: %s AS%d\n", inet_ntoa(peer),
source_as);
printf("ORIGINATED: %s", ctime(&originated));
attrlen = stream_getw(s);
printf("ATTRLEN: %d\n", attrlen);
attr_parse(s, attrlen);
printf("STATUS: 0x%x\n", status);
}
} else {
source_as = stream_getw(s);
dest_as = stream_getw(s);
printf("source_as: %d\n", source_as);
printf("dest_as: %d\n", dest_as);
ifindex = stream_getw(s);
family = stream_getw(s);
printf("ifindex: %d\n", ifindex);
printf("family: %d\n", family);
sip.s_addr = stream_get_ipv4(s);
dip.s_addr = stream_get_ipv4(s);
printf("saddr: %s\n", inet_ntoa(sip));
printf("daddr: %s\n", inet_ntoa(dip));
printf("\n");
}
}
printf ("len: %zd\n", len);
fread (s->data + 12, len, 1, fp);
if (feof (fp))
{
printf ("ENDOF FILE 2\n");
break;
}
if (ferror (fp))
{
printf ("ERROR OF FREAD 2\n");
break;
}
/* printf ("now read %d\n", len); */
if (type == MSG_TABLE_DUMP)
{
u_char status;
time_t originated;
struct in_addr peer;
u_int16_t attrlen;
viewno = stream_getw (s);
seq_num = stream_getw (s);
printf ("VIEW: %d\n", viewno);
printf ("SEQUENCE: %d\n", seq_num);
/* start */
while (s->getp < len - 16)
{
p.prefix.s_addr = stream_get_ipv4 (s);
p.prefixlen = stream_getc (s);
printf ("PREFIX: %s/%d\n", inet_ntoa (p.prefix), p.prefixlen);
status = stream_getc (s);
originated = stream_getl (s);
peer.s_addr = stream_get_ipv4 (s);
source_as = stream_getw(s);
printf ("FROM: %s AS%d\n", inet_ntoa (peer), source_as);
printf ("ORIGINATED: %s", ctime (&originated));
attrlen = stream_getw (s);
printf ("ATTRLEN: %d\n", attrlen);
attr_parse (s, attrlen);
printf ("STATUS: 0x%x\n", status);
}
}
else
{
source_as = stream_getw (s);
dest_as = stream_getw (s);
printf ("source_as: %d\n", source_as);
printf ("dest_as: %d\n", dest_as);
ifindex = stream_getw (s);
family = stream_getw (s);
printf ("ifindex: %d\n", ifindex);
printf ("family: %d\n", family);
sip.s_addr = stream_get_ipv4 (s);
dip.s_addr = stream_get_ipv4 (s);
printf ("saddr: %s\n", inet_ntoa (sip));
printf ("daddr: %s\n", inet_ntoa (dip));
printf ("\n");
}
}
fclose (fp);
return 0;
fclose(fp);
return 0;
}

File diff suppressed because it is too large Load Diff

View File

@ -43,82 +43,76 @@
#define LARGE_COMMUNITY_LIST_EXPANDED 5 /* Expanded Large community-list. */
/* Community-list. */
struct community_list
{
/* Name of the community-list. */
char *name;
struct community_list {
/* Name of the community-list. */
char *name;
/* String or number. */
int sort;
/* String or number. */
int sort;
/* Link to upper list. */
struct community_list_list *parent;
/* Link to upper list. */
struct community_list_list *parent;
/* Linked list for other community-list. */
struct community_list *next;
struct community_list *prev;
/* Linked list for other community-list. */
struct community_list *next;
struct community_list *prev;
/* Community-list entry in this community-list. */
struct community_entry *head;
struct community_entry *tail;
/* Community-list entry in this community-list. */
struct community_entry *head;
struct community_entry *tail;
};
/* Each entry in community-list. */
struct community_entry
{
struct community_entry *next;
struct community_entry *prev;
struct community_entry {
struct community_entry *next;
struct community_entry *prev;
/* Permit or deny. */
u_char direct;
/* Permit or deny. */
u_char direct;
/* Standard or expanded. */
u_char style;
/* Standard or expanded. */
u_char style;
/* Any match. */
u_char any;
/* Any match. */
u_char any;
/* Community structure. */
union
{
struct community *com;
struct ecommunity *ecom;
struct lcommunity *lcom;
} u;
/* Community structure. */
union {
struct community *com;
struct ecommunity *ecom;
struct lcommunity *lcom;
} u;
/* Configuration string. */
char *config;
/* Configuration string. */
char *config;
/* Expanded community-list regular expression. */
regex_t *reg;
/* Expanded community-list regular expression. */
regex_t *reg;
};
/* Linked list of community-list. */
struct community_list_list
{
struct community_list *head;
struct community_list *tail;
struct community_list_list {
struct community_list *head;
struct community_list *tail;
};
/* Master structure of community-list and extcommunity-list. */
struct community_list_master
{
struct community_list_list num;
struct community_list_list str;
struct community_list_master {
struct community_list_list num;
struct community_list_list str;
};
/* Community-list handler. community_list_init() returns this
structure as handler. */
struct community_list_handler
{
/* Community-list. */
struct community_list_master community_list;
struct community_list_handler {
/* Community-list. */
struct community_list_master community_list;
/* Exteded community-list. */
struct community_list_master extcommunity_list;
/* Exteded community-list. */
struct community_list_master extcommunity_list;
/* Large community-list. */
struct community_list_master lcommunity_list;
/* Large community-list. */
struct community_list_master lcommunity_list;
};
/* Error code of community-list. */
@ -131,42 +125,42 @@ struct community_list_handler
extern struct community_list_handler *bgp_clist;
/* Prototypes. */
extern struct community_list_handler *community_list_init (void);
extern void community_list_terminate (struct community_list_handler *);
extern struct community_list_handler *community_list_init(void);
extern void community_list_terminate(struct community_list_handler *);
extern int community_list_set (struct community_list_handler *ch,
extern int community_list_set(struct community_list_handler *ch,
const char *name, const char *str, int direct,
int style);
extern int community_list_unset(struct community_list_handler *ch,
const char *name, const char *str, int direct,
int style, int delete_all);
extern int extcommunity_list_set(struct community_list_handler *ch,
const char *name, const char *str, int direct,
int style);
extern int extcommunity_list_unset(struct community_list_handler *ch,
const char *name, const char *str,
int direct, int style, int delete_all);
extern int lcommunity_list_set(struct community_list_handler *ch,
const char *name, const char *str, int direct,
int style);
extern int community_list_unset (struct community_list_handler *ch,
const char *name, const char *str,
int direct, int style, int delete_all);
extern int extcommunity_list_set (struct community_list_handler *ch,
const char *name, const char *str,
int direct, int style);
extern int extcommunity_list_unset (struct community_list_handler *ch,
const char *name, const char *str,
int direct, int style, int delete_all);
extern int lcommunity_list_set (struct community_list_handler *ch,
const char *name, const char *str,
int direct, int style);
extern int lcommunity_list_unset (struct community_list_handler *ch,
const char *name, const char *str,
int direct, int style);
extern int lcommunity_list_unset(struct community_list_handler *ch,
const char *name, const char *str, int direct,
int style);
extern struct community_list_master *
community_list_master_lookup (struct community_list_handler *, int);
community_list_master_lookup(struct community_list_handler *, int);
extern struct community_list *
community_list_lookup (struct community_list_handler *, const char *, int);
community_list_lookup(struct community_list_handler *, const char *, int);
extern int community_list_match (struct community *, struct community_list *);
extern int ecommunity_list_match (struct ecommunity *, struct community_list *);
extern int lcommunity_list_match (struct lcommunity *, struct community_list *);
extern int community_list_exact_match (struct community *,
struct community_list *);
extern struct community *
community_list_match_delete (struct community *, struct community_list *);
extern int community_list_match(struct community *, struct community_list *);
extern int ecommunity_list_match(struct ecommunity *, struct community_list *);
extern int lcommunity_list_match(struct lcommunity *, struct community_list *);
extern int community_list_exact_match(struct community *,
struct community_list *);
extern struct community *community_list_match_delete(struct community *,
struct community_list *);
extern struct lcommunity *
lcommunity_list_match_delete (struct lcommunity *lcom,
struct community_list *list);
lcommunity_list_match_delete(struct lcommunity *lcom,
struct community_list *list);
#endif /* _QUAGGA_BGP_CLIST_H */

File diff suppressed because it is too large Load Diff

View File

@ -24,23 +24,22 @@
#include "lib/json.h"
/* Communities attribute. */
struct community
{
/* Reference count of communities value. */
unsigned long refcnt;
struct community {
/* Reference count of communities value. */
unsigned long refcnt;
/* Communities value size. */
int size;
/* Communities value size. */
int size;
/* Communities value. */
u_int32_t *val;
/* Communities value. */
u_int32_t *val;
/* Communities as a json object */
json_object *json;
/* Communities as a json object */
json_object *json;
/* String of community attribute. This sring is used by vty output
and expanded community-list for regular expression match. */
char *str;
/* String of community attribute. This sring is used by vty output
and expanded community-list for regular expression match. */
char *str;
};
/* Well-known communities value. */
@ -56,25 +55,27 @@ struct community
#define com_nthval(X,n) ((X)->val + (n))
/* Prototypes of communities attribute functions. */
extern void community_init (void);
extern void community_finish (void);
extern void community_free (struct community *);
extern struct community *community_uniq_sort (struct community *);
extern struct community *community_parse (u_int32_t *, u_short);
extern struct community *community_intern (struct community *);
extern void community_unintern (struct community **);
extern char *community_str (struct community *);
extern unsigned int community_hash_make (struct community *);
extern struct community *community_str2com (const char *);
extern int community_match (const struct community *, const struct community *);
extern int community_cmp (const struct community *, const struct community *);
extern struct community *community_merge (struct community *, struct community *);
extern struct community *community_delete (struct community *, struct community *);
extern struct community *community_dup (struct community *);
extern int community_include (struct community *, u_int32_t);
extern void community_del_val (struct community *, u_int32_t *);
extern unsigned long community_count (void);
extern struct hash *community_hash (void);
extern u_int32_t community_val_get (struct community *com, int i);
extern void community_init(void);
extern void community_finish(void);
extern void community_free(struct community *);
extern struct community *community_uniq_sort(struct community *);
extern struct community *community_parse(u_int32_t *, u_short);
extern struct community *community_intern(struct community *);
extern void community_unintern(struct community **);
extern char *community_str(struct community *);
extern unsigned int community_hash_make(struct community *);
extern struct community *community_str2com(const char *);
extern int community_match(const struct community *, const struct community *);
extern int community_cmp(const struct community *, const struct community *);
extern struct community *community_merge(struct community *,
struct community *);
extern struct community *community_delete(struct community *,
struct community *);
extern struct community *community_dup(struct community *);
extern int community_include(struct community *, u_int32_t);
extern void community_del_val(struct community *, u_int32_t *);
extern unsigned long community_count(void);
extern struct hash *community_hash(void);
extern u_int32_t community_val_get(struct community *com, int i);
#endif /* _QUAGGA_BGP_COMMUNITY_H */

File diff suppressed because it is too large Load Diff

View File

@ -22,92 +22,90 @@
#define _QUAGGA_BGP_DAMP_H
/* Structure maintained on a per-route basis. */
struct bgp_damp_info
{
/* Doubly linked list. This information must be linked to
reuse_list or no_reuse_list. */
struct bgp_damp_info *next;
struct bgp_damp_info *prev;
struct bgp_damp_info {
/* Doubly linked list. This information must be linked to
reuse_list or no_reuse_list. */
struct bgp_damp_info *next;
struct bgp_damp_info *prev;
/* Figure-of-merit. */
unsigned int penalty;
/* Figure-of-merit. */
unsigned int penalty;
/* Number of flapping. */
unsigned int flap;
/* First flap time */
time_t start_time;
/* Last time penalty was updated. */
time_t t_updated;
/* Number of flapping. */
unsigned int flap;
/* Time of route start to be suppressed. */
time_t suppress_time;
/* First flap time */
time_t start_time;
/* Back reference to bgp_info. */
struct bgp_info *binfo;
/* Last time penalty was updated. */
time_t t_updated;
/* Back reference to bgp_node. */
struct bgp_node *rn;
/* Time of route start to be suppressed. */
time_t suppress_time;
/* Current index in the reuse_list. */
int index;
/* Back reference to bgp_info. */
struct bgp_info *binfo;
/* Last time message type. */
u_char lastrecord;
/* Back reference to bgp_node. */
struct bgp_node *rn;
/* Current index in the reuse_list. */
int index;
/* Last time message type. */
u_char lastrecord;
#define BGP_RECORD_UPDATE 1U
#define BGP_RECORD_WITHDRAW 2U
afi_t afi;
safi_t safi;
afi_t afi;
safi_t safi;
};
/* Specified parameter set configuration. */
struct bgp_damp_config
{
/* Value over which routes suppressed. */
unsigned int suppress_value;
struct bgp_damp_config {
/* Value over which routes suppressed. */
unsigned int suppress_value;
/* Value below which suppressed routes reused. */
unsigned int reuse_limit;
/* Value below which suppressed routes reused. */
unsigned int reuse_limit;
/* Max time a route can be suppressed. */
time_t max_suppress_time;
/* Max time a route can be suppressed. */
time_t max_suppress_time;
/* Time during which accumulated penalty reduces by half. */
time_t half_life;
/* Time during which accumulated penalty reduces by half. */
time_t half_life;
/* Non-configurable parameters but fixed at implementation time.
* To change this values, init_bgp_damp() should be modified.
*/
time_t tmax; /* Max time previous instability retained */
unsigned int reuse_list_size; /* Number of reuse lists */
unsigned int reuse_index_size; /* Size of reuse index array */
/* Non-configurable parameters but fixed at implementation time.
* To change this values, init_bgp_damp() should be modified.
*/
time_t tmax; /* Max time previous instability retained */
unsigned int reuse_list_size; /* Number of reuse lists */
unsigned int reuse_index_size; /* Size of reuse index array */
/* Non-configurable parameters. Most of these are calculated from
* the configurable parameters above.
*/
unsigned int ceiling; /* Max value a penalty can attain */
unsigned int decay_rate_per_tick; /* Calculated from half-life */
unsigned int decay_array_size; /* Calculated using config parameters */
double scale_factor;
unsigned int reuse_scale_factor;
/* Decay array per-set based. */
double *decay_array;
/* Non-configurable parameters. Most of these are calculated from
* the configurable parameters above.
*/
unsigned int ceiling; /* Max value a penalty can attain */
unsigned int decay_rate_per_tick; /* Calculated from half-life */
unsigned int decay_array_size; /* Calculated using config parameters */
double scale_factor;
unsigned int reuse_scale_factor;
/* Reuse index array per-set based. */
int *reuse_index;
/* Decay array per-set based. */
double *decay_array;
/* Reuse list array per-set based. */
struct bgp_damp_info **reuse_list;
int reuse_offset;
/* All dampening information which is not on reuse list. */
struct bgp_damp_info *no_reuse_list;
/* Reuse index array per-set based. */
int *reuse_index;
/* Reuse timer thread per-set base. */
struct thread* t_reuse;
/* Reuse list array per-set based. */
struct bgp_damp_info **reuse_list;
int reuse_offset;
/* All dampening information which is not on reuse list. */
struct bgp_damp_info *no_reuse_list;
/* Reuse timer thread per-set base. */
struct thread *t_reuse;
};
#define BGP_DAMP_NONE 0
@ -129,20 +127,22 @@ struct bgp_damp_config
#define REUSE_LIST_SIZE 256
#define REUSE_ARRAY_SIZE 1024
extern int bgp_damp_enable (struct bgp *, afi_t, safi_t, time_t, unsigned int,
unsigned int, time_t);
extern int bgp_damp_disable (struct bgp *, afi_t, safi_t);
extern int bgp_damp_withdraw (struct bgp_info *, struct bgp_node *,
afi_t, safi_t, int);
extern int bgp_damp_update (struct bgp_info *, struct bgp_node *, afi_t, safi_t);
extern int bgp_damp_scan (struct bgp_info *, afi_t, safi_t);
extern void bgp_damp_info_free (struct bgp_damp_info *, int);
extern void bgp_damp_info_clean (void);
extern int bgp_damp_decay (time_t, int);
extern void bgp_config_write_damp (struct vty *);
extern void bgp_damp_info_vty (struct vty *, struct bgp_info *, json_object *json_path);
extern const char * bgp_damp_reuse_time_vty (struct vty *, struct bgp_info *,
char *, size_t, u_char, json_object *);
extern int bgp_show_dampening_parameters (struct vty *vty, afi_t, safi_t);
extern int bgp_damp_enable(struct bgp *, afi_t, safi_t, time_t, unsigned int,
unsigned int, time_t);
extern int bgp_damp_disable(struct bgp *, afi_t, safi_t);
extern int bgp_damp_withdraw(struct bgp_info *, struct bgp_node *, afi_t,
safi_t, int);
extern int bgp_damp_update(struct bgp_info *, struct bgp_node *, afi_t, safi_t);
extern int bgp_damp_scan(struct bgp_info *, afi_t, safi_t);
extern void bgp_damp_info_free(struct bgp_damp_info *, int);
extern void bgp_damp_info_clean(void);
extern int bgp_damp_decay(time_t, int);
extern void bgp_config_write_damp(struct vty *);
extern void bgp_damp_info_vty(struct vty *, struct bgp_info *,
json_object *json_path);
extern const char *bgp_damp_reuse_time_vty(struct vty *, struct bgp_info *,
char *, size_t, u_char,
json_object *);
extern int bgp_show_dampening_parameters(struct vty *vty, afi_t, safi_t);
#endif /* _QUAGGA_BGP_DAMP_H */

File diff suppressed because it is too large Load Diff

View File

@ -57,10 +57,10 @@ extern int Debug_Radix;
#define DETAIL 6
/* Prototypes. */
extern void bgp_debug_init (void);
extern void bgp_packet_dump (struct stream *);
extern void bgp_debug_init(void);
extern void bgp_packet_dump(struct stream *);
extern int debug (unsigned int option);
extern int debug(unsigned int option);
extern unsigned long conf_bgp_debug_as4;
extern unsigned long conf_bgp_debug_neighbor_events;
@ -92,10 +92,9 @@ extern struct list *bgp_debug_update_prefixes;
extern struct list *bgp_debug_bestpath_prefixes;
extern struct list *bgp_debug_zebra_prefixes;
struct bgp_debug_filter
{
char *host;
struct prefix *p;
struct bgp_debug_filter {
char *host;
struct prefix *p;
};
#define BGP_DEBUG_AS4 0x01
@ -122,39 +121,41 @@ struct bgp_debug_filter
#define TERM_DEBUG_ON(a, b) (term_bgp_debug_ ## a |= (BGP_DEBUG_ ## b))
#define TERM_DEBUG_OFF(a, b) (term_bgp_debug_ ## a &= ~(BGP_DEBUG_ ## b))
#define DEBUG_ON(a, b) \
do { \
CONF_DEBUG_ON(a, b); \
TERM_DEBUG_ON(a, b); \
} while (0)
#define DEBUG_OFF(a, b) \
do { \
CONF_DEBUG_OFF(a, b); \
TERM_DEBUG_OFF(a, b); \
} while (0)
#define DEBUG_ON(a, b) \
do { \
CONF_DEBUG_ON(a, b); \
TERM_DEBUG_ON(a, b); \
} while (0)
#define DEBUG_OFF(a, b) \
do { \
CONF_DEBUG_OFF(a, b); \
TERM_DEBUG_OFF(a, b); \
} while (0)
#define BGP_DEBUG(a, b) (term_bgp_debug_ ## a & BGP_DEBUG_ ## b)
#define CONF_BGP_DEBUG(a, b) (conf_bgp_debug_ ## a & BGP_DEBUG_ ## b)
extern const char *bgp_type_str[];
extern int bgp_dump_attr (struct attr *, char *, size_t);
extern int bgp_dump_attr(struct attr *, char *, size_t);
extern int bgp_debug_peer_updout_enabled(char *host);
extern const char *bgp_notify_code_str(char);
extern const char *bgp_notify_subcode_str(char, char);
extern void bgp_notify_print (struct peer *, struct bgp_notify *, const char *);
extern void bgp_notify_print(struct peer *, struct bgp_notify *, const char *);
extern const struct message bgp_status_msg[];
extern int bgp_debug_neighbor_events(struct peer *peer);
extern int bgp_debug_keepalive(struct peer *peer);
extern int bgp_debug_update(struct peer *peer, struct prefix *p,
struct update_group *updgrp, unsigned int inbound);
struct update_group *updgrp, unsigned int inbound);
extern int bgp_debug_bestpath(struct prefix *p);
extern int bgp_debug_zebra(struct prefix *p);
extern int bgp_debug_count(void);
extern const char *bgp_debug_rdpfxpath2str (struct prefix_rd *, union prefixconstptr,
int, u_int32_t, char *, int);
const char *bgp_notify_admin_message(char *buf, size_t bufsz, u_char *data, size_t datalen);
extern const char *bgp_debug_rdpfxpath2str(afi_t, safi_t, struct prefix_rd *,
union prefixconstptr, mpls_label_t *,
int, u_int32_t, char *, int);
const char *bgp_notify_admin_message(char *buf, size_t bufsz, u_char *data,
size_t datalen);
#endif /* _QUAGGA_BGP_DEBUG_H */

File diff suppressed because it is too large Load Diff

View File

@ -49,9 +49,9 @@
#define TABLE_DUMP_V2_PEER_INDEX_TABLE_AS2 0
#define TABLE_DUMP_V2_PEER_INDEX_TABLE_AS4 2
extern void bgp_dump_init (void);
extern void bgp_dump_finish (void);
extern void bgp_dump_state (struct peer *, int, int);
extern void bgp_dump_packet (struct peer *, int, struct stream *);
extern void bgp_dump_init(void);
extern void bgp_dump_finish(void);
extern void bgp_dump_state(struct peer *, int, int);
extern void bgp_dump_packet(struct peer *, int, struct stream *);
#endif /* _QUAGGA_BGP_DUMP_H */

File diff suppressed because it is too large Load Diff

View File

@ -32,12 +32,15 @@
#define ECOMMUNITY_ROUTE_TARGET 0x02
#define ECOMMUNITY_SITE_ORIGIN 0x03
/* Low-order octet of the Extended Communities type field for EVPN types */
#define ECOMMUNITY_EVPN_SUBTYPE_MACMOBILITY 0x00
#define ECOMMUNITY_EVPN_SUBTYPE_ESI_LABEL 0x01
#define ECOMMUNITY_EVPN_SUBTYPE_ES_IMPORT_RT 0x02
#define ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC 0x03
#define ECOMMUNITY_EVPN_SUBTYPE_DEF_GW 0x0d
#define ECOMMUNITY_EVPN_SUBTYPE_MACMOBILITY_FLAG_STICKY 0x01
/* Low-order octet of the Extended Communities type field for OPAQUE types */
#define ECOMMUNITY_OPAQUE_SUBTYPE_ENCAP 0x0c
@ -53,50 +56,98 @@
#define ECOMMUNITY_FLAG_NON_TRANSITIVE 0x40
/* Extended Communities attribute. */
struct ecommunity
{
/* Reference counter. */
unsigned long refcnt;
struct ecommunity {
/* Reference counter. */
unsigned long refcnt;
/* Size of Extended Communities attribute. */
int size;
/* Size of Extended Communities attribute. */
int size;
/* Extended Communities value. */
u_int8_t *val;
/* Extended Communities value. */
u_int8_t *val;
/* Human readable format string. */
char *str;
/* Human readable format string. */
char *str;
};
/* Extended community value is eight octet. */
struct ecommunity_val
{
char val[ECOMMUNITY_SIZE];
struct ecommunity_val {
char val[ECOMMUNITY_SIZE];
};
#define ecom_length(X) ((X)->size * ECOMMUNITY_SIZE)
extern void ecommunity_init (void);
extern void ecommunity_finish (void);
extern void ecommunity_free (struct ecommunity **);
extern struct ecommunity *ecommunity_parse (u_int8_t *, u_short);
extern struct ecommunity *ecommunity_dup (struct ecommunity *);
extern struct ecommunity *ecommunity_merge (struct ecommunity *, struct ecommunity *);
extern struct ecommunity *ecommunity_uniq_sort (struct ecommunity *);
extern struct ecommunity *ecommunity_intern (struct ecommunity *);
extern int ecommunity_cmp (const void *, const void *);
extern void ecommunity_unintern (struct ecommunity **);
extern unsigned int ecommunity_hash_make (void *);
extern struct ecommunity *ecommunity_str2com (const char *, int, int);
extern char *ecommunity_ecom2str (struct ecommunity *, int, int);
extern int ecommunity_match (const struct ecommunity *, const struct ecommunity *);
extern char *ecommunity_str (struct ecommunity *);
extern struct ecommunity_val *ecommunity_lookup (const struct ecommunity *, uint8_t, uint8_t );
extern int ecommunity_add_val (struct ecommunity *ecom, struct ecommunity_val *eval);
/*
* Encode BGP Route Target AS:nn.
*/
static inline void encode_route_target_as(as_t as, u_int32_t val,
struct ecommunity_val *eval)
{
eval->val[0] = ECOMMUNITY_ENCODE_AS;
eval->val[1] = ECOMMUNITY_ROUTE_TARGET;
eval->val[2] = (as >> 8) & 0xff;
eval->val[3] = as & 0xff;
eval->val[4] = (val >> 24) & 0xff;
eval->val[5] = (val >> 16) & 0xff;
eval->val[6] = (val >> 8) & 0xff;
eval->val[7] = val & 0xff;
}
/*
* Encode BGP Route Target IP:nn.
*/
static inline void encode_route_target_ip(struct in_addr ip, u_int16_t val,
struct ecommunity_val *eval)
{
eval->val[0] = ECOMMUNITY_ENCODE_IP;
eval->val[1] = ECOMMUNITY_ROUTE_TARGET;
memcpy(&eval->val[2], &ip, sizeof(struct in_addr));
eval->val[6] = (val >> 8) & 0xff;
eval->val[7] = val & 0xff;
}
/*
* Encode BGP Route Target AS4:nn.
*/
static inline void encode_route_target_as4(as_t as, u_int16_t val,
struct ecommunity_val *eval)
{
eval->val[0] = ECOMMUNITY_ENCODE_AS4;
eval->val[1] = ECOMMUNITY_ROUTE_TARGET;
eval->val[2] = (as >> 24) & 0xff;
eval->val[3] = (as >> 16) & 0xff;
eval->val[4] = (as >> 8) & 0xff;
eval->val[5] = as & 0xff;
eval->val[6] = (val >> 8) & 0xff;
eval->val[7] = val & 0xff;
}
extern void ecommunity_init(void);
extern void ecommunity_finish(void);
extern void ecommunity_free(struct ecommunity **);
extern struct ecommunity *ecommunity_parse(u_int8_t *, u_short);
extern struct ecommunity *ecommunity_dup(struct ecommunity *);
extern struct ecommunity *ecommunity_merge(struct ecommunity *,
struct ecommunity *);
extern struct ecommunity *ecommunity_uniq_sort(struct ecommunity *);
extern struct ecommunity *ecommunity_intern(struct ecommunity *);
extern int ecommunity_cmp(const void *, const void *);
extern void ecommunity_unintern(struct ecommunity **);
extern unsigned int ecommunity_hash_make(void *);
extern struct ecommunity *ecommunity_str2com(const char *, int, int);
extern char *ecommunity_ecom2str(struct ecommunity *, int, int);
extern int ecommunity_match(const struct ecommunity *,
const struct ecommunity *);
extern char *ecommunity_str(struct ecommunity *);
extern struct ecommunity_val *ecommunity_lookup(const struct ecommunity *,
uint8_t, uint8_t);
extern int ecommunity_add_val(struct ecommunity *ecom,
struct ecommunity_val *eval);
/* for vpn */
extern struct ecommunity *ecommunity_new (void);
extern int ecommunity_add_val (struct ecommunity *, struct ecommunity_val *);
extern int ecommunity_strip (struct ecommunity *ecom, uint8_t type, uint8_t subtype);
extern struct ecommunity *ecommunity_new (void);
extern struct ecommunity *ecommunity_new(void);
extern int ecommunity_add_val(struct ecommunity *, struct ecommunity_val *);
extern int ecommunity_strip(struct ecommunity *ecom, uint8_t type,
uint8_t subtype);
extern struct ecommunity *ecommunity_new(void);
#endif /* _QUAGGA_BGP_ECOMMUNITY_H */

File diff suppressed because it is too large Load Diff

View File

@ -19,158 +19,116 @@
#ifndef _QUAGGA_BGP_ENCAP_TLV_H
#define _QUAGGA_BGP_ENCAP_TLV_H
/***********************************************************************
* TUNNEL TYPE-SPECIFIC TLV ENCODE
***********************************************************************/
extern void
bgp_encap_type_l2tpv3overip_to_tlv(
struct bgp_encap_type_l2tpv3_over_ip *bet,
struct attr *attr);
bgp_encap_type_l2tpv3overip_to_tlv(struct bgp_encap_type_l2tpv3_over_ip *bet,
struct attr *attr);
extern void bgp_encap_type_gre_to_tlv(struct bgp_encap_type_gre *bet,
struct attr *attr);
extern void bgp_encap_type_ip_in_ip_to_tlv(struct bgp_encap_type_ip_in_ip *bet,
struct attr *attr);
extern void bgp_encap_type_transmit_tunnel_endpoint(
struct bgp_encap_type_transmit_tunnel_endpoint *bet, struct attr *attr);
extern void bgp_encap_type_ipsec_in_tunnel_mode_to_tlv(
struct bgp_encap_type_ipsec_in_tunnel_mode *bet, struct attr *attr);
extern void bgp_encap_type_ip_in_ip_tunnel_with_ipsec_transport_mode_to_tlv(
struct bgp_encap_type_ip_in_ip_tunnel_with_ipsec_transport_mode *bet,
struct attr *attr);
extern void bgp_encap_type_mpls_in_ip_tunnel_with_ipsec_transport_mode_to_tlv(
struct bgp_encap_type_mpls_in_ip_tunnel_with_ipsec_transport_mode *bet,
struct attr *attr);
extern void bgp_encap_type_pbb_to_tlv(struct bgp_encap_type_pbb *bet,
struct attr *attr);
extern void bgp_encap_type_vxlan_to_tlv(struct bgp_encap_type_vxlan *bet,
struct attr *attr);
extern void bgp_encap_type_nvgre_to_tlv(struct bgp_encap_type_nvgre *bet,
struct attr *attr);
extern void bgp_encap_type_mpls_to_tlv(struct bgp_encap_type_mpls *bet,
struct attr *attr);
extern void
bgp_encap_type_gre_to_tlv(
struct bgp_encap_type_gre *bet,
struct attr *attr);
bgp_encap_type_mpls_in_gre_to_tlv(struct bgp_encap_type_mpls_in_gre *bet,
struct attr *attr);
extern void
bgp_encap_type_ip_in_ip_to_tlv(
struct bgp_encap_type_ip_in_ip *bet,
struct attr *attr);
bgp_encap_type_vxlan_gpe_to_tlv(struct bgp_encap_type_vxlan_gpe *bet,
struct attr *attr);
extern void
bgp_encap_type_transmit_tunnel_endpoint(
struct bgp_encap_type_transmit_tunnel_endpoint *bet,
struct attr *attr);
extern void
bgp_encap_type_ipsec_in_tunnel_mode_to_tlv(
struct bgp_encap_type_ipsec_in_tunnel_mode *bet,
struct attr *attr);
extern void
bgp_encap_type_ip_in_ip_tunnel_with_ipsec_transport_mode_to_tlv(
struct bgp_encap_type_ip_in_ip_tunnel_with_ipsec_transport_mode *bet,
struct attr *attr);
extern void
bgp_encap_type_mpls_in_ip_tunnel_with_ipsec_transport_mode_to_tlv(
struct bgp_encap_type_mpls_in_ip_tunnel_with_ipsec_transport_mode *bet,
struct attr *attr);
extern void
bgp_encap_type_pbb_to_tlv(
struct bgp_encap_type_pbb *bet,
struct attr *attr);
extern void
bgp_encap_type_vxlan_to_tlv(
struct bgp_encap_type_vxlan *bet,
struct attr *attr);
extern void
bgp_encap_type_nvgre_to_tlv(
struct bgp_encap_type_nvgre *bet,
struct attr *attr);
extern void
bgp_encap_type_mpls_to_tlv(
struct bgp_encap_type_mpls *bet,
struct attr *attr);
extern void
bgp_encap_type_mpls_in_gre_to_tlv(
struct bgp_encap_type_mpls_in_gre *bet,
struct attr *attr);
extern void
bgp_encap_type_vxlan_gpe_to_tlv(
struct bgp_encap_type_vxlan_gpe *bet,
struct attr *attr);
extern void
bgp_encap_type_mpls_in_udp_to_tlv(
struct bgp_encap_type_mpls_in_udp *bet,
struct attr *attr);
bgp_encap_type_mpls_in_udp_to_tlv(struct bgp_encap_type_mpls_in_udp *bet,
struct attr *attr);
/***********************************************************************
* TUNNEL TYPE-SPECIFIC TLV DECODE
***********************************************************************/
extern int
tlv_to_bgp_encap_type_l2tpv3overip(
struct bgp_attr_encap_subtlv *stlv, /* subtlv chain */
struct bgp_encap_type_l2tpv3_over_ip *bet); /* caller-allocated */
extern int tlv_to_bgp_encap_type_l2tpv3overip(
struct bgp_attr_encap_subtlv *stlv, /* subtlv chain */
struct bgp_encap_type_l2tpv3_over_ip *bet); /* caller-allocated */
extern int tlv_to_bgp_encap_type_gre(
struct bgp_attr_encap_subtlv *stlv, /* subtlv chain */
struct bgp_encap_type_gre *bet); /* caller-allocated */
extern int tlv_to_bgp_encap_type_ip_in_ip(
struct bgp_attr_encap_subtlv *stlv, /* subtlv chain */
struct bgp_encap_type_ip_in_ip *bet); /* caller-allocated */
extern int tlv_to_bgp_encap_type_transmit_tunnel_endpoint(
struct bgp_attr_encap_subtlv *stlv,
struct bgp_encap_type_transmit_tunnel_endpoint *bet);
extern int tlv_to_bgp_encap_type_ipsec_in_tunnel_mode(
struct bgp_attr_encap_subtlv *stlv, /* subtlv chain */
struct bgp_encap_type_ipsec_in_tunnel_mode *bet); /* caller-allocated */
extern int tlv_to_bgp_encap_type_ip_in_ip_tunnel_with_ipsec_transport_mode(
struct bgp_attr_encap_subtlv *stlv,
struct bgp_encap_type_ip_in_ip_tunnel_with_ipsec_transport_mode *bet);
extern int tlv_to_bgp_encap_type_mpls_in_ip_tunnel_with_ipsec_transport_mode(
struct bgp_attr_encap_subtlv *stlv,
struct bgp_encap_type_mpls_in_ip_tunnel_with_ipsec_transport_mode *bet);
extern int tlv_to_bgp_encap_type_vxlan(struct bgp_attr_encap_subtlv *stlv,
struct bgp_encap_type_vxlan *bet);
extern int tlv_to_bgp_encap_type_nvgre(struct bgp_attr_encap_subtlv *stlv,
struct bgp_encap_type_nvgre *bet);
extern int tlv_to_bgp_encap_type_mpls(struct bgp_attr_encap_subtlv *stlv,
struct bgp_encap_type_mpls *bet);
extern int tlv_to_bgp_encap_type_mpls(struct bgp_attr_encap_subtlv *stlv,
struct bgp_encap_type_mpls *bet);
extern int
tlv_to_bgp_encap_type_gre(
struct bgp_attr_encap_subtlv *stlv, /* subtlv chain */
struct bgp_encap_type_gre *bet); /* caller-allocated */
tlv_to_bgp_encap_type_mpls_in_gre(struct bgp_attr_encap_subtlv *stlv,
struct bgp_encap_type_mpls_in_gre *bet);
extern int
tlv_to_bgp_encap_type_ip_in_ip(
struct bgp_attr_encap_subtlv *stlv, /* subtlv chain */
struct bgp_encap_type_ip_in_ip *bet); /* caller-allocated */
tlv_to_bgp_encap_type_vxlan_gpe(struct bgp_attr_encap_subtlv *stlv,
struct bgp_encap_type_vxlan_gpe *bet);
extern int
tlv_to_bgp_encap_type_transmit_tunnel_endpoint(
struct bgp_attr_encap_subtlv *stlv,
struct bgp_encap_type_transmit_tunnel_endpoint *bet);
tlv_to_bgp_encap_type_mpls_in_udp(struct bgp_attr_encap_subtlv *stlv,
struct bgp_encap_type_mpls_in_udp *bet);
extern int
tlv_to_bgp_encap_type_ipsec_in_tunnel_mode(
struct bgp_attr_encap_subtlv *stlv, /* subtlv chain */
struct bgp_encap_type_ipsec_in_tunnel_mode *bet); /* caller-allocated */
extern int
tlv_to_bgp_encap_type_ip_in_ip_tunnel_with_ipsec_transport_mode(
struct bgp_attr_encap_subtlv *stlv,
struct bgp_encap_type_ip_in_ip_tunnel_with_ipsec_transport_mode *bet);
extern int
tlv_to_bgp_encap_type_mpls_in_ip_tunnel_with_ipsec_transport_mode(
struct bgp_attr_encap_subtlv *stlv,
struct bgp_encap_type_mpls_in_ip_tunnel_with_ipsec_transport_mode *bet);
extern int
tlv_to_bgp_encap_type_vxlan(
struct bgp_attr_encap_subtlv *stlv,
struct bgp_encap_type_vxlan *bet);
extern int
tlv_to_bgp_encap_type_nvgre(
struct bgp_attr_encap_subtlv *stlv,
struct bgp_encap_type_nvgre *bet);
extern int
tlv_to_bgp_encap_type_mpls(
struct bgp_attr_encap_subtlv *stlv,
struct bgp_encap_type_mpls *bet);
extern int
tlv_to_bgp_encap_type_mpls(
struct bgp_attr_encap_subtlv *stlv,
struct bgp_encap_type_mpls *bet);
extern int
tlv_to_bgp_encap_type_mpls_in_gre(
struct bgp_attr_encap_subtlv *stlv,
struct bgp_encap_type_mpls_in_gre *bet);
extern int
tlv_to_bgp_encap_type_vxlan_gpe(
struct bgp_attr_encap_subtlv *stlv,
struct bgp_encap_type_vxlan_gpe *bet);
extern int
tlv_to_bgp_encap_type_mpls_in_udp(
struct bgp_attr_encap_subtlv *stlv,
struct bgp_encap_type_mpls_in_udp *bet);
extern int
tlv_to_bgp_encap_type_pbb(
struct bgp_attr_encap_subtlv *stlv, /* subtlv chain */
struct bgp_encap_type_pbb *bet); /* caller-allocated */
extern int tlv_to_bgp_encap_type_pbb(
struct bgp_attr_encap_subtlv *stlv, /* subtlv chain */
struct bgp_encap_type_pbb *bet); /* caller-allocated */
#endif /* _QUAGGA_BGP_ENCAP_TLV_H */

View File

@ -19,70 +19,75 @@
#ifndef _QUAGGA_BGP_ENCAP_TYPES_H
#define _QUAGGA_BGP_ENCAP_TYPES_H
/* from http://www.iana.org/assignments/bgp-parameters/bgp-parameters.xhtml#tunnel-types */
#include "bgpd/bgp_ecommunity.h"
/* from
* http://www.iana.org/assignments/bgp-parameters/bgp-parameters.xhtml#tunnel-types
*/
typedef enum {
BGP_ENCAP_TYPE_RESERVED=0,
BGP_ENCAP_TYPE_L2TPV3_OVER_IP=1,
BGP_ENCAP_TYPE_GRE=2,
BGP_ENCAP_TYPE_TRANSMIT_TUNNEL_ENDPOINT=3,
BGP_ENCAP_TYPE_IPSEC_IN_TUNNEL_MODE=4,
BGP_ENCAP_TYPE_IP_IN_IP_TUNNEL_WITH_IPSEC_TRANSPORT_MODE=5,
BGP_ENCAP_TYPE_MPLS_IN_IP_TUNNEL_WITH_IPSEC_TRANSPORT_MODE=6,
BGP_ENCAP_TYPE_IP_IN_IP=7,
BGP_ENCAP_TYPE_VXLAN=8,
BGP_ENCAP_TYPE_NVGRE=9,
BGP_ENCAP_TYPE_MPLS=10, /* NOTE: Encap SAFI&Attribute not used */
BGP_ENCAP_TYPE_MPLS_IN_GRE=11,
BGP_ENCAP_TYPE_VXLAN_GPE=12,
BGP_ENCAP_TYPE_MPLS_IN_UDP=13,
BGP_ENCAP_TYPE_PBB
BGP_ENCAP_TYPE_RESERVED = 0,
BGP_ENCAP_TYPE_L2TPV3_OVER_IP = 1,
BGP_ENCAP_TYPE_GRE = 2,
BGP_ENCAP_TYPE_TRANSMIT_TUNNEL_ENDPOINT = 3,
BGP_ENCAP_TYPE_IPSEC_IN_TUNNEL_MODE = 4,
BGP_ENCAP_TYPE_IP_IN_IP_TUNNEL_WITH_IPSEC_TRANSPORT_MODE = 5,
BGP_ENCAP_TYPE_MPLS_IN_IP_TUNNEL_WITH_IPSEC_TRANSPORT_MODE = 6,
BGP_ENCAP_TYPE_IP_IN_IP = 7,
BGP_ENCAP_TYPE_VXLAN = 8,
BGP_ENCAP_TYPE_NVGRE = 9,
BGP_ENCAP_TYPE_MPLS = 10, /* NOTE: Encap SAFI&Attribute not used */
BGP_ENCAP_TYPE_MPLS_IN_GRE = 11,
BGP_ENCAP_TYPE_VXLAN_GPE = 12,
BGP_ENCAP_TYPE_MPLS_IN_UDP = 13,
BGP_ENCAP_TYPE_PBB
} bgp_encap_types;
typedef enum {
BGP_ENCAP_SUBTLV_TYPE_ENCAPSULATION=1,
BGP_ENCAP_SUBTLV_TYPE_PROTO_TYPE=2,
BGP_ENCAP_SUBTLV_TYPE_IPSEC_TA=3,
BGP_ENCAP_SUBTLV_TYPE_COLOR=4,
BGP_ENCAP_SUBTLV_TYPE_REMOTE_ENDPOINT=6 /* speculative, IANA assignment TBD */
BGP_ENCAP_SUBTLV_TYPE_ENCAPSULATION = 1,
BGP_ENCAP_SUBTLV_TYPE_PROTO_TYPE = 2,
BGP_ENCAP_SUBTLV_TYPE_IPSEC_TA = 3,
BGP_ENCAP_SUBTLV_TYPE_COLOR = 4,
BGP_ENCAP_SUBTLV_TYPE_REMOTE_ENDPOINT =
6 /* speculative, IANA assignment TBD */
} bgp_encap_subtlv_types;
/*
* Tunnel Encapsulation Attribute subtlvs
*/
struct bgp_tea_subtlv_encap_l2tpv3_over_ip {
uint32_t sessionid;
uint8_t cookie_length;
uint8_t cookie[8];
uint32_t sessionid;
uint8_t cookie_length;
uint8_t cookie[8];
};
struct bgp_tea_subtlv_encap_gre_key {
uint32_t gre_key;
uint32_t gre_key;
};
struct bgp_tea_subtlv_encap_pbb {
uint32_t flag_isid:1;
uint32_t flag_vid:1;
uint32_t isid:24;
uint16_t vid:12;
uint8_t macaddr[6];
uint32_t flag_isid : 1;
uint32_t flag_vid : 1;
uint32_t isid : 24;
uint16_t vid : 12;
uint8_t macaddr[6];
};
struct bgp_tea_subtlv_proto_type {
uint16_t proto; /* ether-type */
uint16_t proto; /* ether-type */
};
struct bgp_tea_subtlv_color {
uint32_t color;
uint32_t color;
};
/* per draft-rosen-idr-tunnel-encaps */
struct bgp_tea_subtlv_remote_endpoint {
u_char family; /* IPv4 or IPv6 */
union {
struct in_addr v4;
struct in6_addr v6;
} ip_address;
as_t as4; /* always 4 bytes */
u_char family; /* IPv4 or IPv6 */
union {
struct in_addr v4;
struct in6_addr v6;
} ip_address;
as_t as4; /* always 4 bytes */
};
/*
@ -92,9 +97,9 @@ struct bgp_tea_subtlv_remote_endpoint {
#define BGP_ENCAP_SUBTLV_IPSEC_TA_SIZE 20
struct bgp_tea_subtlv_ipsec_ta {
uint16_t authenticator_type; /* only type 1 is supported so far */
uint8_t authenticator_length; /* octets in value field */
uint8_t value[BGP_ENCAP_SUBTLV_IPSEC_TA_SIZE];
uint16_t authenticator_type; /* only type 1 is supported so far */
uint8_t authenticator_length; /* octets in value field */
uint8_t value[BGP_ENCAP_SUBTLV_IPSEC_TA_SIZE];
};
/*
@ -115,102 +120,112 @@ struct bgp_tea_subtlv_ipsec_ta {
* Tunnel Type-specific APIs
*/
struct bgp_encap_type_reserved {
uint32_t valid_subtlvs;
struct bgp_tea_subtlv_remote_endpoint st_endpoint; /* optional */
uint32_t valid_subtlvs;
struct bgp_tea_subtlv_remote_endpoint st_endpoint; /* optional */
};
struct bgp_encap_type_l2tpv3_over_ip {
uint32_t valid_subtlvs;
struct bgp_tea_subtlv_encap_l2tpv3_over_ip st_encap;
struct bgp_tea_subtlv_proto_type st_proto; /* optional */
struct bgp_tea_subtlv_color st_color; /* optional */
struct bgp_tea_subtlv_remote_endpoint st_endpoint; /* optional */
uint32_t valid_subtlvs;
struct bgp_tea_subtlv_encap_l2tpv3_over_ip st_encap;
struct bgp_tea_subtlv_proto_type st_proto; /* optional */
struct bgp_tea_subtlv_color st_color; /* optional */
struct bgp_tea_subtlv_remote_endpoint st_endpoint; /* optional */
};
struct bgp_encap_type_gre {
uint32_t valid_subtlvs;
struct bgp_tea_subtlv_encap_gre_key st_encap; /* optional */
struct bgp_tea_subtlv_proto_type st_proto; /* optional */
struct bgp_tea_subtlv_color st_color; /* optional */
struct bgp_tea_subtlv_remote_endpoint st_endpoint; /* optional */
uint32_t valid_subtlvs;
struct bgp_tea_subtlv_encap_gre_key st_encap; /* optional */
struct bgp_tea_subtlv_proto_type st_proto; /* optional */
struct bgp_tea_subtlv_color st_color; /* optional */
struct bgp_tea_subtlv_remote_endpoint st_endpoint; /* optional */
};
struct bgp_encap_type_ip_in_ip {
uint32_t valid_subtlvs;
struct bgp_tea_subtlv_proto_type st_proto; /* optional */
struct bgp_tea_subtlv_color st_color; /* optional */
struct bgp_tea_subtlv_remote_endpoint st_endpoint; /* optional */
uint32_t valid_subtlvs;
struct bgp_tea_subtlv_proto_type st_proto; /* optional */
struct bgp_tea_subtlv_color st_color; /* optional */
struct bgp_tea_subtlv_remote_endpoint st_endpoint; /* optional */
};
struct bgp_encap_type_transmit_tunnel_endpoint {
uint32_t valid_subtlvs;
struct bgp_tea_subtlv_remote_endpoint st_endpoint; /* optional */
/* No subtlvs defined in spec? */
uint32_t valid_subtlvs;
struct bgp_tea_subtlv_remote_endpoint st_endpoint; /* optional */
/* No subtlvs defined in spec? */
};
struct bgp_encap_type_ipsec_in_tunnel_mode {
uint32_t valid_subtlvs;
struct bgp_tea_subtlv_ipsec_ta st_ipsec_ta; /* optional */
struct bgp_tea_subtlv_remote_endpoint st_endpoint; /* optional */
uint32_t valid_subtlvs;
struct bgp_tea_subtlv_ipsec_ta st_ipsec_ta; /* optional */
struct bgp_tea_subtlv_remote_endpoint st_endpoint; /* optional */
};
struct bgp_encap_type_ip_in_ip_tunnel_with_ipsec_transport_mode {
uint32_t valid_subtlvs;
struct bgp_tea_subtlv_ipsec_ta st_ipsec_ta; /* optional */
struct bgp_tea_subtlv_remote_endpoint st_endpoint; /* optional */
uint32_t valid_subtlvs;
struct bgp_tea_subtlv_ipsec_ta st_ipsec_ta; /* optional */
struct bgp_tea_subtlv_remote_endpoint st_endpoint; /* optional */
};
struct bgp_encap_type_mpls_in_ip_tunnel_with_ipsec_transport_mode {
uint32_t valid_subtlvs;
struct bgp_tea_subtlv_ipsec_ta st_ipsec_ta; /* optional */
struct bgp_tea_subtlv_remote_endpoint st_endpoint; /* optional */
uint32_t valid_subtlvs;
struct bgp_tea_subtlv_ipsec_ta st_ipsec_ta; /* optional */
struct bgp_tea_subtlv_remote_endpoint st_endpoint; /* optional */
};
#define VXLAN_ENCAP_MASK_VNID_VALID 0x80000000
#define VXLAN_ENCAP_MASK_MAC_VALID 0x40000000
struct bgp_encap_type_vxlan {
uint32_t valid_subtlvs;
struct bgp_tea_subtlv_remote_endpoint st_endpoint; /* optional */
/* draft-ietf-idr-tunnel-encaps-02 */
uint32_t vnid; /* does not include V and M bit */
uint8_t *mac_address; /* optional */
uint32_t valid_subtlvs;
struct bgp_tea_subtlv_remote_endpoint st_endpoint; /* optional */
/* draft-ietf-idr-tunnel-encaps-02 */
uint32_t vnid; /* does not include V and M bit */
uint8_t *mac_address; /* optional */
};
struct bgp_encap_type_nvgre {
uint32_t valid_subtlvs;
struct bgp_tea_subtlv_remote_endpoint st_endpoint; /* optional */
/* No subtlvs defined in spec? */
uint32_t valid_subtlvs;
struct bgp_tea_subtlv_remote_endpoint st_endpoint; /* optional */
/* No subtlvs defined in spec? */
};
struct bgp_encap_type_mpls {
uint32_t valid_subtlvs;
struct bgp_tea_subtlv_remote_endpoint st_endpoint; /* optional */
/* No subtlvs defined in spec? */
uint32_t valid_subtlvs;
struct bgp_tea_subtlv_remote_endpoint st_endpoint; /* optional */
/* No subtlvs defined in spec? */
};
struct bgp_encap_type_mpls_in_gre {
uint32_t valid_subtlvs;
struct bgp_tea_subtlv_remote_endpoint st_endpoint; /* optional */
/* No subtlvs defined in spec? */
uint32_t valid_subtlvs;
struct bgp_tea_subtlv_remote_endpoint st_endpoint; /* optional */
/* No subtlvs defined in spec? */
};
struct bgp_encap_type_vxlan_gpe {
uint32_t valid_subtlvs;
struct bgp_tea_subtlv_remote_endpoint st_endpoint; /* optional */
/* No subtlvs defined in spec? */
uint32_t valid_subtlvs;
struct bgp_tea_subtlv_remote_endpoint st_endpoint; /* optional */
/* No subtlvs defined in spec? */
};
struct bgp_encap_type_mpls_in_udp {
uint32_t valid_subtlvs;
struct bgp_tea_subtlv_remote_endpoint st_endpoint; /* optional */
/* No subtlvs defined in spec? */
uint32_t valid_subtlvs;
struct bgp_tea_subtlv_remote_endpoint st_endpoint; /* optional */
/* No subtlvs defined in spec? */
};
struct bgp_encap_type_pbb {
uint32_t valid_subtlvs;
struct bgp_tea_subtlv_remote_endpoint st_endpoint; /* optional */
struct bgp_tea_subtlv_encap_pbb st_encap;
uint32_t valid_subtlvs;
struct bgp_tea_subtlv_remote_endpoint st_endpoint; /* optional */
struct bgp_tea_subtlv_encap_pbb st_encap;
};
static inline void encode_encap_extcomm(bgp_encap_types tnl_type,
struct ecommunity_val *eval)
{
memset(eval, 0, sizeof(*eval));
eval->val[0] = ECOMMUNITY_ENCODE_OPAQUE;
eval->val[1] = ECOMMUNITY_OPAQUE_SUBTYPE_ENCAP;
eval->val[6] = ((tnl_type) >> 8) & 0xff;
eval->val[7] = (tnl_type)&0xff;
}
#endif /* _QUAGGA_BGP_ENCAP_TYPES_H */

File diff suppressed because it is too large Load Diff

View File

@ -21,20 +21,33 @@
#ifndef _QUAGGA_BGP_EVPN_H
#define _QUAGGA_BGP_EVPN_H
#include "vxlan.h"
#define EVPN_ROUTE_STRLEN 200 /* Must be >> MAC + IPv6 strings. */
extern void bgp_evpn_handle_router_id_update(struct bgp *bgp, int withdraw);
extern char *bgp_evpn_label2str(mpls_label_t *label, char *buf, int len);
extern char *bgp_evpn_route2str(struct prefix_evpn *p, char *buf, int len);
extern void bgp_evpn_encode_prefix(struct stream *s, struct prefix *p,
struct prefix_rd *prd, mpls_label_t *label,
struct attr *attr, int addpath_encode,
u_int32_t addpath_tx_id);
extern int bgp_nlri_parse_evpn(struct peer *peer, struct attr *attr,
struct bgp_nlri *packet, int withdraw);
extern int bgp_evpn_import_route(struct bgp *bgp, afi_t afi, safi_t safi,
struct prefix *p, struct bgp_info *ri);
extern int bgp_evpn_unimport_route(struct bgp *bgp, afi_t afi, safi_t safi,
struct prefix *p, struct bgp_info *ri);
extern int bgp_evpn_local_macip_del(struct bgp *bgp, vni_t vni,
struct ethaddr *mac, struct ipaddr *ip);
extern int bgp_evpn_local_macip_add(struct bgp *bgp, vni_t vni,
struct ethaddr *mac, struct ipaddr *ip,
u_char sticky);
extern int bgp_evpn_local_vni_del(struct bgp *bgp, vni_t vni);
extern int bgp_evpn_local_vni_add(struct bgp *bgp, vni_t vni,
struct in_addr originator_ip);
extern void bgp_evpn_cleanup_on_disable(struct bgp *bgp);
extern void bgp_evpn_cleanup(struct bgp *bgp);
extern void bgp_evpn_init(struct bgp *bgp);
extern void
bgp_packet_mpattr_route_type_5(struct stream *s,
struct prefix *p, struct prefix_rd *prd,
u_char * label, struct attr *attr);
/* EVPN route types as per RFC7432 and
* as per draft-ietf-bess-evpn-prefix-advertisement-02
*/
#define EVPN_ETHERNET_AUTO_DISCOVERY 1
#define EVPN_MACIP_ADVERTISEMENT 2
#define EVPN_INCLUSIVE_MULTICAST_ETHERNET_TAG 3
#define EVPN_ETHERNET_SEGMENT 4
#define EVPN_IP_PREFIX 5
#endif /* _QUAGGA_BGP_EVPN_H */
#endif /* _QUAGGA_BGP_EVPN_H */

213
bgpd/bgp_evpn_private.h Normal file
View File

@ -0,0 +1,213 @@
/* BGP EVPN internal definitions
* Copyright (C) 2017 Cumulus Networks, Inc.
*
* This file is part of FRR.
*
* FRR is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2, or (at your option) any
* later version.
*
* FRR is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with FRR; see the file COPYING. If not, write to the Free
* Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#ifndef _BGP_EVPN_PRIVATE_H
#define _BGP_EVPN_PRIVATE_H
#include "vxlan.h"
#include "zebra.h"
#include "bgpd/bgpd.h"
#include "bgpd/bgp_ecommunity.h"
/* EVPN prefix lengths. */
#define EVPN_TYPE_2_ROUTE_PREFIXLEN 224
#define EVPN_TYPE_3_ROUTE_PREFIXLEN 224
/* EVPN route types. */
typedef enum {
BGP_EVPN_AD_ROUTE = 1, /* Ethernet Auto-Discovery (A-D) route */
BGP_EVPN_MAC_IP_ROUTE, /* MAC/IP Advertisement route */
BGP_EVPN_IMET_ROUTE, /* Inclusive Multicast Ethernet Tag route */
BGP_EVPN_ES_ROUTE, /* Ethernet Segment route */
BGP_EVPN_IP_PREFIX_ROUTE, /* IP Prefix route */
} bgp_evpn_route_type;
/*
* Hash table of EVIs. Right now, the only type of EVI supported is with
* VxLAN encapsulation, hence each EVI corresponds to a L2 VNI.
* The VNIs are not "created" through BGP but through some other interface
* on the system. This table stores VNIs that BGP comes to know as present
* on the system (through interaction with zebra) as well as pre-configured
* VNIs (which need to be defined in the system to become "live").
*/
struct bgpevpn {
vni_t vni;
u_int32_t flags;
#define VNI_FLAG_CFGD 0x1 /* VNI is user configured */
#define VNI_FLAG_LIVE 0x2 /* VNI is "live" */
#define VNI_FLAG_RD_CFGD 0x4 /* RD is user configured. */
#define VNI_FLAG_IMPRT_CFGD 0x8 /* Import RT is user configured */
#define VNI_FLAG_EXPRT_CFGD 0x10 /* Export RT is user configured */
/* Id for deriving the RD automatically for this VNI */
u_int16_t rd_id;
/* RD for this VNI. */
struct prefix_rd prd;
/* Route type 3 field */
struct in_addr originator_ip;
/* Import and Export RTs. */
struct list *import_rtl;
struct list *export_rtl;
/* Route table for EVPN routes for this VNI. */
struct bgp_table *route_table;
QOBJ_FIELDS
};
DECLARE_QOBJ_TYPE(bgpevpn)
/* Mapping of Import RT to VNIs.
* The Import RTs of all VNIs are maintained in a hash table with each
* RT linking to all VNIs that will import routes matching this RT.
*/
struct irt_node {
/* RT */
struct ecommunity_val rt;
/* List of VNIs importing routes matching this RT. */
struct list *vnis;
};
#define RT_TYPE_IMPORT 1
#define RT_TYPE_EXPORT 2
#define RT_TYPE_BOTH 3
static inline int is_vni_configured(struct bgpevpn *vpn)
{
return (CHECK_FLAG(vpn->flags, VNI_FLAG_CFGD));
}
static inline int is_vni_live(struct bgpevpn *vpn)
{
return (CHECK_FLAG(vpn->flags, VNI_FLAG_LIVE));
}
static inline int is_rd_configured(struct bgpevpn *vpn)
{
return (CHECK_FLAG(vpn->flags, VNI_FLAG_RD_CFGD));
}
static inline int bgp_evpn_rd_matches_existing(struct bgpevpn *vpn,
struct prefix_rd *prd)
{
return (memcmp(&vpn->prd.val, prd->val, ECOMMUNITY_SIZE) == 0);
}
static inline int is_import_rt_configured(struct bgpevpn *vpn)
{
return (CHECK_FLAG(vpn->flags, VNI_FLAG_IMPRT_CFGD));
}
static inline int is_export_rt_configured(struct bgpevpn *vpn)
{
return (CHECK_FLAG(vpn->flags, VNI_FLAG_EXPRT_CFGD));
}
static inline int is_vni_param_configured(struct bgpevpn *vpn)
{
return (is_rd_configured(vpn) || is_import_rt_configured(vpn)
|| is_export_rt_configured(vpn));
}
static inline void vni2label(vni_t vni, mpls_label_t *label)
{
u_char *tag = (u_char *)label;
tag[0] = (vni >> 16) & 0xFF;
tag[1] = (vni >> 8) & 0xFF;
tag[2] = vni & 0xFF;
}
static inline vni_t label2vni(mpls_label_t *label)
{
u_char *tag = (u_char *)label;
vni_t vni;
vni = ((u_int32_t)*tag++ << 16);
vni |= (u_int32_t)*tag++ << 8;
vni |= (u_int32_t)(*tag & 0xFF);
return vni;
}
static inline void encode_mac_mobility_extcomm(int static_mac, u_int32_t seq,
struct ecommunity_val *eval)
{
memset(eval, 0, sizeof(*eval));
eval->val[0] = ECOMMUNITY_ENCODE_EVPN;
eval->val[1] = ECOMMUNITY_EVPN_SUBTYPE_MACMOBILITY;
if (static_mac)
eval->val[2] = ECOMMUNITY_EVPN_SUBTYPE_MACMOBILITY_FLAG_STICKY;
eval->val[4] = (seq >> 24) & 0xff;
eval->val[5] = (seq >> 16) & 0xff;
eval->val[6] = (seq >> 8) & 0xff;
eval->val[7] = seq & 0xff;
}
static inline void build_evpn_type2_prefix(struct prefix_evpn *p,
struct ethaddr *mac,
struct ipaddr *ip)
{
memset(p, 0, sizeof(struct prefix_evpn));
p->family = AF_ETHERNET;
p->prefixlen = EVPN_TYPE_2_ROUTE_PREFIXLEN;
p->prefix.route_type = BGP_EVPN_MAC_IP_ROUTE;
memcpy(&p->prefix.mac.octet, mac->octet, ETHER_ADDR_LEN);
p->prefix.ip.ipa_type = IPADDR_NONE;
if (ip)
memcpy(&p->prefix.ip, ip, sizeof(*ip));
}
static inline void build_evpn_type3_prefix(struct prefix_evpn *p,
struct in_addr originator_ip)
{
memset(p, 0, sizeof(struct prefix_evpn));
p->family = AF_ETHERNET;
p->prefixlen = EVPN_TYPE_3_ROUTE_PREFIXLEN;
p->prefix.route_type = BGP_EVPN_IMET_ROUTE;
p->prefix.ip.ipa_type = IPADDR_V4;
p->prefix.ip.ipaddr_v4 = originator_ip;
}
extern int bgp_evpn_handle_export_rt_change(struct bgp *bgp,
struct bgpevpn *vpn);
extern void bgp_evpn_handle_rd_change(struct bgp *bgp, struct bgpevpn *vpn,
int withdraw);
extern int bgp_evpn_install_routes(struct bgp *bgp, struct bgpevpn *vpn);
extern int bgp_evpn_uninstall_routes(struct bgp *bgp, struct bgpevpn *vpn);
extern void bgp_evpn_map_vni_to_its_rts(struct bgp *bgp, struct bgpevpn *vpn);
extern void bgp_evpn_unmap_vni_from_its_rts(struct bgp *bgp,
struct bgpevpn *vpn);
extern void bgp_evpn_derive_auto_rt_import(struct bgp *bgp,
struct bgpevpn *vpn);
extern void bgp_evpn_derive_auto_rt_export(struct bgp *bgp,
struct bgpevpn *vpn);
extern void bgp_evpn_derive_auto_rd(struct bgp *bgp, struct bgpevpn *vpn);
extern struct bgpevpn *bgp_evpn_lookup_vni(struct bgp *bgp, vni_t vni);
extern struct bgpevpn *bgp_evpn_new(struct bgp *bgp, vni_t vni,
struct in_addr originator_ip);
extern void bgp_evpn_free(struct bgp *bgp, struct bgpevpn *vpn);
#endif /* _BGP_EVPN_PRIVATE_H */

File diff suppressed because it is too large Load Diff

View File

@ -21,9 +21,11 @@
#ifndef _FRR_BGP_EVPN_VTY_H
#define _FRR_BGP_EVPN_VTY_H
extern void bgp_config_write_evpn_info(struct vty *vty, struct bgp *bgp,
afi_t afi, safi_t safi, int *write);
extern void bgp_ethernetvpn_init(void);
#define L2VPN_HELP_STR "Layer 2 Virtual Private Network\n"
#define EVPN_HELP_STR "Ethernet Virtual Private Network\n"
#endif /* _QUAGGA_BGP_EVPN_VTY_H */
#endif /* _QUAGGA_BGP_EVPN_VTY_H */

File diff suppressed because it is too large Load Diff

View File

@ -21,19 +21,15 @@
#ifndef _QUAGGA_BGP_FILTER_H
#define _QUAGGA_BGP_FILTER_H
enum as_filter_type
{
AS_FILTER_DENY,
AS_FILTER_PERMIT
};
enum as_filter_type { AS_FILTER_DENY, AS_FILTER_PERMIT };
extern void bgp_filter_init (void);
extern void bgp_filter_reset (void);
extern void bgp_filter_init(void);
extern void bgp_filter_reset(void);
extern enum as_filter_type as_list_apply (struct as_list *, void *);
extern enum as_filter_type as_list_apply(struct as_list *, void *);
extern struct as_list *as_list_lookup (const char *);
extern void as_list_add_hook (void (*func) (char *));
extern void as_list_delete_hook (void (*func) (const char *));
extern struct as_list *as_list_lookup(const char *);
extern void as_list_add_hook(void (*func)(char *));
extern void as_list_delete_hook(void (*func)(const char *));
#endif /* _QUAGGA_BGP_FILTER_H */

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,4 @@
/* BGP-4 Finite State Machine
/* BGP-4 Finite State Machine
* From RFC1771 [A Border Gateway Protocol 4 (BGP-4)]
* Copyright (C) 1998 Kunihiro Ishiguro
*
@ -23,82 +23,83 @@
#define _QUAGGA_BGP_FSM_H
/* Macro for BGP read, write and timer thread. */
#define BGP_READ_ON(T,F,V) \
do { \
if ((peer->status != Deleted)) \
thread_add_read (bm->master,(F),peer,(V),&(T)); \
} while (0)
#define BGP_READ_ON(T, F, V) \
do { \
if ((peer->status != Deleted)) \
thread_add_read(bm->master, (F), peer, (V), &(T)); \
} while (0)
#define BGP_READ_OFF(T) \
do { \
if (T) \
THREAD_READ_OFF(T); \
} while (0)
#define BGP_READ_OFF(T) \
do { \
if (T) \
THREAD_READ_OFF(T); \
} while (0)
#define BGP_WRITE_ON(T,F,V) \
do { \
if ((peer)->status != Deleted) \
thread_add_write (bm->master,(F),(peer),(V),&(T)); \
} while (0)
#define BGP_WRITE_ON(T, F, V) \
do { \
if ((peer)->status != Deleted) \
thread_add_write(bm->master, (F), (peer), (V), &(T)); \
} while (0)
#define BGP_PEER_WRITE_ON(T,F,V, peer) \
do { \
if ((peer)->status != Deleted) \
thread_add_write (bm->master,(F),(peer),(V),&(T)); \
} while (0)
#define BGP_PEER_WRITE_ON(T, F, V, peer) \
do { \
if ((peer)->status != Deleted) \
thread_add_write(bm->master, (F), (peer), (V), &(T)); \
} while (0)
#define BGP_WRITE_OFF(T) \
do { \
if (T) \
THREAD_WRITE_OFF(T); \
} while (0)
#define BGP_WRITE_OFF(T) \
do { \
if (T) \
THREAD_WRITE_OFF(T); \
} while (0)
#define BGP_TIMER_ON(T,F,V) \
do { \
if ((peer->status != Deleted)) \
thread_add_timer (bm->master,(F),peer,(V),&(T)); \
} while (0)
#define BGP_TIMER_ON(T, F, V) \
do { \
if ((peer->status != Deleted)) \
thread_add_timer(bm->master, (F), peer, (V), &(T)); \
} while (0)
#define BGP_TIMER_OFF(T) \
do { \
if (T) \
THREAD_TIMER_OFF(T); \
} while (0)
#define BGP_TIMER_OFF(T) \
do { \
if (T) \
THREAD_TIMER_OFF(T); \
} while (0)
#define BGP_EVENT_ADD(P,E) \
do { \
if ((P)->status != Deleted) \
thread_add_event (bm->master, bgp_event, (P), (E), NULL); \
} while (0)
#define BGP_EVENT_ADD(P, E) \
do { \
if ((P)->status != Deleted) \
thread_add_event(bm->master, bgp_event, (P), (E), \
NULL); \
} while (0)
#define BGP_EVENT_FLUSH(P) \
do { \
assert (peer); \
thread_cancel_event (bm->master, (P)); \
} while (0)
#define BGP_EVENT_FLUSH(P) \
do { \
assert(peer); \
thread_cancel_event(bm->master, (P)); \
} while (0)
#define BGP_MSEC_JITTER 10
/* Prototypes. */
extern void bgp_fsm_nht_update(struct peer *, int valid);
extern int bgp_event (struct thread *);
extern int bgp_event_update (struct peer *, int event);
extern int bgp_stop (struct peer *peer);
extern void bgp_timer_set (struct peer *);
extern int bgp_routeadv_timer (struct thread *);
extern void bgp_fsm_change_status (struct peer *peer, int status);
extern int bgp_event(struct thread *);
extern int bgp_event_update(struct peer *, int event);
extern int bgp_stop(struct peer *peer);
extern void bgp_timer_set(struct peer *);
extern int bgp_routeadv_timer(struct thread *);
extern void bgp_fsm_change_status(struct peer *peer, int status);
extern const char *peer_down_str[];
extern void bgp_update_delay_end (struct bgp *);
extern void bgp_maxmed_update (struct bgp *);
extern int bgp_maxmed_onstartup_configured (struct bgp *);
extern int bgp_maxmed_onstartup_active (struct bgp *);
extern void bgp_update_delay_end(struct bgp *);
extern void bgp_maxmed_update(struct bgp *);
extern int bgp_maxmed_onstartup_configured(struct bgp *);
extern int bgp_maxmed_onstartup_active(struct bgp *);
/**
* Start the route advertisement timer (that honors MRAI) for all the
* peers. Typically called at the end of initial convergence, coming
* out of read-only mode.
*/
extern void bgp_start_routeadv (struct bgp *);
extern void bgp_start_routeadv(struct bgp *);
/**
* See if the route advertisement timer needs to be adjusted for a
@ -107,10 +108,10 @@ extern void bgp_start_routeadv (struct bgp *);
* timer to expire to send the new set of prefixes. It should fire
* instantly and updates should go out sooner.
*/
extern void bgp_adjust_routeadv (struct peer *);
extern void bgp_adjust_routeadv(struct peer *);
#include "hook.h"
DECLARE_HOOK(peer_backward_transition, (struct peer *peer), (peer))
DECLARE_HOOK(peer_established, (struct peer *peer), (peer))
DECLARE_HOOK(peer_backward_transition, (struct peer * peer), (peer))
DECLARE_HOOK(peer_established, (struct peer * peer), (peer))
#endif /* _QUAGGA_BGP_FSM_H */

View File

@ -41,301 +41,301 @@
extern struct zclient *zclient;
int
bgp_parse_fec_update (void)
int bgp_parse_fec_update(void)
{
struct stream *s;
struct bgp_node *rn;
struct bgp *bgp;
struct bgp_table *table;
struct prefix p;
u_int32_t label;
afi_t afi;
safi_t safi;
struct stream *s;
struct bgp_node *rn;
struct bgp *bgp;
struct bgp_table *table;
struct prefix p;
u_int32_t label;
afi_t afi;
safi_t safi;
s = zclient->ibuf;
s = zclient->ibuf;
memset(&p, 0, sizeof(struct prefix));
p.family = stream_getw(s);
p.prefixlen = stream_getc(s);
stream_get(&p.u.prefix, s, PSIZE(p.prefixlen));
label = stream_getl(s);
memset(&p, 0, sizeof(struct prefix));
p.family = stream_getw(s);
p.prefixlen = stream_getc(s);
stream_get(&p.u.prefix, s, PSIZE(p.prefixlen));
label = stream_getl(s);
/* hack for the bgp instance & SAFI = have to send/receive it */
afi = family2afi(p.family);
safi = SAFI_LABELED_UNICAST;
bgp = bgp_get_default();
if (!bgp)
{
zlog_debug("no default bgp instance");
return -1;
}
/* hack for the bgp instance & SAFI = have to send/receive it */
afi = family2afi(p.family);
safi = SAFI_UNICAST;
bgp = bgp_get_default();
if (!bgp) {
zlog_debug("no default bgp instance");
return -1;
}
table = bgp->rib[afi][safi];
if (!table)
{
zlog_debug("no %u labeled-unicast table", p.family);
return -1;
}
rn = bgp_node_lookup(table, &p);
if (!rn)
{
zlog_debug("no node for the prefix");
return -1;
}
table = bgp->rib[afi][safi];
if (!table) {
zlog_debug("no %u unicast table", p.family);
return -1;
}
rn = bgp_node_lookup(table, &p);
if (!rn) {
zlog_debug("no node for the prefix");
return -1;
}
/* treat it as implicit withdraw - the label is invalid */
if (label == MPLS_INVALID_LABEL)
bgp_unset_valid_label(rn->local_label);
else
{
label_ntop(label, 1, rn->local_label);
bgp_set_valid_label(rn->local_label);
}
SET_FLAG(rn->flags, BGP_NODE_LABEL_CHANGED);
bgp_unlock_node (rn);
bgp_process (bgp, rn, afi, safi);
return 1;
/* treat it as implicit withdraw - the label is invalid */
if (label == MPLS_INVALID_LABEL)
bgp_unset_valid_label(&rn->local_label);
else {
label_ntop(label, 1, &rn->local_label);
bgp_set_valid_label(&rn->local_label);
}
SET_FLAG(rn->flags, BGP_NODE_LABEL_CHANGED);
bgp_unlock_node(rn);
bgp_process(bgp, rn, afi, safi);
return 1;
}
u_char *
bgp_adv_label (struct bgp_node *rn, struct bgp_info *ri, struct peer *to,
afi_t afi, safi_t safi)
mpls_label_t bgp_adv_label(struct bgp_node *rn, struct bgp_info *ri,
struct peer *to, afi_t afi, safi_t safi)
{
struct peer *from;
u_char *remote_label;
int reflect;
struct peer *from;
mpls_label_t remote_label;
int reflect;
if (!rn || !ri || !to)
return NULL;
if (!rn || !ri || !to)
return MPLS_INVALID_LABEL;
remote_label = ri->extra ? ri->extra->tag : NULL;
from = ri->peer;
reflect = ((from->sort == BGP_PEER_IBGP) && (to->sort == BGP_PEER_IBGP));
remote_label = ri->extra ? ri->extra->label : MPLS_INVALID_LABEL;
from = ri->peer;
reflect =
((from->sort == BGP_PEER_IBGP) && (to->sort == BGP_PEER_IBGP));
if (reflect && !CHECK_FLAG(to->af_flags[afi][safi],
PEER_FLAG_FORCE_NEXTHOP_SELF))
return remote_label;
if (reflect
&& !CHECK_FLAG(to->af_flags[afi][safi],
PEER_FLAG_FORCE_NEXTHOP_SELF))
return remote_label;
if (CHECK_FLAG(to->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED))
return remote_label;
if (CHECK_FLAG(to->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED))
return remote_label;
return rn->local_label;
return rn->local_label;
}
void
bgp_reg_dereg_for_label (struct bgp_node *rn, struct bgp_info *ri,
int reg)
void bgp_reg_dereg_for_label(struct bgp_node *rn, struct bgp_info *ri, int reg)
{
struct stream *s;
struct prefix *p;
int command;
u_int16_t flags = 0;
size_t flags_pos = 0;
struct stream *s;
struct prefix *p;
int command;
u_int16_t flags = 0;
size_t flags_pos = 0;
/* Check socket. */
if (!zclient || zclient->sock < 0)
return;
/* Check socket. */
if (!zclient || zclient->sock < 0)
return;
p = &(rn->p);
s = zclient->obuf;
stream_reset (s);
command = (reg) ? ZEBRA_FEC_REGISTER : ZEBRA_FEC_UNREGISTER;
zclient_create_header (s, command, VRF_DEFAULT);
flags_pos = stream_get_endp (s); /* save position of 'flags' */
stream_putw(s, flags); /* initial flags */
stream_putw(s, PREFIX_FAMILY(p));
stream_put_prefix(s, p);
if (reg)
{
assert (ri);
if (ri->attr->flag & ATTR_FLAG_BIT (BGP_ATTR_PREFIX_SID))
{
assert (ri->attr->extra);
p = &(rn->p);
s = zclient->obuf;
stream_reset(s);
command = (reg) ? ZEBRA_FEC_REGISTER : ZEBRA_FEC_UNREGISTER;
zclient_create_header(s, command, VRF_DEFAULT);
flags_pos = stream_get_endp(s); /* save position of 'flags' */
stream_putw(s, flags); /* initial flags */
stream_putw(s, PREFIX_FAMILY(p));
stream_put_prefix(s, p);
if (reg) {
assert(ri);
if (ri->attr->flag & ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID)) {
if (ri->attr->label_index != BGP_INVALID_LABEL_INDEX) {
flags |= ZEBRA_FEC_REGISTER_LABEL_INDEX;
stream_putl(s, ri->attr->label_index);
}
}
SET_FLAG(rn->flags, BGP_NODE_REGISTERED_FOR_LABEL);
} else
UNSET_FLAG(rn->flags, BGP_NODE_REGISTERED_FOR_LABEL);
if (ri->attr->extra->label_index != BGP_INVALID_LABEL_INDEX)
{
flags |= ZEBRA_FEC_REGISTER_LABEL_INDEX;
stream_putl (s, ri->attr->extra->label_index);
}
}
SET_FLAG (rn->flags, BGP_NODE_REGISTERED_FOR_LABEL);
}
else
UNSET_FLAG (rn->flags, BGP_NODE_REGISTERED_FOR_LABEL);
/* Set length and flags */
stream_putw_at(s, 0, stream_get_endp(s));
stream_putw_at(s, flags_pos, flags);
/* Set length and flags */
stream_putw_at (s, 0, stream_get_endp (s));
stream_putw_at (s, flags_pos, flags);
zclient_send_message(zclient);
zclient_send_message(zclient);
}
static int
bgp_nlri_get_labels (struct peer *peer, u_char *pnt, u_char plen,
u_char label[])
static int bgp_nlri_get_labels(struct peer *peer, u_char *pnt, u_char plen,
mpls_label_t *label)
{
u_char *data = pnt;
u_char *lim = pnt + plen;
u_char llen = 0;
u_char *data = pnt;
u_char *lim = pnt + plen;
u_char llen = 0;
u_char label_depth = 0;
for (; data < lim; data += BGP_LABEL_BYTES)
{
memcpy(label, data, BGP_LABEL_BYTES);
llen += 3;
if (bgp_is_withdraw_label(label) || label_bos(label))
break;
}
if (!(bgp_is_withdraw_label(label) || label_bos(label)))
zlog_warn("%s: [Update:RCVD] invalid label - no bottom of stack",
peer->host);
for (; data < lim; data += BGP_LABEL_BYTES) {
memcpy(label, data, BGP_LABEL_BYTES);
llen += BGP_LABEL_BYTES;
return llen;
bgp_set_valid_label(label);
label_depth += 1;
if (bgp_is_withdraw_label(label) || label_bos(label))
break;
}
/* If we RX multiple labels we will end up keeping only the last
* one. We do not yet support a label stack greater than 1. */
if (label_depth > 1)
zlog_warn("%s rcvd UPDATE with label stack %d deep", peer->host,
label_depth);
if (!(bgp_is_withdraw_label(label) || label_bos(label)))
zlog_warn(
"%s rcvd UPDATE with invalid label stack - no bottom of stack",
peer->host);
return llen;
}
int
bgp_nlri_parse_label (struct peer *peer, struct attr *attr,
struct bgp_nlri *packet)
int bgp_nlri_parse_label(struct peer *peer, struct attr *attr,
struct bgp_nlri *packet)
{
u_char *pnt;
u_char *lim;
struct prefix p;
int psize = 0;
int prefixlen;
afi_t afi;
safi_t safi;
int addpath_encoded;
u_int32_t addpath_id;
u_char label[3];
u_char llen;
u_char *pnt;
u_char *lim;
struct prefix p;
int psize = 0;
int prefixlen;
afi_t afi;
safi_t safi;
int addpath_encoded;
u_int32_t addpath_id;
mpls_label_t label = MPLS_INVALID_LABEL;
u_char llen;
/* Check peer status. */
if (peer->status != Established)
return 0;
/* Check peer status. */
if (peer->status != Established)
return 0;
pnt = packet->nlri;
lim = pnt + packet->length;
afi = packet->afi;
safi = packet->safi;
addpath_id = 0;
pnt = packet->nlri;
lim = pnt + packet->length;
afi = packet->afi;
safi = packet->safi;
addpath_id = 0;
addpath_encoded = (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_RX_ADV) &&
CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_TX_RCV));
addpath_encoded =
(CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_RX_ADV)
&& CHECK_FLAG(peer->af_cap[afi][safi],
PEER_CAP_ADDPATH_AF_TX_RCV));
for (; pnt < lim; pnt += psize)
{
/* Clear prefix structure. */
memset (&p, 0, sizeof (struct prefix));
llen = 0;
for (; pnt < lim; pnt += psize) {
/* Clear prefix structure. */
memset(&p, 0, sizeof(struct prefix));
llen = 0;
if (addpath_encoded)
{
if (addpath_encoded) {
/* When packet overflow occurs return immediately. */
if (pnt + BGP_ADDPATH_ID_LEN > lim)
return -1;
/* When packet overflow occurs return immediately. */
if (pnt + BGP_ADDPATH_ID_LEN > lim)
return -1;
addpath_id = ntohl(*((uint32_t*) pnt));
pnt += BGP_ADDPATH_ID_LEN;
}
addpath_id = ntohl(*((uint32_t *)pnt));
pnt += BGP_ADDPATH_ID_LEN;
}
/* Fetch prefix length. */
prefixlen = *pnt++;
p.family = afi2family (packet->afi);
psize = PSIZE (prefixlen);
/* Fetch prefix length. */
prefixlen = *pnt++;
p.family = afi2family(packet->afi);
psize = PSIZE(prefixlen);
/* sanity check against packet data */
if ((pnt + psize) > lim)
{
zlog_err ("%s [Error] Update packet error / L-U (prefix length %d exceeds packet size %u)",
peer->host,
prefixlen, (uint)(lim-pnt));
return -1;
}
/* sanity check against packet data */
if ((pnt + psize) > lim) {
zlog_err(
"%s [Error] Update packet error / L-U (prefix length %d exceeds packet size %u)",
peer->host, prefixlen, (uint)(lim - pnt));
return -1;
}
/* Fill in the labels */
llen = bgp_nlri_get_labels(peer, pnt, psize, label);
// zlog_debug("rcvd label [%x/%x/%x], llen=%d\n", label[0], label[1], label[2], llen);
p.prefixlen = prefixlen - BSIZE(llen);
/* Fill in the labels */
llen = bgp_nlri_get_labels(peer, pnt, psize, &label);
p.prefixlen = prefixlen - BSIZE(llen);
/* There needs to be at least one label */
if (prefixlen < 24)
{
zlog_err ("%s [Error] Update packet error"
" (wrong label length %d)",
peer->host, prefixlen);
bgp_notify_send (peer, BGP_NOTIFY_UPDATE_ERR,
BGP_NOTIFY_UPDATE_INVAL_NETWORK);
return -1;
}
/* There needs to be at least one label */
if (prefixlen < 24) {
zlog_err(
"%s [Error] Update packet error"
" (wrong label length %d)",
peer->host, prefixlen);
bgp_notify_send(peer, BGP_NOTIFY_UPDATE_ERR,
BGP_NOTIFY_UPDATE_INVAL_NETWORK);
return -1;
}
if ((afi == AFI_IP && p.prefixlen > 32)
|| (afi == AFI_IP6 && p.prefixlen > 128))
return -1;
if ((afi == AFI_IP && p.prefixlen > 32)
|| (afi == AFI_IP6 && p.prefixlen > 128))
return -1;
/* Fetch prefix from NLRI packet */
memcpy (&p.u.prefix, pnt + llen, psize - llen);
/* Fetch prefix from NLRI packet */
memcpy(&p.u.prefix, pnt + llen, psize - llen);
/* Check address. */
if (afi == AFI_IP && safi == SAFI_LABELED_UNICAST)
{
if (IN_CLASSD (ntohl (p.u.prefix4.s_addr)))
{
/* From RFC4271 Section 6.3:
*
* If a prefix in the NLRI field is semantically incorrect
* (e.g., an unexpected multicast IP address), an error SHOULD
* be logged locally, and the prefix SHOULD be ignored.
*/
zlog_err ("%s: IPv4 labeled-unicast NLRI is multicast address %s, ignoring",
peer->host, inet_ntoa (p.u.prefix4));
continue;
}
}
/* Check address. */
if (afi == AFI_IP && safi == SAFI_LABELED_UNICAST) {
if (IN_CLASSD(ntohl(p.u.prefix4.s_addr))) {
/* From RFC4271 Section 6.3:
*
* If a prefix in the NLRI field is semantically
* incorrect
* (e.g., an unexpected multicast IP address),
* an error SHOULD
* be logged locally, and the prefix SHOULD be
* ignored.
*/
zlog_err(
"%s: IPv4 labeled-unicast NLRI is multicast address %s, ignoring",
peer->host, inet_ntoa(p.u.prefix4));
continue;
}
}
/* Check address. */
if (afi == AFI_IP6 && safi == SAFI_LABELED_UNICAST)
{
if (IN6_IS_ADDR_LINKLOCAL (&p.u.prefix6))
{
char buf[BUFSIZ];
/* Check address. */
if (afi == AFI_IP6 && safi == SAFI_LABELED_UNICAST) {
if (IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6)) {
char buf[BUFSIZ];
zlog_err ("%s: IPv6 labeled-unicast NLRI is link-local address %s, ignoring",
peer->host, inet_ntop (AF_INET6, &p.u.prefix6, buf, BUFSIZ));
zlog_err(
"%s: IPv6 labeled-unicast NLRI is link-local address %s, ignoring",
peer->host,
inet_ntop(AF_INET6, &p.u.prefix6, buf,
BUFSIZ));
continue;
}
continue;
}
if (IN6_IS_ADDR_MULTICAST (&p.u.prefix6))
{
char buf[BUFSIZ];
if (IN6_IS_ADDR_MULTICAST(&p.u.prefix6)) {
char buf[BUFSIZ];
zlog_err ("%s: IPv6 unicast NLRI is multicast address %s, ignoring",
peer->host, inet_ntop (AF_INET6, &p.u.prefix6, buf, BUFSIZ));
zlog_err(
"%s: IPv6 unicast NLRI is multicast address %s, ignoring",
peer->host,
inet_ntop(AF_INET6, &p.u.prefix6, buf,
BUFSIZ));
continue;
}
}
continue;
}
}
if (attr)
{
bgp_update (peer, &p, addpath_id, attr, packet->afi, SAFI_LABELED_UNICAST,
ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, NULL, label, 0, NULL);
}
else
{
bgp_withdraw (peer, &p, addpath_id, attr, packet->afi, SAFI_LABELED_UNICAST,
ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, NULL, label, NULL);
}
}
if (attr) {
bgp_update(peer, &p, addpath_id, attr, packet->afi,
SAFI_UNICAST, ZEBRA_ROUTE_BGP,
BGP_ROUTE_NORMAL, NULL, &label, 0, NULL);
} else {
bgp_withdraw(peer, &p, addpath_id, attr, packet->afi,
SAFI_UNICAST, ZEBRA_ROUTE_BGP,
BGP_ROUTE_NORMAL, NULL, &label, NULL);
}
}
/* Packet length consistency check. */
if (pnt != lim)
{
zlog_err ("%s [Error] Update packet error / L-U (%zu data remaining after parsing)",
peer->host, lim - pnt);
return -1;
}
/* Packet length consistency check. */
if (pnt != lim) {
zlog_err(
"%s [Error] Update packet error / L-U (%zu data remaining after parsing)",
peer->host, lim - pnt);
return -1;
}
return 0;
return 0;
}

View File

@ -29,97 +29,95 @@ struct bgp_node;
struct bgp_info;
struct peer;
extern void bgp_reg_dereg_for_label (struct bgp_node *rn, struct bgp_info *ri,
int reg);
extern void bgp_reg_dereg_for_label(struct bgp_node *rn, struct bgp_info *ri,
int reg);
extern int bgp_parse_fec_update(void);
extern u_char * bgp_adv_label(struct bgp_node *rn, struct bgp_info *ri,
struct peer *to, afi_t afi, safi_t safi);
extern mpls_label_t bgp_adv_label(struct bgp_node *rn, struct bgp_info *ri,
struct peer *to, afi_t afi, safi_t safi);
extern int bgp_nlri_parse_label (struct peer *peer, struct attr *attr,
struct bgp_nlri *packet);
extern int bgp_nlri_parse_label(struct peer *peer, struct attr *attr,
struct bgp_nlri *packet);
static inline int
bgp_labeled_safi (safi_t safi)
static inline int bgp_labeled_safi(safi_t safi)
{
if ((safi == SAFI_LABELED_UNICAST) || (safi == SAFI_MPLS_VPN) ||
(safi == SAFI_EVPN))
return 1;
return 0;
/* NOTE: This API really says a label (tag) MAY be present. Not all EVPN
* routes will have a label.
*/
if ((safi == SAFI_LABELED_UNICAST) || (safi == SAFI_MPLS_VPN)
|| (safi == SAFI_EVPN))
return 1;
return 0;
}
static inline int
bgp_is_withdraw_label (u_char *pkt)
static inline int bgp_is_withdraw_label(mpls_label_t *label)
{
if ((pkt[0] == 0x80) && (pkt[1] == 0x00) && (pkt[2] == 0x00))
return 1;
return 0;
u_char *pkt = (u_char *)label;
/* The check on pkt[2] for 0x00 or 0x02 is in case bgp_set_valid_label()
* was called on the withdraw label */
if ((pkt[0] == 0x80) && (pkt[1] == 0x00)
&& ((pkt[2] == 0x00) || (pkt[2] == 0x02)))
return 1;
return 0;
}
static inline u_char *
bgp_encode_withdraw_label (u_char *pkt)
static inline int bgp_is_valid_label(mpls_label_t *label)
{
*pkt++ = 0x80; *pkt++ = 0x00; *pkt++ = 0x00;
return pkt;
u_char *t = (u_char *)label;
if (!t)
return 0;
return (t[2] & 0x02);
}
static inline int
bgp_is_valid_label (u_char *t)
static inline void bgp_set_valid_label(mpls_label_t *label)
{
if (!t)
return 0;
return (t[2] & 0x02);
u_char *t = (u_char *)label;
if (t)
t[2] |= 0x02;
}
static inline void
bgp_set_valid_label (u_char *t)
static inline void bgp_unset_valid_label(mpls_label_t *label)
{
if (t)
t[2] |= 0x02;
u_char *t = (u_char *)label;
if (t)
t[2] &= ~0x02;
}
static inline void
bgp_unset_valid_label (u_char *t)
static inline void bgp_register_for_label(struct bgp_node *rn,
struct bgp_info *ri)
{
if (t)
t[2] &= ~0x02;
bgp_reg_dereg_for_label(rn, ri, 1);
}
static inline void
bgp_register_for_label (struct bgp_node *rn, struct bgp_info *ri)
static inline void bgp_unregister_for_label(struct bgp_node *rn)
{
bgp_reg_dereg_for_label (rn, ri, 1);
}
static inline void
bgp_unregister_for_label (struct bgp_node *rn)
{
bgp_reg_dereg_for_label (rn, NULL, 0);
bgp_reg_dereg_for_label(rn, NULL, 0);
}
/* Label stream to value */
static inline u_int32_t
label_pton (u_char t[])
static inline u_int32_t label_pton(mpls_label_t *label)
{
return ((((unsigned int) t[0]) << 12) | (((unsigned int) t[1]) << 4) |
((unsigned int) ((t[2] & 0xF0) >> 4)));
u_char *t = (u_char *)label;
return ((((unsigned int)t[0]) << 12) | (((unsigned int)t[1]) << 4)
| ((unsigned int)((t[2] & 0xF0) >> 4)));
}
/* Encode label values */
static inline void
label_ntop (u_int32_t l, int bos, u_char t[])
static inline void label_ntop(u_int32_t l, int bos, mpls_label_t *label)
{
t[0] = ((l & 0x000FF000) >> 12);
t[1] = ((l & 0x00000FF0) >> 4);
t[2] = ((l & 0x0000000F) << 4);
if (bos)
t[2] |= 0x01;
u_char *t = (u_char *)label;
t[0] = ((l & 0x000FF000) >> 12);
t[1] = ((l & 0x00000FF0) >> 4);
t[2] = ((l & 0x0000000F) << 4);
if (bos)
t[2] |= 0x01;
}
/* Return BOS value of label stream */
static inline u_char
label_bos (u_char t[])
static inline u_char label_bos(mpls_label_t *label)
{
return (t[2] & 0x01);
u_char *t = (u_char *)label;
return (t[2] & 0x01);
};
#endif /* _BGP_LABEL_H */

View File

@ -34,29 +34,26 @@
static struct hash *lcomhash;
/* Allocate a new lcommunities. */
static struct lcommunity *
lcommunity_new (void)
static struct lcommunity *lcommunity_new(void)
{
return (struct lcommunity *) XCALLOC (MTYPE_LCOMMUNITY,
sizeof (struct lcommunity));
return (struct lcommunity *)XCALLOC(MTYPE_LCOMMUNITY,
sizeof(struct lcommunity));
}
/* Allocate lcommunities. */
void
lcommunity_free (struct lcommunity **lcom)
void lcommunity_free(struct lcommunity **lcom)
{
if ((*lcom)->val)
XFREE (MTYPE_LCOMMUNITY_VAL, (*lcom)->val);
if ((*lcom)->str)
XFREE (MTYPE_LCOMMUNITY_STR, (*lcom)->str);
XFREE (MTYPE_LCOMMUNITY, *lcom);
lcom = NULL;
if ((*lcom)->val)
XFREE(MTYPE_LCOMMUNITY_VAL, (*lcom)->val);
if ((*lcom)->str)
XFREE(MTYPE_LCOMMUNITY_STR, (*lcom)->str);
XFREE(MTYPE_LCOMMUNITY, *lcom);
lcom = NULL;
}
static void
lcommunity_hash_free (struct lcommunity *lcom)
static void lcommunity_hash_free(struct lcommunity *lcom)
{
lcommunity_free (&lcom);
lcommunity_free(&lcom);
}
/* Add a new Large Communities value to Large Communities
@ -64,329 +61,308 @@ lcommunity_hash_free (struct lcommunity *lcom)
structure, we don't add the value. Newly added value is sorted by
numerical order. When the value is added to the structure return 1
else return 0. */
static int
lcommunity_add_val (struct lcommunity *lcom, struct lcommunity_val *lval)
static int lcommunity_add_val(struct lcommunity *lcom,
struct lcommunity_val *lval)
{
u_int8_t *p;
int ret;
int c;
u_int8_t *p;
int ret;
int c;
/* When this is fist value, just add it. */
if (lcom->val == NULL)
{
lcom->size++;
lcom->val = XMALLOC (MTYPE_LCOMMUNITY_VAL, lcom_length (lcom));
memcpy (lcom->val, lval->val, LCOMMUNITY_SIZE);
return 1;
}
/* When this is fist value, just add it. */
if (lcom->val == NULL) {
lcom->size++;
lcom->val = XMALLOC(MTYPE_LCOMMUNITY_VAL, lcom_length(lcom));
memcpy(lcom->val, lval->val, LCOMMUNITY_SIZE);
return 1;
}
/* If the value already exists in the structure return 0. */
c = 0;
for (p = lcom->val; c < lcom->size; p += LCOMMUNITY_SIZE, c++)
{
ret = memcmp (p, lval->val, LCOMMUNITY_SIZE);
if (ret == 0)
return 0;
if (ret > 0)
break;
}
/* If the value already exists in the structure return 0. */
c = 0;
for (p = lcom->val; c < lcom->size; p += LCOMMUNITY_SIZE, c++) {
ret = memcmp(p, lval->val, LCOMMUNITY_SIZE);
if (ret == 0)
return 0;
if (ret > 0)
break;
}
/* Add the value to the structure with numerical sorting. */
lcom->size++;
lcom->val = XREALLOC (MTYPE_LCOMMUNITY_VAL, lcom->val, lcom_length (lcom));
/* Add the value to the structure with numerical sorting. */
lcom->size++;
lcom->val =
XREALLOC(MTYPE_LCOMMUNITY_VAL, lcom->val, lcom_length(lcom));
memmove (lcom->val + (c + 1) * LCOMMUNITY_SIZE,
lcom->val + c * LCOMMUNITY_SIZE,
(lcom->size - 1 - c) * LCOMMUNITY_SIZE);
memcpy (lcom->val + c * LCOMMUNITY_SIZE, lval->val, LCOMMUNITY_SIZE);
memmove(lcom->val + (c + 1) * LCOMMUNITY_SIZE,
lcom->val + c * LCOMMUNITY_SIZE,
(lcom->size - 1 - c) * LCOMMUNITY_SIZE);
memcpy(lcom->val + c * LCOMMUNITY_SIZE, lval->val, LCOMMUNITY_SIZE);
return 1;
return 1;
}
/* This function takes pointer to Large Communites strucutre then
create a new Large Communities structure by uniq and sort each
Large Communities value. */
struct lcommunity *
lcommunity_uniq_sort (struct lcommunity *lcom)
struct lcommunity *lcommunity_uniq_sort(struct lcommunity *lcom)
{
int i;
struct lcommunity *new;
struct lcommunity_val *lval;
int i;
struct lcommunity *new;
struct lcommunity_val *lval;
if (! lcom)
return NULL;
if (!lcom)
return NULL;
new = lcommunity_new ();
new = lcommunity_new();
for (i = 0; i < lcom->size; i++)
{
lval = (struct lcommunity_val *) (lcom->val + (i * LCOMMUNITY_SIZE));
lcommunity_add_val (new, lval);
}
return new;
for (i = 0; i < lcom->size; i++) {
lval = (struct lcommunity_val *)(lcom->val
+ (i * LCOMMUNITY_SIZE));
lcommunity_add_val(new, lval);
}
return new;
}
/* Parse Large Communites Attribute in BGP packet. */
struct lcommunity *
lcommunity_parse (u_int8_t *pnt, u_short length)
struct lcommunity *lcommunity_parse(u_int8_t *pnt, u_short length)
{
struct lcommunity tmp;
struct lcommunity *new;
struct lcommunity tmp;
struct lcommunity *new;
/* Length check. */
if (length % LCOMMUNITY_SIZE)
return NULL;
/* Length check. */
if (length % LCOMMUNITY_SIZE)
return NULL;
/* Prepare tmporary structure for making a new Large Communities
Attribute. */
tmp.size = length / LCOMMUNITY_SIZE;
tmp.val = pnt;
/* Prepare tmporary structure for making a new Large Communities
Attribute. */
tmp.size = length / LCOMMUNITY_SIZE;
tmp.val = pnt;
/* Create a new Large Communities Attribute by uniq and sort each
Large Communities value */
new = lcommunity_uniq_sort (&tmp);
/* Create a new Large Communities Attribute by uniq and sort each
Large Communities value */
new = lcommunity_uniq_sort(&tmp);
return lcommunity_intern (new);
return lcommunity_intern(new);
}
/* Duplicate the Large Communities Attribute structure. */
struct lcommunity *
lcommunity_dup (struct lcommunity *lcom)
struct lcommunity *lcommunity_dup(struct lcommunity *lcom)
{
struct lcommunity *new;
struct lcommunity *new;
new = XCALLOC (MTYPE_LCOMMUNITY, sizeof (struct lcommunity));
new->size = lcom->size;
if (new->size)
{
new->val = XMALLOC (MTYPE_LCOMMUNITY_VAL, lcom->size * LCOMMUNITY_SIZE);
memcpy (new->val, lcom->val, lcom->size * LCOMMUNITY_SIZE);
}
else
new->val = NULL;
return new;
new = XCALLOC(MTYPE_LCOMMUNITY, sizeof(struct lcommunity));
new->size = lcom->size;
if (new->size) {
new->val = XMALLOC(MTYPE_LCOMMUNITY_VAL,
lcom->size * LCOMMUNITY_SIZE);
memcpy(new->val, lcom->val, lcom->size * LCOMMUNITY_SIZE);
} else
new->val = NULL;
return new;
}
/* Retrun string representation of communities attribute. */
char *
lcommunity_str (struct lcommunity *lcom)
char *lcommunity_str(struct lcommunity *lcom)
{
if (! lcom->str)
lcom->str = lcommunity_lcom2str (lcom, LCOMMUNITY_FORMAT_DISPLAY);
return lcom->str;
if (!lcom->str)
lcom->str =
lcommunity_lcom2str(lcom, LCOMMUNITY_FORMAT_DISPLAY);
return lcom->str;
}
/* Merge two Large Communities Attribute structure. */
struct lcommunity *
lcommunity_merge (struct lcommunity *lcom1, struct lcommunity *lcom2)
struct lcommunity *lcommunity_merge(struct lcommunity *lcom1,
struct lcommunity *lcom2)
{
if (lcom1->val)
lcom1->val = XREALLOC (MTYPE_LCOMMUNITY_VAL, lcom1->val,
(lcom1->size + lcom2->size) * LCOMMUNITY_SIZE);
else
lcom1->val = XMALLOC (MTYPE_LCOMMUNITY_VAL,
(lcom1->size + lcom2->size) * LCOMMUNITY_SIZE);
if (lcom1->val)
lcom1->val =
XREALLOC(MTYPE_LCOMMUNITY_VAL, lcom1->val,
(lcom1->size + lcom2->size) * LCOMMUNITY_SIZE);
else
lcom1->val =
XMALLOC(MTYPE_LCOMMUNITY_VAL,
(lcom1->size + lcom2->size) * LCOMMUNITY_SIZE);
memcpy (lcom1->val + (lcom1->size * LCOMMUNITY_SIZE),
lcom2->val, lcom2->size * LCOMMUNITY_SIZE);
lcom1->size += lcom2->size;
memcpy(lcom1->val + (lcom1->size * LCOMMUNITY_SIZE), lcom2->val,
lcom2->size * LCOMMUNITY_SIZE);
lcom1->size += lcom2->size;
return lcom1;
return lcom1;
}
/* Intern Large Communities Attribute. */
struct lcommunity *
lcommunity_intern (struct lcommunity *lcom)
struct lcommunity *lcommunity_intern(struct lcommunity *lcom)
{
struct lcommunity *find;
struct lcommunity *find;
assert (lcom->refcnt == 0);
assert(lcom->refcnt == 0);
find = (struct lcommunity *) hash_get (lcomhash, lcom, hash_alloc_intern);
find = (struct lcommunity *)hash_get(lcomhash, lcom, hash_alloc_intern);
if (find != lcom)
lcommunity_free (&lcom);
if (find != lcom)
lcommunity_free(&lcom);
find->refcnt++;
find->refcnt++;
if (! find->str)
find->str = lcommunity_lcom2str (find, LCOMMUNITY_FORMAT_DISPLAY);
if (!find->str)
find->str =
lcommunity_lcom2str(find, LCOMMUNITY_FORMAT_DISPLAY);
return find;
return find;
}
/* Unintern Large Communities Attribute. */
void
lcommunity_unintern (struct lcommunity **lcom)
void lcommunity_unintern(struct lcommunity **lcom)
{
struct lcommunity *ret;
struct lcommunity *ret;
if ((*lcom)->refcnt)
(*lcom)->refcnt--;
if ((*lcom)->refcnt)
(*lcom)->refcnt--;
/* Pull off from hash. */
if ((*lcom)->refcnt == 0)
{
/* Large community must be in the hash. */
ret = (struct lcommunity *) hash_release (lcomhash, *lcom);
assert (ret != NULL);
/* Pull off from hash. */
if ((*lcom)->refcnt == 0) {
/* Large community must be in the hash. */
ret = (struct lcommunity *)hash_release(lcomhash, *lcom);
assert(ret != NULL);
lcommunity_free (lcom);
}
lcommunity_free(lcom);
}
}
/* Utility function to make hash key. */
unsigned int
lcommunity_hash_make (void *arg)
unsigned int lcommunity_hash_make(void *arg)
{
const struct lcommunity *lcom = arg;
int size = lcom->size * LCOMMUNITY_SIZE;
u_int8_t *pnt = lcom->val;
unsigned int key = 0;
int c;
const struct lcommunity *lcom = arg;
int size = lcom->size * LCOMMUNITY_SIZE;
u_int8_t *pnt = lcom->val;
unsigned int key = 0;
int c;
for (c = 0; c < size; c += LCOMMUNITY_SIZE)
{
key += pnt[c];
key += pnt[c + 1];
key += pnt[c + 2];
key += pnt[c + 3];
key += pnt[c + 4];
key += pnt[c + 5];
key += pnt[c + 6];
key += pnt[c + 7];
key += pnt[c + 8];
key += pnt[c + 9];
key += pnt[c + 10];
key += pnt[c + 11];
}
for (c = 0; c < size; c += LCOMMUNITY_SIZE) {
key += pnt[c];
key += pnt[c + 1];
key += pnt[c + 2];
key += pnt[c + 3];
key += pnt[c + 4];
key += pnt[c + 5];
key += pnt[c + 6];
key += pnt[c + 7];
key += pnt[c + 8];
key += pnt[c + 9];
key += pnt[c + 10];
key += pnt[c + 11];
}
return key;
return key;
}
/* Compare two Large Communities Attribute structure. */
int
lcommunity_cmp (const void *arg1, const void *arg2)
int lcommunity_cmp(const void *arg1, const void *arg2)
{
const struct lcommunity *lcom1 = arg1;
const struct lcommunity *lcom2 = arg2;
const struct lcommunity *lcom1 = arg1;
const struct lcommunity *lcom2 = arg2;
return (lcom1->size == lcom2->size
&& memcmp (lcom1->val, lcom2->val, lcom1->size * LCOMMUNITY_SIZE) == 0);
return (lcom1->size == lcom2->size
&& memcmp(lcom1->val, lcom2->val, lcom1->size * LCOMMUNITY_SIZE)
== 0);
}
/* Return communities hash. */
struct hash *
lcommunity_hash (void)
struct hash *lcommunity_hash(void)
{
return lcomhash;
return lcomhash;
}
/* Initialize Large Comminities related hash. */
void
lcommunity_init (void)
void lcommunity_init(void)
{
lcomhash = hash_create (lcommunity_hash_make, lcommunity_cmp, NULL);
lcomhash = hash_create(lcommunity_hash_make, lcommunity_cmp, NULL);
}
void
lcommunity_finish (void)
void lcommunity_finish(void)
{
hash_clean (lcomhash, (void (*)(void *))lcommunity_hash_free);
hash_free (lcomhash);
lcomhash = NULL;
hash_clean(lcomhash, (void (*)(void *))lcommunity_hash_free);
hash_free(lcomhash);
lcomhash = NULL;
}
/* Large Communities token enum. */
enum lcommunity_token
{
lcommunity_token_unknown = 0,
lcommunity_token_val,
enum lcommunity_token {
lcommunity_token_unknown = 0,
lcommunity_token_val,
};
/* Get next Large Communities token from the string. */
static const char *
lcommunity_gettoken (const char *str, struct lcommunity_val *lval,
enum lcommunity_token *token)
static const char *lcommunity_gettoken(const char *str,
struct lcommunity_val *lval,
enum lcommunity_token *token)
{
const char *p = str;
const char *p = str;
/* Skip white space. */
while (isspace ((int) *p))
{
p++;
str++;
}
/* Check the end of the line. */
if (*p == '\0')
return NULL;
/* Community value. */
if (isdigit ((int) *p))
{
int separator = 0;
int digit = 0;
u_int32_t globaladmin = 0;
u_int32_t localdata1 = 0;
u_int32_t localdata2 = 0;
while (isdigit ((int) *p) || *p == ':')
{
if (*p == ':')
{
if (separator == 2)
{
*token = lcommunity_token_unknown;
return NULL;
}
else
{
separator++;
digit = 0;
if (separator == 1) {
globaladmin = localdata2;
} else {
localdata1 = localdata2;
}
localdata2 = 0;
}
}
else
{
digit = 1;
localdata2 *= 10;
localdata2 += (*p - '0');
}
p++;
}
if (! digit)
{
*token = lcommunity_token_unknown;
return NULL;
/* Skip white space. */
while (isspace((int)*p)) {
p++;
str++;
}
/*
* Copy the large comm.
*/
lval->val[0] = (globaladmin >> 24) & 0xff;
lval->val[1] = (globaladmin >> 16) & 0xff;
lval->val[2] = (globaladmin >> 8) & 0xff;
lval->val[3] = globaladmin & 0xff;
lval->val[4] = (localdata1 >> 24) & 0xff;
lval->val[5] = (localdata1 >> 16) & 0xff;
lval->val[6] = (localdata1 >> 8) & 0xff;
lval->val[7] = localdata1 & 0xff;
lval->val[8] = (localdata2 >> 24) & 0xff;
lval->val[9] = (localdata2 >> 16) & 0xff;
lval->val[10] = (localdata2 >> 8) & 0xff;
lval->val[11] = localdata2 & 0xff;
/* Check the end of the line. */
if (*p == '\0')
return NULL;
*token = lcommunity_token_val;
return p;
}
*token = lcommunity_token_unknown;
return p;
/* Community value. */
if (isdigit((int)*p)) {
int separator = 0;
int digit = 0;
u_int32_t globaladmin = 0;
u_int32_t localdata1 = 0;
u_int32_t localdata2 = 0;
while (isdigit((int)*p) || *p == ':') {
if (*p == ':') {
if (separator == 2) {
*token = lcommunity_token_unknown;
return NULL;
} else {
separator++;
digit = 0;
if (separator == 1) {
globaladmin = localdata2;
} else {
localdata1 = localdata2;
}
localdata2 = 0;
}
} else {
digit = 1;
localdata2 *= 10;
localdata2 += (*p - '0');
}
p++;
}
if (!digit) {
*token = lcommunity_token_unknown;
return NULL;
}
/*
* Copy the large comm.
*/
lval->val[0] = (globaladmin >> 24) & 0xff;
lval->val[1] = (globaladmin >> 16) & 0xff;
lval->val[2] = (globaladmin >> 8) & 0xff;
lval->val[3] = globaladmin & 0xff;
lval->val[4] = (localdata1 >> 24) & 0xff;
lval->val[5] = (localdata1 >> 16) & 0xff;
lval->val[6] = (localdata1 >> 8) & 0xff;
lval->val[7] = localdata1 & 0xff;
lval->val[8] = (localdata2 >> 24) & 0xff;
lval->val[9] = (localdata2 >> 16) & 0xff;
lval->val[10] = (localdata2 >> 8) & 0xff;
lval->val[11] = localdata2 & 0xff;
*token = lcommunity_token_val;
return p;
}
*token = lcommunity_token_unknown;
return p;
}
/*
@ -396,174 +372,168 @@ lcommunity_gettoken (const char *str, struct lcommunity_val *lval,
When string includes keyword for each large community value.
Please specify keyword_included as non-zero value.
*/
struct lcommunity *
lcommunity_str2com (const char *str)
struct lcommunity *lcommunity_str2com(const char *str)
{
struct lcommunity *lcom = NULL;
enum lcommunity_token token = lcommunity_token_unknown;
struct lcommunity_val lval;
struct lcommunity *lcom = NULL;
enum lcommunity_token token = lcommunity_token_unknown;
struct lcommunity_val lval;
while ((str = lcommunity_gettoken (str, &lval, &token)))
{
switch (token)
{
case lcommunity_token_val:
if (lcom == NULL)
lcom = lcommunity_new ();
lcommunity_add_val (lcom, &lval);
break;
case lcommunity_token_unknown:
default:
if (lcom)
lcommunity_free (&lcom);
return NULL;
}
}
return lcom;
while ((str = lcommunity_gettoken(str, &lval, &token))) {
switch (token) {
case lcommunity_token_val:
if (lcom == NULL)
lcom = lcommunity_new();
lcommunity_add_val(lcom, &lval);
break;
case lcommunity_token_unknown:
default:
if (lcom)
lcommunity_free(&lcom);
return NULL;
}
}
return lcom;
}
int
lcommunity_include (struct lcommunity *lcom, u_char *ptr)
int lcommunity_include(struct lcommunity *lcom, u_char *ptr)
{
int i;
u_char *lcom_ptr;
int i;
u_char *lcom_ptr;
lcom_ptr = lcom->val;
for (i = 0; i < lcom->size; i++) {
lcom_ptr += (i * LCOMMUNITY_SIZE);
if (memcmp (ptr, lcom_ptr, LCOMMUNITY_SIZE) == 0)
return 1;
}
return 0;
lcom_ptr = lcom->val;
for (i = 0; i < lcom->size; i++) {
lcom_ptr += (i * LCOMMUNITY_SIZE);
if (memcmp(ptr, lcom_ptr, LCOMMUNITY_SIZE) == 0)
return 1;
}
return 0;
}
/* Convert large community attribute to string.
The large coms will be in 65535:65531:0 format.
*/
char *
lcommunity_lcom2str (struct lcommunity *lcom, int format)
char *lcommunity_lcom2str(struct lcommunity *lcom, int format)
{
int i;
u_int8_t *pnt;
int i;
u_int8_t *pnt;
#define LCOMMUNITY_STR_DEFAULT_LEN 40
int str_size;
int str_pnt;
char *str_buf;
int len = 0;
int first = 1;
u_int32_t globaladmin, localdata1, localdata2;
int str_size;
int str_pnt;
char *str_buf;
int len = 0;
int first = 1;
u_int32_t globaladmin, localdata1, localdata2;
if (lcom->size == 0)
{
str_buf = XMALLOC (MTYPE_LCOMMUNITY_STR, 1);
str_buf[0] = '\0';
return str_buf;
}
/* Prepare buffer. */
str_buf = XMALLOC (MTYPE_LCOMMUNITY_STR, LCOMMUNITY_STR_DEFAULT_LEN + 1);
str_size = LCOMMUNITY_STR_DEFAULT_LEN + 1;
str_pnt = 0;
for (i = 0; i < lcom->size; i++)
{
/* Make it sure size is enough. */
while (str_pnt + LCOMMUNITY_STR_DEFAULT_LEN >= str_size)
{
str_size *= 2;
str_buf = XREALLOC (MTYPE_LCOMMUNITY_STR, str_buf, str_size);
if (lcom->size == 0) {
str_buf = XMALLOC(MTYPE_LCOMMUNITY_STR, 1);
str_buf[0] = '\0';
return str_buf;
}
/* Space between each value. */
if (! first)
str_buf[str_pnt++] = ' ';
/* Prepare buffer. */
str_buf = XMALLOC(MTYPE_LCOMMUNITY_STR, LCOMMUNITY_STR_DEFAULT_LEN + 1);
str_size = LCOMMUNITY_STR_DEFAULT_LEN + 1;
str_pnt = 0;
pnt = lcom->val + (i * 12);
for (i = 0; i < lcom->size; i++) {
/* Make it sure size is enough. */
while (str_pnt + LCOMMUNITY_STR_DEFAULT_LEN >= str_size) {
str_size *= 2;
str_buf = XREALLOC(MTYPE_LCOMMUNITY_STR, str_buf,
str_size);
}
globaladmin = (*pnt++ << 24);
globaladmin |= (*pnt++ << 16);
globaladmin |= (*pnt++ << 8);
globaladmin |= (*pnt++);
/* Space between each value. */
if (!first)
str_buf[str_pnt++] = ' ';
localdata1 = (*pnt++ << 24);
localdata1 |= (*pnt++ << 16);
localdata1 |= (*pnt++ << 8);
localdata1 |= (*pnt++);
pnt = lcom->val + (i * 12);
localdata2 = (*pnt++ << 24);
localdata2 |= (*pnt++ << 16);
localdata2 |= (*pnt++ << 8);
localdata2 |= (*pnt++);
globaladmin = (*pnt++ << 24);
globaladmin |= (*pnt++ << 16);
globaladmin |= (*pnt++ << 8);
globaladmin |= (*pnt++);
len = sprintf( str_buf + str_pnt, "%u:%u:%u", globaladmin,
localdata1, localdata2);
str_pnt += len;
first = 0;
}
return str_buf;
localdata1 = (*pnt++ << 24);
localdata1 |= (*pnt++ << 16);
localdata1 |= (*pnt++ << 8);
localdata1 |= (*pnt++);
localdata2 = (*pnt++ << 24);
localdata2 |= (*pnt++ << 16);
localdata2 |= (*pnt++ << 8);
localdata2 |= (*pnt++);
len = sprintf(str_buf + str_pnt, "%u:%u:%u", globaladmin,
localdata1, localdata2);
str_pnt += len;
first = 0;
}
return str_buf;
}
int
lcommunity_match (const struct lcommunity *lcom1,
const struct lcommunity *lcom2)
int lcommunity_match(const struct lcommunity *lcom1,
const struct lcommunity *lcom2)
{
int i = 0;
int j = 0;
int i = 0;
int j = 0;
if (lcom1 == NULL && lcom2 == NULL)
return 1;
if (lcom1 == NULL && lcom2 == NULL)
return 1;
if (lcom1 == NULL || lcom2 == NULL)
return 0;
if (lcom1 == NULL || lcom2 == NULL)
return 0;
if (lcom1->size < lcom2->size)
return 0;
if (lcom1->size < lcom2->size)
return 0;
/* Every community on com2 needs to be on com1 for this to match */
while (i < lcom1->size && j < lcom2->size)
{
if (memcmp (lcom1->val + (i*12), lcom2->val + (j*12), LCOMMUNITY_SIZE) == 0)
j++;
i++;
}
/* Every community on com2 needs to be on com1 for this to match */
while (i < lcom1->size && j < lcom2->size) {
if (memcmp(lcom1->val + (i * 12), lcom2->val + (j * 12),
LCOMMUNITY_SIZE)
== 0)
j++;
i++;
}
if (j == lcom2->size)
return 1;
else
return 0;
if (j == lcom2->size)
return 1;
else
return 0;
}
/* Delete one lcommunity. */
void
lcommunity_del_val (struct lcommunity *lcom, u_char *ptr)
void lcommunity_del_val(struct lcommunity *lcom, u_char *ptr)
{
int i = 0;
int c = 0;
int i = 0;
int c = 0;
if (! lcom->val)
return;
if (!lcom->val)
return;
while (i < lcom->size)
{
if (memcmp (lcom->val + i*LCOMMUNITY_SIZE, ptr, LCOMMUNITY_SIZE) == 0)
{
c = lcom->size -i -1;
while (i < lcom->size) {
if (memcmp(lcom->val + i * LCOMMUNITY_SIZE, ptr,
LCOMMUNITY_SIZE)
== 0) {
c = lcom->size - i - 1;
if (c > 0)
memmove (lcom->val + i*LCOMMUNITY_SIZE, lcom->val + (i + 1)*LCOMMUNITY_SIZE, c * LCOMMUNITY_SIZE);
if (c > 0)
memmove(lcom->val + i * LCOMMUNITY_SIZE,
lcom->val + (i + 1) * LCOMMUNITY_SIZE,
c * LCOMMUNITY_SIZE);
lcom->size--;
lcom->size--;
if (lcom->size > 0)
lcom->val = XREALLOC (MTYPE_COMMUNITY_VAL, lcom->val,
lcom_length (lcom));
else
{
XFREE (MTYPE_COMMUNITY_VAL, lcom->val);
lcom->val = NULL;
}
return;
if (lcom->size > 0)
lcom->val =
XREALLOC(MTYPE_COMMUNITY_VAL, lcom->val,
lcom_length(lcom));
else {
XFREE(MTYPE_COMMUNITY_VAL, lcom->val);
lcom->val = NULL;
}
return;
}
i++;
}
i++;
}
}

View File

@ -30,45 +30,45 @@
#define LCOMMUNITY_SIZE 12
/* Large Communities attribute. */
struct lcommunity
{
/* Reference counter. */
unsigned long refcnt;
struct lcommunity {
/* Reference counter. */
unsigned long refcnt;
/* Size of Extended Communities attribute. */
int size;
/* Size of Extended Communities attribute. */
int size;
/* Extended Communities value. */
u_int8_t *val;
/* Extended Communities value. */
u_int8_t *val;
/* Human readable format string. */
char *str;
/* Human readable format string. */
char *str;
};
/* Extended community value is eight octet. */
struct lcommunity_val
{
char val[LCOMMUNITY_SIZE];
struct lcommunity_val {
char val[LCOMMUNITY_SIZE];
};
#define lcom_length(X) ((X)->size * LCOMMUNITY_SIZE)
extern void lcommunity_init (void);
extern void lcommunity_finish (void);
extern void lcommunity_free (struct lcommunity **);
extern struct lcommunity *lcommunity_parse (u_int8_t *, u_short);
extern struct lcommunity *lcommunity_dup (struct lcommunity *);
extern struct lcommunity *lcommunity_merge (struct lcommunity *, struct lcommunity *);
extern struct lcommunity *lcommunity_uniq_sort (struct lcommunity *);
extern struct lcommunity *lcommunity_intern (struct lcommunity *);
extern int lcommunity_cmp (const void *, const void *);
extern void lcommunity_unintern (struct lcommunity **);
extern unsigned int lcommunity_hash_make (void *);
extern struct hash *lcommunity_hash (void);
extern struct lcommunity *lcommunity_str2com (const char *);
extern char *lcommunity_lcom2str (struct lcommunity *, int);
extern int lcommunity_match (const struct lcommunity *, const struct lcommunity *);
extern char *lcommunity_str (struct lcommunity *);
extern int lcommunity_include (struct lcommunity *lcom, u_char *ptr);
extern void lcommunity_del_val (struct lcommunity *lcom, u_char *ptr);
extern void lcommunity_init(void);
extern void lcommunity_finish(void);
extern void lcommunity_free(struct lcommunity **);
extern struct lcommunity *lcommunity_parse(u_int8_t *, u_short);
extern struct lcommunity *lcommunity_dup(struct lcommunity *);
extern struct lcommunity *lcommunity_merge(struct lcommunity *,
struct lcommunity *);
extern struct lcommunity *lcommunity_uniq_sort(struct lcommunity *);
extern struct lcommunity *lcommunity_intern(struct lcommunity *);
extern int lcommunity_cmp(const void *, const void *);
extern void lcommunity_unintern(struct lcommunity **);
extern unsigned int lcommunity_hash_make(void *);
extern struct hash *lcommunity_hash(void);
extern struct lcommunity *lcommunity_str2com(const char *);
extern char *lcommunity_lcom2str(struct lcommunity *, int);
extern int lcommunity_match(const struct lcommunity *,
const struct lcommunity *);
extern char *lcommunity_str(struct lcommunity *);
extern int lcommunity_include(struct lcommunity *lcom, u_char *ptr);
extern void lcommunity_del_val(struct lcommunity *lcom, u_char *ptr);
#endif /* _QUAGGA_BGP_LCOMMUNITY_H */

View File

@ -60,112 +60,101 @@
#endif
/* bgpd options, we use GNU getopt library. */
static const struct option longopts[] =
{
{ "bgp_port", required_argument, NULL, 'p'},
{ "listenon", required_argument, NULL, 'l'},
{ "retain", no_argument, NULL, 'r'},
{ "no_kernel", no_argument, NULL, 'n'},
{ "skip_runas", no_argument, NULL, 'S'},
{ "ecmp", required_argument, NULL, 'e'},
{ 0 }
};
static const struct option longopts[] = {
{"bgp_port", required_argument, NULL, 'p'},
{"listenon", required_argument, NULL, 'l'},
{"retain", no_argument, NULL, 'r'},
{"no_kernel", no_argument, NULL, 'n'},
{"skip_runas", no_argument, NULL, 'S'},
{"ecmp", required_argument, NULL, 'e'},
{0}};
/* signal definitions */
void sighup (void);
void sigint (void);
void sigusr1 (void);
void sighup(void);
void sigint(void);
void sigusr1(void);
static void bgp_exit (int);
static void bgp_vrf_terminate (void);
static void bgp_exit(int);
static void bgp_vrf_terminate(void);
static struct quagga_signal_t bgp_signals[] =
{
{
.signal = SIGHUP,
.handler = &sighup,
},
{
.signal = SIGUSR1,
.handler = &sigusr1,
},
{
.signal = SIGINT,
.handler = &sigint,
},
{
.signal = SIGTERM,
.handler = &sigint,
},
static struct quagga_signal_t bgp_signals[] = {
{
.signal = SIGHUP,
.handler = &sighup,
},
{
.signal = SIGUSR1,
.handler = &sigusr1,
},
{
.signal = SIGINT,
.handler = &sigint,
},
{
.signal = SIGTERM,
.handler = &sigint,
},
};
/* Route retain mode flag. */
static int retain_mode = 0;
/* privileges */
static zebra_capabilities_t _caps_p [] =
{
ZCAP_BIND,
ZCAP_NET_RAW,
ZCAP_NET_ADMIN,
static zebra_capabilities_t _caps_p[] = {
ZCAP_BIND, ZCAP_NET_RAW, ZCAP_NET_ADMIN,
};
struct zebra_privs_t bgpd_privs =
{
struct zebra_privs_t bgpd_privs = {
#if defined(FRR_USER) && defined(FRR_GROUP)
.user = FRR_USER,
.group = FRR_GROUP,
.user = FRR_USER,
.group = FRR_GROUP,
#endif
#ifdef VTY_GROUP
.vty_group = VTY_GROUP,
.vty_group = VTY_GROUP,
#endif
.caps_p = _caps_p,
.cap_num_p = array_size(_caps_p),
.cap_num_i = 0,
.caps_p = _caps_p,
.cap_num_p = array_size(_caps_p),
.cap_num_i = 0,
};
static struct frr_daemon_info bgpd_di;
/* SIGHUP handler. */
void
sighup (void)
void sighup(void)
{
zlog_info ("SIGHUP received");
zlog_info("SIGHUP received");
/* Terminate all thread. */
bgp_terminate ();
bgp_reset ();
zlog_info ("bgpd restarting!");
/* Terminate all thread. */
bgp_terminate();
bgp_reset();
zlog_info("bgpd restarting!");
/* Reload config file. */
vty_read_config (bgpd_di.config_file, config_default);
/* Reload config file. */
vty_read_config(bgpd_di.config_file, config_default);
/* Try to return to normal operation. */
/* Try to return to normal operation. */
}
/* SIGINT handler. */
__attribute__((__noreturn__)) void
sigint (void)
__attribute__((__noreturn__)) void sigint(void)
{
zlog_notice ("Terminating on signal");
zlog_notice("Terminating on signal");
if (! retain_mode)
{
bgp_terminate ();
if (bgpd_privs.user) /* NULL if skip_runas flag set */
zprivs_terminate (&bgpd_privs);
}
if (!retain_mode) {
bgp_terminate();
if (bgpd_privs.user) /* NULL if skip_runas flag set */
zprivs_terminate(&bgpd_privs);
}
bgp_exit (0);
bgp_exit(0);
exit (0);
exit(0);
}
/* SIGUSR1 handler. */
void
sigusr1 (void)
void sigusr1(void)
{
zlog_rotate();
zlog_rotate();
}
/*
@ -175,270 +164,250 @@ sigusr1 (void)
Zebra route removal and protocol teardown are not meant to be done here.
For example, "retain_mode" may be set.
*/
static __attribute__((__noreturn__)) void
bgp_exit (int status)
static __attribute__((__noreturn__)) void bgp_exit(int status)
{
struct bgp *bgp;
struct listnode *node, *nnode;
struct bgp *bgp;
struct listnode *node, *nnode;
/* it only makes sense for this to be called on a clean exit */
assert (status == 0);
/* it only makes sense for this to be called on a clean exit */
assert(status == 0);
bfd_gbl_exit();
bfd_gbl_exit();
bgp_close();
bgp_close();
if (retain_mode)
if_add_hook (IF_DELETE_HOOK, NULL);
if (retain_mode)
if_add_hook(IF_DELETE_HOOK, NULL);
/* reverse bgp_master_init */
for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
bgp_delete (bgp);
/* reverse bgp_master_init */
for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp))
bgp_delete(bgp);
/* reverse bgp_dump_init */
bgp_dump_finish ();
/* reverse bgp_dump_init */
bgp_dump_finish();
/* reverse bgp_route_init */
bgp_route_finish ();
/* reverse bgp_route_init */
bgp_route_finish();
/* cleanup route maps */
bgp_route_map_terminate();
/* cleanup route maps */
bgp_route_map_terminate();
/* reverse bgp_attr_init */
bgp_attr_finish ();
/* reverse bgp_attr_init */
bgp_attr_finish();
/* reverse access_list_init */
access_list_add_hook (NULL);
access_list_delete_hook (NULL);
access_list_reset ();
/* reverse access_list_init */
access_list_add_hook(NULL);
access_list_delete_hook(NULL);
access_list_reset();
/* reverse bgp_filter_init */
as_list_add_hook (NULL);
as_list_delete_hook (NULL);
bgp_filter_reset ();
/* reverse bgp_filter_init */
as_list_add_hook(NULL);
as_list_delete_hook(NULL);
bgp_filter_reset();
/* reverse prefix_list_init */
prefix_list_add_hook (NULL);
prefix_list_delete_hook (NULL);
prefix_list_reset ();
/* reverse prefix_list_init */
prefix_list_add_hook(NULL);
prefix_list_delete_hook(NULL);
prefix_list_reset();
/* reverse community_list_init */
community_list_terminate (bgp_clist);
/* reverse community_list_init */
community_list_terminate(bgp_clist);
bgp_vrf_terminate ();
cmd_terminate ();
vty_terminate ();
bgp_vrf_terminate();
cmd_terminate();
vty_terminate();
#if ENABLE_BGP_VNC
vnc_zebra_destroy();
vnc_zebra_destroy();
#endif
bgp_zebra_destroy();
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);
bgp_zebra_destroy();
/* reverse bgp_master_init */
if (bm->master)
thread_master_free (bm->master);
/* reverse bgp_master_init */
if (bm->master)
thread_master_free(bm->master);
closezlog ();
closezlog();
list_delete (bm->bgp);
memset (bm, 0, sizeof (*bm));
list_delete(bm->bgp);
memset(bm, 0, sizeof(*bm));
if (bgp_debug_count())
log_memstats_stderr ("bgpd");
exit (status);
if (bgp_debug_count())
log_memstats_stderr("bgpd");
exit(status);
}
static int
bgp_vrf_new (struct vrf *vrf)
static int bgp_vrf_new(struct vrf *vrf)
{
if (BGP_DEBUG (zebra, ZEBRA))
zlog_debug ("VRF Created: %s(%d)", vrf->name, vrf->vrf_id);
if (BGP_DEBUG(zebra, ZEBRA))
zlog_debug("VRF Created: %s(%d)", vrf->name, vrf->vrf_id);
return 0;
return 0;
}
static int
bgp_vrf_delete (struct vrf *vrf)
static int bgp_vrf_delete(struct vrf *vrf)
{
if (BGP_DEBUG (zebra, ZEBRA))
zlog_debug ("VRF Deletion: %s(%d)", vrf->name, vrf->vrf_id);
if (BGP_DEBUG(zebra, ZEBRA))
zlog_debug("VRF Deletion: %s(%d)", vrf->name, vrf->vrf_id);
return 0;
return 0;
}
static int
bgp_vrf_enable (struct vrf *vrf)
static int bgp_vrf_enable(struct vrf *vrf)
{
struct bgp *bgp;
vrf_id_t old_vrf_id;
struct bgp *bgp;
vrf_id_t old_vrf_id;
if (BGP_DEBUG (zebra, ZEBRA))
zlog_debug("VRF enable add %s id %d", vrf->name, vrf->vrf_id);
if (BGP_DEBUG(zebra, ZEBRA))
zlog_debug("VRF enable add %s id %d", vrf->name, vrf->vrf_id);
bgp = bgp_lookup_by_name (vrf->name);
if (bgp)
{
old_vrf_id = bgp->vrf_id;
/* We have instance configured, link to VRF and make it "up". */
bgp_vrf_link (bgp, vrf);
bgp = bgp_lookup_by_name(vrf->name);
if (bgp) {
old_vrf_id = bgp->vrf_id;
/* We have instance configured, link to VRF and make it "up". */
bgp_vrf_link(bgp, vrf);
/* Update any redistribute vrf bitmaps if the vrf_id changed */
if (old_vrf_id != bgp->vrf_id)
bgp_update_redist_vrf_bitmaps(bgp, old_vrf_id);
bgp_instance_up (bgp);
}
/* Update any redistribute vrf bitmaps if the vrf_id changed */
if (old_vrf_id != bgp->vrf_id)
bgp_update_redist_vrf_bitmaps(bgp, old_vrf_id);
bgp_instance_up(bgp);
}
return 0;
return 0;
}
static int
bgp_vrf_disable (struct vrf *vrf)
static int bgp_vrf_disable(struct vrf *vrf)
{
struct bgp *bgp;
vrf_id_t old_vrf_id;
struct bgp *bgp;
vrf_id_t old_vrf_id;
if (vrf->vrf_id == VRF_DEFAULT)
return 0;
if (vrf->vrf_id == VRF_DEFAULT)
return 0;
if (BGP_DEBUG (zebra, ZEBRA))
zlog_debug("VRF disable %s id %d", vrf->name, vrf->vrf_id);
if (BGP_DEBUG(zebra, ZEBRA))
zlog_debug("VRF disable %s id %d", vrf->name, vrf->vrf_id);
bgp = bgp_lookup_by_name (vrf->name);
if (bgp)
{
old_vrf_id = bgp->vrf_id;
/* We have instance configured, unlink from VRF and make it "down". */
bgp_vrf_unlink (bgp, vrf);
/* Update any redistribute vrf bitmaps if the vrf_id changed */
if (old_vrf_id != bgp->vrf_id)
bgp_update_redist_vrf_bitmaps(bgp, old_vrf_id);
bgp_instance_down (bgp);
}
bgp = bgp_lookup_by_name(vrf->name);
if (bgp) {
old_vrf_id = bgp->vrf_id;
/* We have instance configured, unlink from VRF and make it
* "down". */
bgp_vrf_unlink(bgp, vrf);
/* Update any redistribute vrf bitmaps if the vrf_id changed */
if (old_vrf_id != bgp->vrf_id)
bgp_update_redist_vrf_bitmaps(bgp, old_vrf_id);
bgp_instance_down(bgp);
}
/* Note: This is a callback, the VRF will be deleted by the caller. */
return 0;
/* Note: This is a callback, the VRF will be deleted by the caller. */
return 0;
}
static void
bgp_vrf_init (void)
static void bgp_vrf_init(void)
{
vrf_init (bgp_vrf_new,
bgp_vrf_enable,
bgp_vrf_disable,
bgp_vrf_delete);
vrf_init(bgp_vrf_new, bgp_vrf_enable, bgp_vrf_disable, bgp_vrf_delete);
}
static void
bgp_vrf_terminate (void)
static void bgp_vrf_terminate(void)
{
vrf_terminate ();
vrf_terminate();
}
FRR_DAEMON_INFO(bgpd, BGP,
.vty_port = BGP_VTY_PORT,
FRR_DAEMON_INFO(bgpd, BGP, .vty_port = BGP_VTY_PORT,
.proghelp = "Implementation of the BGP routing protocol.",
.proghelp = "Implementation of the BGP routing protocol.",
.signals = bgp_signals,
.n_signals = array_size(bgp_signals),
.signals = bgp_signals, .n_signals = array_size(bgp_signals),
.privs = &bgpd_privs,
)
.privs = &bgpd_privs, )
/* Main routine of bgpd. Treatment of argument and start bgp finite
state machine is handled at here. */
int
main (int argc, char **argv)
int main(int argc, char **argv)
{
int opt;
int tmp_port;
int opt;
int tmp_port;
int bgp_port = BGP_PORT_DEFAULT;
char *bgp_address = NULL;
int no_fib_flag = 0;
int skip_runas = 0;
int bgp_port = BGP_PORT_DEFAULT;
char *bgp_address = NULL;
int no_fib_flag = 0;
int skip_runas = 0;
frr_preinit(&bgpd_di, argc, argv);
frr_opt_add("p:l:rne:", longopts,
" -p, --bgp_port Set bgp protocol's port number\n"
" -l, --listenon Listen on specified address (implies -n)\n"
" -r, --retain When program terminates, retain added route by bgpd.\n"
" -n, --no_kernel Do not install route to kernel.\n"
" -S, --skip_runas Skip capabilities checks, and changing user and group IDs.\n"
" -e, --ecmp Specify ECMP to use.\n");
frr_preinit(&bgpd_di, argc, argv);
frr_opt_add(
"p:l:rne:", longopts,
" -p, --bgp_port Set bgp protocol's port number\n"
" -l, --listenon Listen on specified address (implies -n)\n"
" -r, --retain When program terminates, retain added route by bgpd.\n"
" -n, --no_kernel Do not install route to kernel.\n"
" -S, --skip_runas Skip capabilities checks, and changing user and group IDs.\n"
" -e, --ecmp Specify ECMP to use.\n");
/* Command line argument treatment. */
while (1)
{
opt = frr_getopt (argc, argv, 0);
if (opt == EOF)
break;
/* Command line argument treatment. */
while (1) {
opt = frr_getopt(argc, argv, 0);
switch (opt)
{
case 0:
break;
case 'p':
tmp_port = atoi (optarg);
if (tmp_port <= 0 || tmp_port > 0xffff)
bgp_port = BGP_PORT_DEFAULT;
else
bgp_port = tmp_port;
break;
case 'e':
multipath_num = atoi (optarg);
if (multipath_num > MULTIPATH_NUM || multipath_num <= 0)
{
zlog_err ("Multipath Number specified must be less than %d and greater than 0", MULTIPATH_NUM);
return 1;
}
break;
case 'r':
retain_mode = 1;
break;
case 'l':
bgp_address = optarg;
/* listenon implies -n */
case 'n':
no_fib_flag = 1;
break;
case 'S':
skip_runas = 1;
break;
default:
frr_help_exit (1);
break;
if (opt == EOF)
break;
switch (opt) {
case 0:
break;
case 'p':
tmp_port = atoi(optarg);
if (tmp_port <= 0 || tmp_port > 0xffff)
bgp_port = BGP_PORT_DEFAULT;
else
bgp_port = tmp_port;
break;
case 'e':
multipath_num = atoi(optarg);
if (multipath_num > MULTIPATH_NUM
|| multipath_num <= 0) {
zlog_err(
"Multipath Number specified must be less than %d and greater than 0",
MULTIPATH_NUM);
return 1;
}
break;
case 'r':
retain_mode = 1;
break;
case 'l':
bgp_address = optarg;
/* listenon implies -n */
/* fallthru */
case 'n':
no_fib_flag = 1;
break;
case 'S':
skip_runas = 1;
break;
default:
frr_help_exit(1);
break;
}
}
}
if (skip_runas)
memset (&bgpd_privs, 0, sizeof (bgpd_privs));
if (skip_runas)
memset(&bgpd_privs, 0, sizeof(bgpd_privs));
/* BGP master init. */
bgp_master_init (frr_init ());
bm->port = bgp_port;
bm->address = bgp_address;
if (no_fib_flag)
bgp_option_set (BGP_OPT_NO_FIB);
/* BGP master init. */
bgp_master_init(frr_init());
bm->port = bgp_port;
bm->address = bgp_address;
if (no_fib_flag)
bgp_option_set(BGP_OPT_NO_FIB);
/* Initializations. */
bgp_vrf_init ();
/* Initializations. */
bgp_vrf_init();
/* BGP related initialization. */
bgp_init ();
/* BGP related initialization. */
bgp_init();
snprintf (bgpd_di.startinfo, sizeof (bgpd_di.startinfo), ", bgp@%s:%d",
(bm->address ? bm->address : "<all>"),
bm->port);
snprintf(bgpd_di.startinfo, sizeof(bgpd_di.startinfo), ", bgp@%s:%d",
(bm->address ? bm->address : "<all>"), bm->port);
frr_config_fork ();
frr_run (bm->master);
frr_config_fork();
frr_run(bm->master);
/* Not reached. */
return (0);
/* Not reached. */
return (0);
}

View File

@ -29,88 +29,91 @@
* files they're used in */
DEFINE_MGROUP(BGPD, "bgpd")
DEFINE_MTYPE(BGPD, BGP, "BGP instance")
DEFINE_MTYPE(BGPD, BGP_LISTENER, "BGP listen socket details")
DEFINE_MTYPE(BGPD, BGP_PEER, "BGP peer")
DEFINE_MTYPE(BGPD, BGP_PEER_HOST, "BGP peer hostname")
DEFINE_MTYPE(BGPD, BGP_PEER_IFNAME, "BGP peer ifname")
DEFINE_MTYPE(BGPD, PEER_GROUP, "Peer group")
DEFINE_MTYPE(BGPD, PEER_GROUP_HOST, "BGP Peer group hostname")
DEFINE_MTYPE(BGPD, PEER_DESC, "Peer description")
DEFINE_MTYPE(BGPD, PEER_PASSWORD, "Peer password string")
DEFINE_MTYPE(BGPD, BGP_PEER_AF, "BGP peer af")
DEFINE_MTYPE(BGPD, BGP_UPDGRP, "BGP update group")
DEFINE_MTYPE(BGPD, BGP_UPD_SUBGRP, "BGP update subgroup")
DEFINE_MTYPE(BGPD, BGP_PACKET, "BGP packet")
DEFINE_MTYPE(BGPD, ATTR, "BGP attribute")
DEFINE_MTYPE(BGPD, ATTR_EXTRA, "BGP extra attributes")
DEFINE_MTYPE(BGPD, AS_PATH, "BGP aspath")
DEFINE_MTYPE(BGPD, AS_SEG, "BGP aspath seg")
DEFINE_MTYPE(BGPD, AS_SEG_DATA, "BGP aspath segment data")
DEFINE_MTYPE(BGPD, AS_STR, "BGP aspath str")
DEFINE_MTYPE(BGPD, BGP, "BGP instance")
DEFINE_MTYPE(BGPD, BGP_LISTENER, "BGP listen socket details")
DEFINE_MTYPE(BGPD, BGP_PEER, "BGP peer")
DEFINE_MTYPE(BGPD, BGP_PEER_HOST, "BGP peer hostname")
DEFINE_MTYPE(BGPD, BGP_PEER_IFNAME, "BGP peer ifname")
DEFINE_MTYPE(BGPD, PEER_GROUP, "Peer group")
DEFINE_MTYPE(BGPD, PEER_GROUP_HOST, "BGP Peer group hostname")
DEFINE_MTYPE(BGPD, PEER_DESC, "Peer description")
DEFINE_MTYPE(BGPD, PEER_PASSWORD, "Peer password string")
DEFINE_MTYPE(BGPD, BGP_PEER_AF, "BGP peer af")
DEFINE_MTYPE(BGPD, BGP_UPDGRP, "BGP update group")
DEFINE_MTYPE(BGPD, BGP_UPD_SUBGRP, "BGP update subgroup")
DEFINE_MTYPE(BGPD, BGP_PACKET, "BGP packet")
DEFINE_MTYPE(BGPD, ATTR, "BGP attribute")
DEFINE_MTYPE(BGPD, AS_PATH, "BGP aspath")
DEFINE_MTYPE(BGPD, AS_SEG, "BGP aspath seg")
DEFINE_MTYPE(BGPD, AS_SEG_DATA, "BGP aspath segment data")
DEFINE_MTYPE(BGPD, AS_STR, "BGP aspath str")
DEFINE_MTYPE(BGPD, BGP_TABLE, "BGP table")
DEFINE_MTYPE(BGPD, BGP_NODE, "BGP node")
DEFINE_MTYPE(BGPD, BGP_ROUTE, "BGP route")
DEFINE_MTYPE(BGPD, BGP_ROUTE_EXTRA, "BGP ancillary route info")
DEFINE_MTYPE(BGPD, BGP_CONN, "BGP connected")
DEFINE_MTYPE(BGPD, BGP_STATIC, "BGP static")
DEFINE_MTYPE(BGPD, BGP_ADVERTISE_ATTR, "BGP adv attr")
DEFINE_MTYPE(BGPD, BGP_ADVERTISE, "BGP adv")
DEFINE_MTYPE(BGPD, BGP_SYNCHRONISE, "BGP synchronise")
DEFINE_MTYPE(BGPD, BGP_ADJ_IN, "BGP adj in")
DEFINE_MTYPE(BGPD, BGP_ADJ_OUT, "BGP adj out")
DEFINE_MTYPE(BGPD, BGP_MPATH_INFO, "BGP multipath info")
DEFINE_MTYPE(BGPD, BGP_TABLE, "BGP table")
DEFINE_MTYPE(BGPD, BGP_NODE, "BGP node")
DEFINE_MTYPE(BGPD, BGP_ROUTE, "BGP route")
DEFINE_MTYPE(BGPD, BGP_ROUTE_EXTRA, "BGP ancillary route info")
DEFINE_MTYPE(BGPD, BGP_CONN, "BGP connected")
DEFINE_MTYPE(BGPD, BGP_STATIC, "BGP static")
DEFINE_MTYPE(BGPD, BGP_ADVERTISE_ATTR, "BGP adv attr")
DEFINE_MTYPE(BGPD, BGP_ADVERTISE, "BGP adv")
DEFINE_MTYPE(BGPD, BGP_SYNCHRONISE, "BGP synchronise")
DEFINE_MTYPE(BGPD, BGP_ADJ_IN, "BGP adj in")
DEFINE_MTYPE(BGPD, BGP_ADJ_OUT, "BGP adj out")
DEFINE_MTYPE(BGPD, BGP_MPATH_INFO, "BGP multipath info")
DEFINE_MTYPE(BGPD, AS_LIST, "BGP AS list")
DEFINE_MTYPE(BGPD, AS_FILTER, "BGP AS filter")
DEFINE_MTYPE(BGPD, AS_FILTER_STR, "BGP AS filter str")
DEFINE_MTYPE(BGPD, AS_LIST, "BGP AS list")
DEFINE_MTYPE(BGPD, AS_FILTER, "BGP AS filter")
DEFINE_MTYPE(BGPD, AS_FILTER_STR, "BGP AS filter str")
DEFINE_MTYPE(BGPD, COMMUNITY, "community")
DEFINE_MTYPE(BGPD, COMMUNITY_VAL, "community val")
DEFINE_MTYPE(BGPD, COMMUNITY_STR, "community str")
DEFINE_MTYPE(BGPD, COMMUNITY, "community")
DEFINE_MTYPE(BGPD, COMMUNITY_VAL, "community val")
DEFINE_MTYPE(BGPD, COMMUNITY_STR, "community str")
DEFINE_MTYPE(BGPD, ECOMMUNITY, "extcommunity")
DEFINE_MTYPE(BGPD, ECOMMUNITY_VAL, "extcommunity val")
DEFINE_MTYPE(BGPD, ECOMMUNITY_STR, "extcommunity str")
DEFINE_MTYPE(BGPD, ECOMMUNITY, "extcommunity")
DEFINE_MTYPE(BGPD, ECOMMUNITY_VAL, "extcommunity val")
DEFINE_MTYPE(BGPD, ECOMMUNITY_STR, "extcommunity str")
DEFINE_MTYPE(BGPD, COMMUNITY_LIST, "community-list")
DEFINE_MTYPE(BGPD, COMMUNITY_LIST_NAME, "community-list name")
DEFINE_MTYPE(BGPD, COMMUNITY_LIST_ENTRY, "community-list entry")
DEFINE_MTYPE(BGPD, COMMUNITY_LIST_CONFIG, "community-list config")
DEFINE_MTYPE(BGPD, COMMUNITY_LIST_HANDLER, "community-list handler")
DEFINE_MTYPE(BGPD, COMMUNITY_LIST, "community-list")
DEFINE_MTYPE(BGPD, COMMUNITY_LIST_NAME, "community-list name")
DEFINE_MTYPE(BGPD, COMMUNITY_LIST_ENTRY, "community-list entry")
DEFINE_MTYPE(BGPD, COMMUNITY_LIST_CONFIG, "community-list config")
DEFINE_MTYPE(BGPD, COMMUNITY_LIST_HANDLER, "community-list handler")
DEFINE_MTYPE(BGPD, CLUSTER, "Cluster list")
DEFINE_MTYPE(BGPD, CLUSTER_VAL, "Cluster list val")
DEFINE_MTYPE(BGPD, CLUSTER, "Cluster list")
DEFINE_MTYPE(BGPD, CLUSTER_VAL, "Cluster list val")
DEFINE_MTYPE(BGPD, BGP_PROCESS_QUEUE, "BGP Process queue")
DEFINE_MTYPE(BGPD, BGP_CLEAR_NODE_QUEUE, "BGP node clear queue")
DEFINE_MTYPE(BGPD, BGP_PROCESS_QUEUE, "BGP Process queue")
DEFINE_MTYPE(BGPD, BGP_CLEAR_NODE_QUEUE, "BGP node clear queue")
DEFINE_MTYPE(BGPD, TRANSIT, "BGP transit attr")
DEFINE_MTYPE(BGPD, TRANSIT_VAL, "BGP transit val")
DEFINE_MTYPE(BGPD, TRANSIT, "BGP transit attr")
DEFINE_MTYPE(BGPD, TRANSIT_VAL, "BGP transit val")
DEFINE_MTYPE(BGPD, BGP_DEBUG_FILTER, "BGP debug filter")
DEFINE_MTYPE(BGPD, BGP_DEBUG_STR, "BGP debug filter string")
DEFINE_MTYPE(BGPD, BGP_DEBUG_FILTER, "BGP debug filter")
DEFINE_MTYPE(BGPD, BGP_DEBUG_STR, "BGP debug filter string")
DEFINE_MTYPE(BGPD, BGP_DISTANCE, "BGP distance")
DEFINE_MTYPE(BGPD, BGP_NEXTHOP_CACHE, "BGP nexthop")
DEFINE_MTYPE(BGPD, BGP_CONFED_LIST, "BGP confed list")
DEFINE_MTYPE(BGPD, PEER_UPDATE_SOURCE, "BGP peer update interface")
DEFINE_MTYPE(BGPD, PEER_CONF_IF, "BGP peer config interface")
DEFINE_MTYPE(BGPD, BGP_DAMP_INFO, "Dampening info")
DEFINE_MTYPE(BGPD, BGP_DAMP_ARRAY, "BGP Dampening array")
DEFINE_MTYPE(BGPD, BGP_REGEXP, "BGP regexp")
DEFINE_MTYPE(BGPD, BGP_AGGREGATE, "BGP aggregate")
DEFINE_MTYPE(BGPD, BGP_ADDR, "BGP own address")
DEFINE_MTYPE(BGPD, BGP_DISTANCE, "BGP distance")
DEFINE_MTYPE(BGPD, BGP_NEXTHOP_CACHE, "BGP nexthop")
DEFINE_MTYPE(BGPD, BGP_CONFED_LIST, "BGP confed list")
DEFINE_MTYPE(BGPD, PEER_UPDATE_SOURCE, "BGP peer update interface")
DEFINE_MTYPE(BGPD, PEER_CONF_IF, "BGP peer config interface")
DEFINE_MTYPE(BGPD, BGP_DAMP_INFO, "Dampening info")
DEFINE_MTYPE(BGPD, BGP_DAMP_ARRAY, "BGP Dampening array")
DEFINE_MTYPE(BGPD, BGP_REGEXP, "BGP regexp")
DEFINE_MTYPE(BGPD, BGP_AGGREGATE, "BGP aggregate")
DEFINE_MTYPE(BGPD, BGP_ADDR, "BGP own address")
DEFINE_MTYPE(BGPD, BGP_REDIST, "BGP redistribution")
DEFINE_MTYPE(BGPD, BGP_FILTER_NAME, "BGP Filter Information")
DEFINE_MTYPE(BGPD, BGP_DUMP_STR, "BGP Dump String Information")
DEFINE_MTYPE(BGPD, ENCAP_TLV, "ENCAP TLV")
DEFINE_MTYPE(BGPD, BGP_REDIST, "BGP redistribution")
DEFINE_MTYPE(BGPD, BGP_FILTER_NAME, "BGP Filter Information")
DEFINE_MTYPE(BGPD, BGP_DUMP_STR, "BGP Dump String Information")
DEFINE_MTYPE(BGPD, ENCAP_TLV, "ENCAP TLV")
DEFINE_MTYPE(BGPD, BGP_TEA_OPTIONS, "BGP TEA Options")
DEFINE_MTYPE(BGPD, BGP_TEA_OPTIONS, "BGP TEA Options")
DEFINE_MTYPE(BGPD, BGP_TEA_OPTIONS_VALUE, "BGP TEA Options Value")
DEFINE_MTYPE(BGPD, LCOMMUNITY, "Large Community")
DEFINE_MTYPE(BGPD, LCOMMUNITY_STR, "Large Community display string")
DEFINE_MTYPE(BGPD, LCOMMUNITY_VAL, "Large Community value")
DEFINE_MTYPE(BGPD, BGP_EVPN, "BGP EVPN Information")
DEFINE_MTYPE(BGPD, BGP_EVPN_IMPORT_RT, "BGP EVPN Import RT")
DEFINE_MTYPE(BGPD, BGP_EVPN_MACIP, "BGP EVPN MAC IP")

View File

@ -39,7 +39,6 @@ DECLARE_MTYPE(BGP_UPDGRP)
DECLARE_MTYPE(BGP_UPD_SUBGRP)
DECLARE_MTYPE(BGP_PACKET)
DECLARE_MTYPE(ATTR)
DECLARE_MTYPE(ATTR_EXTRA)
DECLARE_MTYPE(AS_PATH)
DECLARE_MTYPE(AS_SEG)
DECLARE_MTYPE(AS_SEG_DATA)
@ -110,4 +109,8 @@ DECLARE_MTYPE(BGP_TEA_OPTIONS_VALUE)
DECLARE_MTYPE(LCOMMUNITY)
DECLARE_MTYPE(LCOMMUNITY_STR)
DECLARE_MTYPE(LCOMMUNITY_VAL)
DECLARE_MTYPE(BGP_EVPN)
DECLARE_MTYPE(BGP_EVPN_IMPORT_RT)
DECLARE_MTYPE(BGP_EVPN_MACIP)
#endif /* _QUAGGA_BGP_MEMORY_H */

File diff suppressed because it is too large Load Diff

View File

@ -25,53 +25,52 @@
/* Supplemental information linked to bgp_info for keeping track of
* multipath selections, lazily allocated to save memory
*/
struct bgp_info_mpath
{
/* Points to the first multipath (on bestpath) or the next multipath */
struct bgp_info_mpath *mp_next;
struct bgp_info_mpath {
/* Points to the first multipath (on bestpath) or the next multipath */
struct bgp_info_mpath *mp_next;
/* Points to the previous multipath or NULL on bestpath */
struct bgp_info_mpath *mp_prev;
/* Points to the previous multipath or NULL on bestpath */
struct bgp_info_mpath *mp_prev;
/* Points to bgp_info associated with this multipath info */
struct bgp_info *mp_info;
/* Points to bgp_info associated with this multipath info */
struct bgp_info *mp_info;
/* When attached to best path, the number of selected multipaths */
u_int32_t mp_count;
/* When attached to best path, the number of selected multipaths */
u_int32_t mp_count;
/* Aggregated attribute for advertising multipath route */
struct attr *mp_attr;
/* Aggregated attribute for advertising multipath route */
struct attr *mp_attr;
};
/* Functions to support maximum-paths configuration */
extern int bgp_maximum_paths_set (struct bgp *, afi_t, safi_t, int, u_int16_t,
u_int16_t);
extern int bgp_maximum_paths_unset (struct bgp *, afi_t, safi_t, int);
extern int bgp_maximum_paths_set(struct bgp *, afi_t, safi_t, int, u_int16_t,
u_int16_t);
extern int bgp_maximum_paths_unset(struct bgp *, afi_t, safi_t, int);
/* Functions used by bgp_best_selection to record current
* multipath selections
*/
extern int bgp_info_nexthop_cmp (struct bgp_info *bi1, struct bgp_info *bi2);
extern void bgp_mp_list_init (struct list *);
extern void bgp_mp_list_clear (struct list *);
extern void bgp_mp_list_add (struct list *, struct bgp_info *);
extern void bgp_mp_dmed_deselect (struct bgp_info *);
extern void bgp_info_mpath_update (struct bgp_node *, struct bgp_info *,
struct bgp_info *, struct list *,
struct bgp_maxpaths_cfg *);
extern void bgp_info_mpath_aggregate_update (struct bgp_info *,
struct bgp_info *);
extern int bgp_info_nexthop_cmp(struct bgp_info *bi1, struct bgp_info *bi2);
extern void bgp_mp_list_init(struct list *);
extern void bgp_mp_list_clear(struct list *);
extern void bgp_mp_list_add(struct list *, struct bgp_info *);
extern void bgp_mp_dmed_deselect(struct bgp_info *);
extern void bgp_info_mpath_update(struct bgp_node *, struct bgp_info *,
struct bgp_info *, struct list *,
struct bgp_maxpaths_cfg *);
extern void bgp_info_mpath_aggregate_update(struct bgp_info *,
struct bgp_info *);
/* Unlink and free multipath information associated with a bgp_info */
extern void bgp_info_mpath_dequeue (struct bgp_info *);
extern void bgp_info_mpath_free (struct bgp_info_mpath **);
extern void bgp_info_mpath_dequeue(struct bgp_info *);
extern void bgp_info_mpath_free(struct bgp_info_mpath **);
/* Walk list of multipaths associated with a best path */
extern struct bgp_info *bgp_info_mpath_first (struct bgp_info *);
extern struct bgp_info *bgp_info_mpath_next (struct bgp_info *);
extern struct bgp_info *bgp_info_mpath_first(struct bgp_info *);
extern struct bgp_info *bgp_info_mpath_next(struct bgp_info *);
/* Accessors for multipath information */
extern u_int32_t bgp_info_mpath_count (struct bgp_info *);
extern struct attr *bgp_info_mpath_attr (struct bgp_info *);
extern u_int32_t bgp_info_mpath_count(struct bgp_info *);
extern struct attr *bgp_info_mpath_attr(struct bgp_info *);
#endif /* _QUAGGA_BGP_MPATH_H */

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,7 @@
/* MPLS-VPN
* Copyright (C) 2000 Kunihiro Ishiguro <kunihiro@zebra.org>
*
* This file is part of GNU Zebra.
* This file is part of GxNU Zebra.
*
* GNU Zebra is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
@ -22,100 +22,57 @@
#define _QUAGGA_BGP_MPLSVPN_H
#include "bgpd/bgp_route.h"
#define RD_TYPE_AS 0
#define RD_TYPE_IP 1
#define RD_TYPE_AS4 2
#if ENABLE_BGP_VNC
#define RD_TYPE_VNC_ETH 0xff00 /* VNC L2VPN */
#endif
#define RD_ADDRSTRLEN 28
#include "bgpd/bgp_rd.h"
#ifdef MPLS_LABEL_MAX
# undef MPLS_LABEL_MAX
#undef MPLS_LABEL_MAX
#endif
typedef enum {
MPLS_LABEL_IPV4_EXPLICIT_NULL = 0, /* [RFC3032] */
MPLS_LABEL_ROUTER_ALERT = 1, /* [RFC3032] */
MPLS_LABEL_IPV6_EXPLICIT_NULL = 2, /* [RFC3032] */
MPLS_LABEL_IMPLICIT_NULL = 3, /* [RFC3032] */
MPLS_LABEL_UNASSIGNED4 = 4,
MPLS_LABEL_UNASSIGNED5 = 5,
MPLS_LABEL_UNASSIGNED6 = 6,
MPLS_LABEL_ELI = 7, /* Entropy Indicator [RFC6790] */
MPLS_LABEL_UNASSIGNED8 = 8,
MPLS_LABEL_UNASSIGNED9 = 9,
MPLS_LABEL_UNASSIGNED10 = 10,
MPLS_LABEL_UNASSIGNED11 = 11,
MPLS_LABEL_GAL = 13, /* [RFC5586] */
MPLS_LABEL_OAM_ALERT = 14, /* [RFC3429] */
MPLS_LABEL_EXTENSION = 15, /* [RFC7274] */
MPLS_LABEL_MAX = 1048575,
MPLS_LABEL_ILLEGAL = 0xFFFFFFFF /* for internal use only */
MPLS_LABEL_IPV4_EXPLICIT_NULL = 0, /* [RFC3032] */
MPLS_LABEL_ROUTER_ALERT = 1, /* [RFC3032] */
MPLS_LABEL_IPV6_EXPLICIT_NULL = 2, /* [RFC3032] */
MPLS_LABEL_IMPLICIT_NULL = 3, /* [RFC3032] */
MPLS_LABEL_UNASSIGNED4 = 4,
MPLS_LABEL_UNASSIGNED5 = 5,
MPLS_LABEL_UNASSIGNED6 = 6,
MPLS_LABEL_ELI = 7, /* Entropy Indicator [RFC6790] */
MPLS_LABEL_UNASSIGNED8 = 8,
MPLS_LABEL_UNASSIGNED9 = 9,
MPLS_LABEL_UNASSIGNED10 = 10,
MPLS_LABEL_UNASSIGNED11 = 11,
MPLS_LABEL_GAL = 13, /* [RFC5586] */
MPLS_LABEL_OAM_ALERT = 14, /* [RFC3429] */
MPLS_LABEL_EXTENSION = 15, /* [RFC7274] */
MPLS_LABEL_MAX = 1048575,
MPLS_LABEL_ILLEGAL = 0xFFFFFFFF /* for internal use only */
} mpls_special_label_t;
#define MPLS_LABEL_IS_SPECIAL(label) \
((label) <= MPLS_LABEL_EXTENSION)
#define MPLS_LABEL_IS_NULL(label) \
((label) == MPLS_LABEL_IPV4_EXPLICIT_NULL || \
(label) == MPLS_LABEL_IPV6_EXPLICIT_NULL || \
(label) == MPLS_LABEL_IMPLICIT_NULL)
#define MPLS_LABEL_IS_SPECIAL(label) ((label) <= MPLS_LABEL_EXTENSION)
#define MPLS_LABEL_IS_NULL(label) \
((label) == MPLS_LABEL_IPV4_EXPLICIT_NULL \
|| (label) == MPLS_LABEL_IPV6_EXPLICIT_NULL \
|| (label) == MPLS_LABEL_IMPLICIT_NULL)
#define BGP_VPNVX_HELP_STR \
"Address Family\n" \
"Address Family\n"
#define BGP_VPNVX_HELP_STR \
"Address Family\n" \
"Address Family\n"
#define V4_HEADER \
" Network Next Hop Metric LocPrf Weight Path"
#define V4_HEADER_TAG \
" Network Next Hop In tag/Out tag"
#define V4_HEADER_OVERLAY \
" Network Next Hop EthTag Overlay Index RouterMac"
#define V4_HEADER \
" Network Next Hop Metric LocPrf Weight Path\n"
#define V4_HEADER_TAG " Network Next Hop In tag/Out tag\n"
#define V4_HEADER_OVERLAY \
" Network Next Hop EthTag Overlay Index RouterMac\n"
struct rd_as
{
u_int16_t type;
as_t as;
u_int32_t val;
};
extern void bgp_mplsvpn_init(void);
extern int bgp_nlri_parse_vpn(struct peer *, struct attr *, struct bgp_nlri *);
extern u_int32_t decode_label(mpls_label_t *);
extern void encode_label(mpls_label_t, mpls_label_t *);
struct rd_ip
{
u_int16_t type;
struct in_addr ip;
u_int16_t val;
};
#if ENABLE_BGP_VNC
struct rd_vnc_eth
{
u_int16_t type;
uint8_t local_nve_id;
struct ethaddr macaddr;
};
#endif
extern u_int16_t decode_rd_type (u_char *);
extern void encode_rd_type (u_int16_t, u_char *);
extern void bgp_mplsvpn_init (void);
extern int bgp_nlri_parse_vpn (struct peer *, struct attr *, struct bgp_nlri *);
extern u_int32_t decode_label (u_char *);
extern void encode_label(u_int32_t, u_char *);
extern void decode_rd_as (u_char *, struct rd_as *);
extern void decode_rd_as4 (u_char *, struct rd_as *);
extern void decode_rd_ip (u_char *, struct rd_ip *);
#if ENABLE_BGP_VNC
extern void
decode_rd_vnc_eth (u_char *pnt, struct rd_vnc_eth *rd_vnc_eth);
#endif
extern int str2prefix_rd (const char *, struct prefix_rd *);
extern char *prefix_rd2str (struct prefix_rd *, char *, size_t);
extern int
argv_find_and_parse_vpnvx(struct cmd_token **argv, int argc, int *index, afi_t *afi);
extern int bgp_show_mpls_vpn (struct vty *vty, afi_t afi, struct prefix_rd *prd,
enum bgp_show_type type, void *output_arg, int tags, u_char use_json);
extern int argv_find_and_parse_vpnvx(struct cmd_token **argv, int argc,
int *index, afi_t *afi);
extern int bgp_show_mpls_vpn(struct vty *vty, afi_t afi, struct prefix_rd *prd,
enum bgp_show_type type, void *output_arg,
int tags, u_char use_json);
#endif /* _QUAGGA_BGP_MPLSVPN_H */

File diff suppressed because it is too large Load Diff

View File

@ -23,13 +23,13 @@
#define BGP_SOCKET_SNDBUF_SIZE 65536
extern int bgp_socket (unsigned short, const char *);
extern void bgp_close (void);
extern int bgp_connect (struct peer *);
extern int bgp_getsockname (struct peer *);
extern int bgp_socket(unsigned short, const char *);
extern void bgp_close(void);
extern int bgp_connect(struct peer *);
extern int bgp_getsockname(struct peer *);
extern int bgp_md5_set (struct peer *);
extern int bgp_md5_unset (struct peer *);
extern int bgp_md5_set(struct peer *);
extern int bgp_md5_unset(struct peer *);
extern int bgp_set_socket_ttl(struct peer *, int fd);
#endif /* _QUAGGA_BGP_NETWORK_H */

View File

@ -45,444 +45,445 @@
#include "bgpd/bgp_fsm.h"
#include "bgpd/bgp_vty.h"
#include "zebra/rib.h"
#include "zebra/zserv.h" /* For ZEBRA_SERV_PATH. */
#include "zebra/zserv.h" /* For ZEBRA_SERV_PATH. */
char *
bnc_str (struct bgp_nexthop_cache *bnc, char *buf, int size)
char *bnc_str(struct bgp_nexthop_cache *bnc, char *buf, int size)
{
prefix2str(&(bnc->node->p), buf, size);
return buf;
prefix2str(&(bnc->node->p), buf, size);
return buf;
}
void
bnc_nexthop_free (struct bgp_nexthop_cache *bnc)
void bnc_nexthop_free(struct bgp_nexthop_cache *bnc)
{
nexthops_free(bnc->nexthop);
nexthops_free(bnc->nexthop);
}
struct bgp_nexthop_cache *
bnc_new (void)
struct bgp_nexthop_cache *bnc_new(void)
{
struct bgp_nexthop_cache *bnc;
struct bgp_nexthop_cache *bnc;
bnc = XCALLOC (MTYPE_BGP_NEXTHOP_CACHE, sizeof (struct bgp_nexthop_cache));
LIST_INIT(&(bnc->paths));
return bnc;
bnc = XCALLOC(MTYPE_BGP_NEXTHOP_CACHE,
sizeof(struct bgp_nexthop_cache));
LIST_INIT(&(bnc->paths));
return bnc;
}
void
bnc_free (struct bgp_nexthop_cache *bnc)
void bnc_free(struct bgp_nexthop_cache *bnc)
{
bnc_nexthop_free (bnc);
XFREE (MTYPE_BGP_NEXTHOP_CACHE, bnc);
bnc_nexthop_free(bnc);
XFREE(MTYPE_BGP_NEXTHOP_CACHE, bnc);
}
/* Reset and free all BGP nexthop cache. */
static void
bgp_nexthop_cache_reset (struct bgp_table *table)
static void bgp_nexthop_cache_reset(struct bgp_table *table)
{
struct bgp_node *rn;
struct bgp_nexthop_cache *bnc;
struct bgp_node *rn;
struct bgp_nexthop_cache *bnc;
for (rn = bgp_table_top (table); rn; rn = bgp_route_next (rn))
if ((bnc = rn->info) != NULL)
{
bnc_free (bnc);
rn->info = NULL;
bgp_unlock_node (rn);
}
for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn))
if ((bnc = rn->info) != NULL) {
bnc_free(bnc);
rn->info = NULL;
bgp_unlock_node(rn);
}
}
/* BGP own address structure */
struct bgp_addr
{
struct in_addr addr;
int refcnt;
struct bgp_addr {
struct in_addr addr;
int refcnt;
};
static void *
bgp_address_hash_alloc (void *p)
static void *bgp_address_hash_alloc(void *p)
{
const struct in_addr *val = (const struct in_addr *)p;
struct bgp_addr *addr;
const struct in_addr *val = (const struct in_addr *)p;
struct bgp_addr *addr;
addr = XMALLOC (MTYPE_BGP_ADDR, sizeof (struct bgp_addr));
addr->refcnt = 0;
addr->addr.s_addr = val->s_addr;
addr = XMALLOC(MTYPE_BGP_ADDR, sizeof(struct bgp_addr));
addr->refcnt = 0;
addr->addr.s_addr = val->s_addr;
return addr;
return addr;
}
static void
bgp_address_hash_free (void *addr)
static void bgp_address_hash_free(void *addr)
{
XFREE (MTYPE_BGP_ADDR, addr);
XFREE(MTYPE_BGP_ADDR, addr);
}
static unsigned int
bgp_address_hash_key_make (void *p)
static unsigned int bgp_address_hash_key_make(void *p)
{
const struct bgp_addr *addr = p;
const struct bgp_addr *addr = p;
return jhash_1word(addr->addr.s_addr, 0);
return jhash_1word(addr->addr.s_addr, 0);
}
static int
bgp_address_hash_cmp (const void *p1, const void *p2)
static int bgp_address_hash_cmp(const void *p1, const void *p2)
{
const struct bgp_addr *addr1 = p1;
const struct bgp_addr *addr2 = p2;
const struct bgp_addr *addr1 = p1;
const struct bgp_addr *addr2 = p2;
return addr1->addr.s_addr == addr2->addr.s_addr;
return addr1->addr.s_addr == addr2->addr.s_addr;
}
void
bgp_address_init (struct bgp *bgp)
void bgp_address_init(struct bgp *bgp)
{
bgp->address_hash = hash_create (bgp_address_hash_key_make,
bgp_address_hash_cmp, NULL);
bgp->address_hash = hash_create(bgp_address_hash_key_make,
bgp_address_hash_cmp, NULL);
}
void
bgp_address_destroy (struct bgp *bgp)
void bgp_address_destroy(struct bgp *bgp)
{
if (bgp->address_hash == NULL)
return;
hash_clean(bgp->address_hash, bgp_address_hash_free);
hash_free(bgp->address_hash);
bgp->address_hash = NULL;
if (bgp->address_hash == NULL)
return;
hash_clean(bgp->address_hash, bgp_address_hash_free);
hash_free(bgp->address_hash);
bgp->address_hash = NULL;
}
static void
bgp_address_add (struct bgp *bgp, struct prefix *p)
static void bgp_address_add(struct bgp *bgp, struct prefix *p)
{
struct bgp_addr tmp;
struct bgp_addr *addr;
struct bgp_addr tmp;
struct bgp_addr *addr;
tmp.addr = p->u.prefix4;
tmp.addr = p->u.prefix4;
addr = hash_get (bgp->address_hash, &tmp, bgp_address_hash_alloc);
if (!addr)
return;
addr = hash_get(bgp->address_hash, &tmp, bgp_address_hash_alloc);
if (!addr)
return;
addr->refcnt++;
addr->refcnt++;
}
static void
bgp_address_del (struct bgp *bgp, struct prefix *p)
static void bgp_address_del(struct bgp *bgp, struct prefix *p)
{
struct bgp_addr tmp;
struct bgp_addr *addr;
struct bgp_addr tmp;
struct bgp_addr *addr;
tmp.addr = p->u.prefix4;
tmp.addr = p->u.prefix4;
addr = hash_lookup (bgp->address_hash, &tmp);
/* may have been deleted earlier by bgp_interface_down() */
if (addr == NULL)
return;
addr = hash_lookup(bgp->address_hash, &tmp);
/* may have been deleted earlier by bgp_interface_down() */
if (addr == NULL)
return;
addr->refcnt--;
addr->refcnt--;
if (addr->refcnt == 0)
{
hash_release (bgp->address_hash, addr);
XFREE (MTYPE_BGP_ADDR, addr);
}
if (addr->refcnt == 0) {
hash_release(bgp->address_hash, addr);
XFREE(MTYPE_BGP_ADDR, addr);
}
}
struct bgp_connected_ref
{
unsigned int refcnt;
struct bgp_connected_ref {
unsigned int refcnt;
};
void
bgp_connected_add (struct bgp *bgp, struct connected *ifc)
void bgp_connected_add(struct bgp *bgp, struct connected *ifc)
{
struct prefix p;
struct prefix *addr;
struct bgp_node *rn;
struct bgp_connected_ref *bc;
struct listnode *node, *nnode;
struct peer *peer;
struct prefix p;
struct prefix *addr;
struct bgp_node *rn;
struct bgp_connected_ref *bc;
struct listnode *node, *nnode;
struct peer *peer;
addr = ifc->address;
addr = ifc->address;
p = *(CONNECTED_PREFIX(ifc));
if (addr->family == AF_INET)
{
apply_mask_ipv4 ((struct prefix_ipv4 *) &p);
p = *(CONNECTED_PREFIX(ifc));
if (addr->family == AF_INET) {
apply_mask_ipv4((struct prefix_ipv4 *)&p);
if (prefix_ipv4_any ((struct prefix_ipv4 *) &p))
return;
if (prefix_ipv4_any((struct prefix_ipv4 *)&p))
return;
bgp_address_add (bgp, addr);
bgp_address_add(bgp, addr);
rn = bgp_node_get (bgp->connected_table[AFI_IP], (struct prefix *) &p);
if (rn->info)
{
bc = rn->info;
bc->refcnt++;
}
else
{
bc = XCALLOC (MTYPE_BGP_CONN, sizeof (struct bgp_connected_ref));
bc->refcnt = 1;
rn->info = bc;
}
rn = bgp_node_get(bgp->connected_table[AFI_IP],
(struct prefix *)&p);
if (rn->info) {
bc = rn->info;
bc->refcnt++;
} else {
bc = XCALLOC(MTYPE_BGP_CONN,
sizeof(struct bgp_connected_ref));
bc->refcnt = 1;
rn->info = bc;
}
for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
{
if (peer->conf_if && (strcmp (peer->conf_if, ifc->ifp->name) == 0) &&
peer->status != Established &&
!CHECK_FLAG(peer->flags, PEER_FLAG_IFPEER_V6ONLY))
{
if (peer_active(peer))
BGP_EVENT_ADD (peer, BGP_Stop);
BGP_EVENT_ADD (peer, BGP_Start);
}
}
}
else if (addr->family == AF_INET6)
{
apply_mask_ipv6 ((struct prefix_ipv6 *) &p);
if (IN6_IS_ADDR_UNSPECIFIED (&p.u.prefix6))
return;
if (IN6_IS_ADDR_LINKLOCAL (&p.u.prefix6))
return;
rn = bgp_node_get (bgp->connected_table[AFI_IP6], (struct prefix *) &p);
if (rn->info)
{
bc = rn->info;
bc->refcnt++;
}
else
{
bc = XCALLOC (MTYPE_BGP_CONN, sizeof (struct bgp_connected_ref));
bc->refcnt = 1;
rn->info = bc;
}
}
}
void
bgp_connected_delete (struct bgp *bgp, struct connected *ifc)
{
struct prefix p;
struct prefix *addr;
struct bgp_node *rn;
struct bgp_connected_ref *bc;
addr = ifc->address;
p = *(CONNECTED_PREFIX(ifc));
if (addr->family == AF_INET)
{
apply_mask_ipv4 ((struct prefix_ipv4 *) &p);
if (prefix_ipv4_any ((struct prefix_ipv4 *) &p))
return;
bgp_address_del (bgp, addr);
rn = bgp_node_lookup (bgp->connected_table[AFI_IP], &p);
if (! rn)
return;
bc = rn->info;
bc->refcnt--;
if (bc->refcnt == 0)
{
XFREE (MTYPE_BGP_CONN, bc);
rn->info = NULL;
}
bgp_unlock_node (rn);
bgp_unlock_node (rn);
}
else if (addr->family == AF_INET6)
{
apply_mask_ipv6 ((struct prefix_ipv6 *) &p);
if (IN6_IS_ADDR_UNSPECIFIED (&p.u.prefix6))
return;
if (IN6_IS_ADDR_LINKLOCAL (&p.u.prefix6))
return;
rn = bgp_node_lookup (bgp->connected_table[AFI_IP6], (struct prefix *) &p);
if (! rn)
return;
bc = rn->info;
bc->refcnt--;
if (bc->refcnt == 0)
{
XFREE (MTYPE_BGP_CONN, bc);
rn->info = NULL;
}
bgp_unlock_node (rn);
bgp_unlock_node (rn);
}
}
int
bgp_nexthop_self (struct bgp *bgp, struct attr *attr)
{
struct bgp_addr tmp, *addr;
tmp.addr = attr->nexthop;
addr = hash_lookup (bgp->address_hash, &tmp);
if (addr)
return 1;
return 0;
}
int
bgp_multiaccess_check_v4 (struct in_addr nexthop, struct peer *peer)
{
struct bgp_node *rn1;
struct bgp_node *rn2;
struct prefix p;
int ret;
p.family = AF_INET;
p.prefixlen = IPV4_MAX_BITLEN;
p.u.prefix4 = nexthop;
rn1 = bgp_node_match (peer->bgp->connected_table[AFI_IP], &p);
if (!rn1)
return 0;
p.family = AF_INET;
p.prefixlen = IPV4_MAX_BITLEN;
p.u.prefix4 = peer->su.sin.sin_addr;
rn2 = bgp_node_match (peer->bgp->connected_table[AFI_IP], &p);
if (!rn2)
{
bgp_unlock_node(rn1);
return 0;
}
ret = (rn1 == rn2) ? 1 : 0;
bgp_unlock_node(rn1);
bgp_unlock_node(rn2);
return (ret);
}
static void
bgp_show_nexthops (struct vty *vty, struct bgp *bgp, int detail)
{
struct bgp_node *rn;
struct bgp_nexthop_cache *bnc;
char buf[PREFIX2STR_BUFFER];
struct nexthop *nexthop;
time_t tbuf;
afi_t afi;
vty_outln (vty, "Current BGP nexthop cache:");
for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
{
if (!bgp->nexthop_cache_table[afi])
continue;
for (rn = bgp_table_top (bgp->nexthop_cache_table[afi]); rn; rn = bgp_route_next (rn))
{
if ((bnc = rn->info) != NULL)
{
if (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_VALID))
{
vty_outln (vty, " %s valid [IGP metric %d], #paths %d",
inet_ntop (rn->p.family, &rn->p.u.prefix, buf, sizeof (buf)),
bnc->metric, bnc->path_count);
if (detail)
for (nexthop = bnc->nexthop; nexthop; nexthop = nexthop->next)
switch (nexthop->type)
{
case NEXTHOP_TYPE_IPV6:
vty_outln (vty, " gate %s",
inet_ntop(AF_INET6, &nexthop->gate.ipv6, buf, sizeof(buf)));
break;
case NEXTHOP_TYPE_IPV6_IFINDEX:
vty_outln (vty, " gate %s, if %s",
inet_ntop(AF_INET6, &nexthop->gate.ipv6, buf,
sizeof (buf)),
ifindex2ifname(nexthop->ifindex, bgp->vrf_id));
break;
case NEXTHOP_TYPE_IPV4:
vty_outln (vty, " gate %s",
inet_ntop(AF_INET, &nexthop->gate.ipv4, buf, sizeof(buf)));
break;
case NEXTHOP_TYPE_IFINDEX:
vty_outln (vty, " if %s",
ifindex2ifname(nexthop->ifindex, bgp->vrf_id));
break;
case NEXTHOP_TYPE_IPV4_IFINDEX:
vty_outln (vty, " gate %s, if %s",
inet_ntop(AF_INET, &nexthop->gate.ipv4, buf,
sizeof (buf)),
ifindex2ifname(nexthop->ifindex, bgp->vrf_id));
break;
default:
vty_outln (vty, " invalid nexthop type %u",
nexthop->type);
for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
if (peer->conf_if
&& (strcmp(peer->conf_if, ifc->ifp->name) == 0)
&& peer->status != Established
&& !CHECK_FLAG(peer->flags,
PEER_FLAG_IFPEER_V6ONLY)) {
if (peer_active(peer))
BGP_EVENT_ADD(peer, BGP_Stop);
BGP_EVENT_ADD(peer, BGP_Start);
}
}
else
{
vty_outln (vty, " %s invalid",
inet_ntop(rn->p.family, &rn->p.u.prefix, buf, sizeof(buf)));
if (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_CONNECTED))
vty_outln (vty, " Must be Connected");
} else if (addr->family == AF_INET6) {
apply_mask_ipv6((struct prefix_ipv6 *)&p);
if (IN6_IS_ADDR_UNSPECIFIED(&p.u.prefix6))
return;
if (IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6))
return;
rn = bgp_node_get(bgp->connected_table[AFI_IP6],
(struct prefix *)&p);
if (rn->info) {
bc = rn->info;
bc->refcnt++;
} else {
bc = XCALLOC(MTYPE_BGP_CONN,
sizeof(struct bgp_connected_ref));
bc->refcnt = 1;
rn->info = bc;
}
tbuf = time(NULL) - (bgp_clock() - bnc->last_update);
vty_out (vty, " Last update: %s", ctime(&tbuf));
vty_out (vty, VTYNL);
}
}
}
}
static int
show_ip_bgp_nexthop_table (struct vty *vty, const char *name, int detail)
void bgp_connected_delete(struct bgp *bgp, struct connected *ifc)
{
struct bgp *bgp;
struct prefix p;
struct prefix *addr;
struct bgp_node *rn;
struct bgp_connected_ref *bc;
if (name)
bgp = bgp_lookup_by_name (name);
else
bgp = bgp_get_default ();
if (!bgp)
{
vty_outln (vty, "%% No such BGP instance exist");
return CMD_WARNING;
}
addr = ifc->address;
bgp_show_nexthops (vty, bgp, detail);
p = *(CONNECTED_PREFIX(ifc));
if (addr->family == AF_INET) {
apply_mask_ipv4((struct prefix_ipv4 *)&p);
return CMD_SUCCESS;
if (prefix_ipv4_any((struct prefix_ipv4 *)&p))
return;
bgp_address_del(bgp, addr);
rn = bgp_node_lookup(bgp->connected_table[AFI_IP], &p);
if (!rn)
return;
bc = rn->info;
bc->refcnt--;
if (bc->refcnt == 0) {
XFREE(MTYPE_BGP_CONN, bc);
rn->info = NULL;
}
bgp_unlock_node(rn);
bgp_unlock_node(rn);
} else if (addr->family == AF_INET6) {
apply_mask_ipv6((struct prefix_ipv6 *)&p);
if (IN6_IS_ADDR_UNSPECIFIED(&p.u.prefix6))
return;
if (IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6))
return;
rn = bgp_node_lookup(bgp->connected_table[AFI_IP6],
(struct prefix *)&p);
if (!rn)
return;
bc = rn->info;
bc->refcnt--;
if (bc->refcnt == 0) {
XFREE(MTYPE_BGP_CONN, bc);
rn->info = NULL;
}
bgp_unlock_node(rn);
bgp_unlock_node(rn);
}
}
static void
bgp_show_all_instances_nexthops_vty (struct vty *vty)
int bgp_nexthop_self(struct bgp *bgp, struct in_addr nh_addr)
{
struct listnode *node, *nnode;
struct bgp *bgp;
struct bgp_addr tmp, *addr;
for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
{
vty_outln (vty, "%sInstance %s:",
VTYNL,
(bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) ? "Default" : bgp->name);
bgp_show_nexthops (vty, bgp, 0);
}
tmp.addr = nh_addr;
addr = hash_lookup(bgp->address_hash, &tmp);
if (addr)
return 1;
return 0;
}
int bgp_multiaccess_check_v4(struct in_addr nexthop, struct peer *peer)
{
struct bgp_node *rn1;
struct bgp_node *rn2;
struct prefix p;
int ret;
p.family = AF_INET;
p.prefixlen = IPV4_MAX_BITLEN;
p.u.prefix4 = nexthop;
rn1 = bgp_node_match(peer->bgp->connected_table[AFI_IP], &p);
if (!rn1)
return 0;
p.family = AF_INET;
p.prefixlen = IPV4_MAX_BITLEN;
p.u.prefix4 = peer->su.sin.sin_addr;
rn2 = bgp_node_match(peer->bgp->connected_table[AFI_IP], &p);
if (!rn2) {
bgp_unlock_node(rn1);
return 0;
}
ret = (rn1 == rn2) ? 1 : 0;
bgp_unlock_node(rn1);
bgp_unlock_node(rn2);
return (ret);
}
static void bgp_show_nexthops(struct vty *vty, struct bgp *bgp, int detail)
{
struct bgp_node *rn;
struct bgp_nexthop_cache *bnc;
char buf[PREFIX2STR_BUFFER];
struct nexthop *nexthop;
time_t tbuf;
afi_t afi;
vty_out(vty, "Current BGP nexthop cache:\n");
for (afi = AFI_IP; afi < AFI_MAX; afi++) {
if (!bgp->nexthop_cache_table[afi])
continue;
for (rn = bgp_table_top(bgp->nexthop_cache_table[afi]); rn;
rn = bgp_route_next(rn)) {
if ((bnc = rn->info) != NULL) {
if (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_VALID)) {
vty_out(vty,
" %s valid [IGP metric %d], #paths %d\n",
inet_ntop(rn->p.family,
&rn->p.u.prefix, buf,
sizeof(buf)),
bnc->metric, bnc->path_count);
if (detail)
for (nexthop = bnc->nexthop;
nexthop;
nexthop = nexthop->next)
switch (nexthop->type) {
case NEXTHOP_TYPE_IPV6:
vty_out(vty,
" gate %s\n",
inet_ntop(
AF_INET6,
&nexthop->gate
.ipv6,
buf,
sizeof(buf)));
break;
case NEXTHOP_TYPE_IPV6_IFINDEX:
vty_out(vty,
" gate %s, if %s\n",
inet_ntop(
AF_INET6,
&nexthop->gate
.ipv6,
buf,
sizeof(buf)),
ifindex2ifname(
nexthop->ifindex,
bgp->vrf_id));
break;
case NEXTHOP_TYPE_IPV4:
vty_out(vty,
" gate %s\n",
inet_ntop(
AF_INET,
&nexthop->gate
.ipv4,
buf,
sizeof(buf)));
break;
case NEXTHOP_TYPE_IFINDEX:
vty_out(vty,
" if %s\n",
ifindex2ifname(
nexthop->ifindex,
bgp->vrf_id));
break;
case NEXTHOP_TYPE_IPV4_IFINDEX:
vty_out(vty,
" gate %s, if %s\n",
inet_ntop(
AF_INET,
&nexthop->gate
.ipv4,
buf,
sizeof(buf)),
ifindex2ifname(
nexthop->ifindex,
bgp->vrf_id));
break;
default:
vty_out(vty,
" invalid nexthop type %u\n",
nexthop->type);
}
} else {
vty_out(vty, " %s invalid\n",
inet_ntop(rn->p.family,
&rn->p.u.prefix, buf,
sizeof(buf)));
if (CHECK_FLAG(bnc->flags,
BGP_NEXTHOP_CONNECTED))
vty_out(vty,
" Must be Connected\n");
}
tbuf = time(NULL)
- (bgp_clock() - bnc->last_update);
vty_out(vty, " Last update: %s", ctime(&tbuf));
vty_out(vty, "\n");
}
}
}
}
static int show_ip_bgp_nexthop_table(struct vty *vty, const char *name,
int detail)
{
struct bgp *bgp;
if (name)
bgp = bgp_lookup_by_name(name);
else
bgp = bgp_get_default();
if (!bgp) {
vty_out(vty, "%% No such BGP instance exist\n");
return CMD_WARNING;
}
bgp_show_nexthops(vty, bgp, detail);
return CMD_SUCCESS;
}
static void bgp_show_all_instances_nexthops_vty(struct vty *vty)
{
struct listnode *node, *nnode;
struct bgp *bgp;
for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
vty_out(vty, "\nInstance %s:\n",
(bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
? "Default"
: bgp->name);
bgp_show_nexthops(vty, bgp, 0);
}
}
DEFUN (show_ip_bgp_nexthop,
@ -495,10 +496,10 @@ DEFUN (show_ip_bgp_nexthop,
"BGP nexthop table\n"
"Show detailed information\n")
{
int idx = 0;
char *vrf = argv_find (argv, argc, "WORD", &idx) ? argv[idx]->arg : NULL;
int detail = argv_find (argv, argc, "detail", &idx) ? 1 : 0;
return show_ip_bgp_nexthop_table (vty, vrf, detail);
int idx = 0;
char *vrf = argv_find(argv, argc, "WORD", &idx) ? argv[idx]->arg : NULL;
int detail = argv_find(argv, argc, "detail", &idx) ? 1 : 0;
return show_ip_bgp_nexthop_table(vty, vrf, detail);
}
DEFUN (show_ip_bgp_instance_all_nexthop,
@ -510,46 +511,43 @@ DEFUN (show_ip_bgp_instance_all_nexthop,
BGP_INSTANCE_ALL_HELP_STR
"BGP nexthop table\n")
{
bgp_show_all_instances_nexthops_vty (vty);
return CMD_SUCCESS;
bgp_show_all_instances_nexthops_vty(vty);
return CMD_SUCCESS;
}
void
bgp_scan_init (struct bgp *bgp)
void bgp_scan_init(struct bgp *bgp)
{
afi_t afi;
afi_t afi;
for (afi = AFI_IP; afi < AFI_MAX; afi++)
{
bgp->nexthop_cache_table[afi] = bgp_table_init (afi, SAFI_UNICAST);
bgp->connected_table[afi] = bgp_table_init (afi, SAFI_UNICAST);
bgp->import_check_table[afi] = bgp_table_init (afi, SAFI_UNICAST);
}
for (afi = AFI_IP; afi < AFI_MAX; afi++) {
bgp->nexthop_cache_table[afi] =
bgp_table_init(afi, SAFI_UNICAST);
bgp->connected_table[afi] = bgp_table_init(afi, SAFI_UNICAST);
bgp->import_check_table[afi] =
bgp_table_init(afi, SAFI_UNICAST);
}
}
void
bgp_scan_vty_init (void)
void bgp_scan_vty_init(void)
{
install_element (VIEW_NODE, &show_ip_bgp_nexthop_cmd);
install_element (VIEW_NODE, &show_ip_bgp_instance_all_nexthop_cmd);
install_element(VIEW_NODE, &show_ip_bgp_nexthop_cmd);
install_element(VIEW_NODE, &show_ip_bgp_instance_all_nexthop_cmd);
}
void
bgp_scan_finish (struct bgp *bgp)
void bgp_scan_finish(struct bgp *bgp)
{
afi_t afi;
afi_t afi;
for (afi = AFI_IP; afi < AFI_MAX; afi++)
{
/* Only the current one needs to be reset. */
bgp_nexthop_cache_reset (bgp->nexthop_cache_table[afi]);
bgp_table_unlock (bgp->nexthop_cache_table[afi]);
bgp->nexthop_cache_table[afi] = NULL;
for (afi = AFI_IP; afi < AFI_MAX; afi++) {
/* Only the current one needs to be reset. */
bgp_nexthop_cache_reset(bgp->nexthop_cache_table[afi]);
bgp_table_unlock(bgp->nexthop_cache_table[afi]);
bgp->nexthop_cache_table[afi] = NULL;
bgp_table_unlock (bgp->connected_table[afi]);
bgp->connected_table[afi] = NULL;
bgp_table_unlock(bgp->connected_table[afi]);
bgp->connected_table[afi] = NULL;
bgp_table_unlock (bgp->import_check_table[afi]);
bgp->import_check_table[afi] = NULL;
}
bgp_table_unlock(bgp->import_check_table[afi]);
bgp->import_check_table[afi] = NULL;
}
}

View File

@ -25,28 +25,26 @@
#include "queue.h"
#include "prefix.h"
#define NEXTHOP_FAMILY(nexthop_len) ( \
((nexthop_len) == 4 || \
(nexthop_len) == 12 ? AF_INET : \
((nexthop_len) == 16 || \
(nexthop_len) == 24 || \
(nexthop_len) == 48 ? AF_INET6 : \
AF_UNSPEC)) \
)
#define NEXTHOP_FAMILY(nexthop_len) \
(((nexthop_len) == 4 || (nexthop_len) == 12 \
? AF_INET \
: ((nexthop_len) == 16 || (nexthop_len) == 24 \
|| (nexthop_len) == 48 \
? AF_INET6 \
: AF_UNSPEC)))
#define BGP_MP_NEXTHOP_FAMILY NEXTHOP_FAMILY
/* BGP nexthop cache value structure. */
struct bgp_nexthop_cache
{
/* IGP route's metric. */
u_int32_t metric;
struct bgp_nexthop_cache {
/* IGP route's metric. */
u_int32_t metric;
/* Nexthop number and nexthop linked list.*/
u_char nexthop_num;
struct nexthop *nexthop;
time_t last_update;
u_int16_t flags;
/* Nexthop number and nexthop linked list.*/
u_char nexthop_num;
struct nexthop *nexthop;
time_t last_update;
u_int16_t flags;
#define BGP_NEXTHOP_VALID (1 << 0)
#define BGP_NEXTHOP_REGISTERED (1 << 1)
@ -55,26 +53,26 @@ struct bgp_nexthop_cache
#define BGP_STATIC_ROUTE (1 << 4)
#define BGP_STATIC_ROUTE_EXACT_MATCH (1 << 5)
u_int16_t change_flags;
u_int16_t change_flags;
#define BGP_NEXTHOP_CHANGED (1 << 0)
#define BGP_NEXTHOP_METRIC_CHANGED (1 << 1)
#define BGP_NEXTHOP_CONNECTED_CHANGED (1 << 2)
struct bgp_node *node;
void *nht_info; /* In BGP, peer session */
LIST_HEAD(path_list, bgp_info) paths;
unsigned int path_count;
struct bgp *bgp;
struct bgp_node *node;
void *nht_info; /* In BGP, peer session */
LIST_HEAD(path_list, bgp_info) paths;
unsigned int path_count;
struct bgp *bgp;
};
extern int bgp_nexthop_lookup (afi_t, struct peer *peer, struct bgp_info *,
int *, int *);
extern void bgp_connected_add (struct bgp *bgp, struct connected *c);
extern void bgp_connected_delete (struct bgp *bgp, struct connected *c);
extern int bgp_multiaccess_check_v4 (struct in_addr, struct peer *);
extern int bgp_config_write_scan_time (struct vty *);
extern int bgp_nexthop_self (struct bgp *, struct attr *);
extern int bgp_nexthop_lookup(afi_t, struct peer *peer, struct bgp_info *,
int *, int *);
extern void bgp_connected_add(struct bgp *bgp, struct connected *c);
extern void bgp_connected_delete(struct bgp *bgp, struct connected *c);
extern int bgp_multiaccess_check_v4(struct in_addr, struct peer *);
extern int bgp_config_write_scan_time(struct vty *);
extern int bgp_nexthop_self(struct bgp *, struct in_addr);
extern struct bgp_nexthop_cache *bnc_new(void);
extern void bnc_free(struct bgp_nexthop_cache *bnc);
extern void bnc_nexthop_free(struct bgp_nexthop_cache *bnc);
@ -82,7 +80,7 @@ extern char *bnc_str(struct bgp_nexthop_cache *bnc, char *buf, int size);
extern void bgp_scan_init(struct bgp *bgp);
extern void bgp_scan_finish(struct bgp *bgp);
extern void bgp_scan_vty_init(void);
extern void bgp_address_init (struct bgp *bgp);
extern void bgp_address_destroy (struct bgp *bgp);
extern void bgp_address_init(struct bgp *bgp);
extern void bgp_address_destroy(struct bgp *bgp);
#endif /* _QUAGGA_BGP_NEXTHOP_H */

File diff suppressed because it is too large Load Diff

View File

@ -45,8 +45,8 @@ extern int bgp_find_nexthop(struct bgp_info *p, int connected);
* peer - The BGP peer associated with this NHT
* connected - True if NH MUST be a connected route
*/
extern int bgp_find_or_add_nexthop(struct bgp *bgp, afi_t a,
struct bgp_info *p, struct peer *peer, int connected);
extern int bgp_find_or_add_nexthop(struct bgp *bgp, afi_t a, struct bgp_info *p,
struct peer *peer, int connected);
/**
* bgp_unlink_nexthop() - Unlink the nexthop object from the path structure.
@ -54,7 +54,7 @@ extern int bgp_find_or_add_nexthop(struct bgp *bgp, afi_t a,
* p - path structure.
*/
extern void bgp_unlink_nexthop(struct bgp_info *p);
void bgp_unlink_nexthop_by_peer (struct peer *);
void bgp_unlink_nexthop_by_peer(struct peer *);
/**
* bgp_delete_connected_nexthop() - Reset the 'peer' pointer for a connected
@ -64,6 +64,6 @@ void bgp_unlink_nexthop_by_peer (struct peer *);
* afi - afi: AFI_IP or AF_IP6
* peer - Ptr to peer
*/
extern void bgp_delete_connected_nexthop (afi_t afi, struct peer *peer);
extern void bgp_delete_connected_nexthop(afi_t afi, struct peer *peer);
#endif /* _BGP_NHT_H */

File diff suppressed because it is too large Load Diff

View File

@ -22,36 +22,31 @@
#define _QUAGGA_BGP_OPEN_H
/* Standard header for capability TLV */
struct capability_header
{
u_char code;
u_char length;
struct capability_header {
u_char code;
u_char length;
};
/* Generic MP capability data */
struct capability_mp_data
{
iana_afi_t afi;
u_char reserved;
safi_t safi;
struct capability_mp_data {
iana_afi_t afi;
u_char reserved;
safi_t safi;
};
struct capability_as4
{
uint32_t as4;
struct capability_as4 {
uint32_t as4;
};
struct graceful_restart_af
{
afi_t afi;
safi_t safi;
u_char flag;
struct graceful_restart_af {
afi_t afi;
safi_t safi;
u_char flag;
};
struct capability_gr
{
u_int16_t restart_flag_time;
struct graceful_restart_af gr[];
struct capability_gr {
u_int16_t restart_flag_time;
struct graceful_restart_af gr[];
};
/* Capability Code */
@ -68,7 +63,6 @@ struct capability_gr
#define CAPABILITY_CODE_REFRESH_OLD 128 /* Route Refresh Capability(cisco) */
#define CAPABILITY_CODE_ORF_OLD 130 /* Cooperative Route Filtering Capability(cisco) */
/* Capability Length */
#define CAPABILITY_CODE_MP_LEN 4
#define CAPABILITY_CODE_REFRESH_LEN 0
@ -99,9 +93,10 @@ struct capability_gr
#define RESTART_R_BIT 0x8000
#define RESTART_F_BIT 0x80
extern int bgp_open_option_parse (struct peer *, u_char, int *);
extern void bgp_open_capability (struct stream *, struct peer *);
extern void bgp_capability_vty_out (struct vty *, struct peer *, u_char, json_object *);
extern as_t peek_for_as4_capability (struct peer *, u_char);
extern int bgp_open_option_parse(struct peer *, u_char, int *);
extern void bgp_open_capability(struct stream *, struct peer *);
extern void bgp_capability_vty_out(struct vty *, struct peer *, u_char,
json_object *);
extern as_t peek_for_as4_capability(struct peer *, u_char);
#endif /* _QUAGGA_BGP_OPEN_H */

File diff suppressed because it is too large Load Diff

View File

@ -38,31 +38,33 @@
#define ORF_COMMON_PART_DENY 0x20
/* Packet send and receive function prototypes. */
extern int bgp_read (struct thread *);
extern int bgp_write (struct thread *);
extern int bgp_connect_check (struct peer *, int change_state);
extern int bgp_read(struct thread *);
extern int bgp_write(struct thread *);
extern int bgp_connect_check(struct peer *, int change_state);
extern void bgp_keepalive_send (struct peer *);
extern void bgp_open_send (struct peer *);
extern void bgp_notify_send (struct peer *, u_int8_t, u_int8_t);
extern void bgp_notify_send_with_data (struct peer *, u_int8_t, u_int8_t,
u_int8_t *, size_t);
extern void bgp_route_refresh_send (struct peer *, afi_t, safi_t, u_char, u_char, int);
extern void bgp_capability_send (struct peer *, afi_t, safi_t, int, int);
extern void bgp_default_update_send (struct peer *, struct attr *,
afi_t, safi_t, struct peer *);
extern void bgp_default_withdraw_send (struct peer *, afi_t, safi_t);
extern void bgp_keepalive_send(struct peer *);
extern void bgp_open_send(struct peer *);
extern void bgp_notify_send(struct peer *, u_int8_t, u_int8_t);
extern void bgp_notify_send_with_data(struct peer *, u_int8_t, u_int8_t,
u_int8_t *, size_t);
extern void bgp_route_refresh_send(struct peer *, afi_t, safi_t, u_char, u_char,
int);
extern void bgp_capability_send(struct peer *, afi_t, safi_t, int, int);
extern void bgp_default_update_send(struct peer *, struct attr *, afi_t, safi_t,
struct peer *);
extern void bgp_default_withdraw_send(struct peer *, afi_t, safi_t);
extern int bgp_capability_receive (struct peer *, bgp_size_t);
extern int bgp_capability_receive(struct peer *, bgp_size_t);
extern int bgp_nlri_parse (struct peer *, struct attr *, struct bgp_nlri *, int mp_withdraw);
extern int bgp_nlri_parse(struct peer *, struct attr *, struct bgp_nlri *,
int mp_withdraw);
extern void bgp_update_restarted_peers (struct peer *);
extern void bgp_update_implicit_eors (struct peer *);
extern void bgp_check_update_delay (struct bgp *);
extern void bgp_update_restarted_peers(struct peer *);
extern void bgp_update_implicit_eors(struct peer *);
extern void bgp_check_update_delay(struct bgp *);
extern int bgp_packet_set_marker (struct stream *s, u_char type);
extern int bgp_packet_set_size (struct stream *s);
extern void bgp_packet_add (struct peer *peer, struct stream *s);
extern int bgp_packet_set_marker(struct stream *s, u_char type);
extern int bgp_packet_set_size(struct stream *s);
extern void bgp_packet_add(struct peer *peer, struct stream *s);
#endif /* _QUAGGA_BGP_PACKET_H */

209
bgpd/bgp_rd.c Normal file
View File

@ -0,0 +1,209 @@
/* BGP RD definitions for BGP-based VPNs (IP/EVPN)
* -- brought over from bgpd/bgp_mplsvpn.c
* Copyright (C) 2000 Kunihiro Ishiguro <kunihiro@zebra.org>
*
* This file is part of FRR.
*
* FRR is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2, or (at your option) any
* later version.
*
* FRR is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with FRR; see the file COPYING. If not, write to the Free
* Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#include <zebra.h>
#include "command.h"
#include "log.h"
#include "prefix.h"
#include "memory.h"
#include "stream.h"
#include "filter.h"
#include "bgpd/bgpd.h"
#include "bgpd/bgp_rd.h"
#include "bgpd/bgp_attr.h"
#if ENABLE_BGP_VNC
#include "bgpd/rfapi/rfapi_backend.h"
#endif
u_int16_t decode_rd_type(u_char *pnt)
{
u_int16_t v;
v = ((u_int16_t)*pnt++ << 8);
#if ENABLE_BGP_VNC
/*
* VNC L2 stores LHI in lower byte, so omit it
*/
if (v != RD_TYPE_VNC_ETH)
v |= (u_int16_t)*pnt;
#else /* duplicate code for clarity */
v |= (u_int16_t)*pnt;
#endif
return v;
}
void encode_rd_type(u_int16_t v, u_char *pnt)
{
*((u_int16_t *)pnt) = htons(v);
}
/* type == RD_TYPE_AS */
void decode_rd_as(u_char *pnt, struct rd_as *rd_as)
{
rd_as->as = (u_int16_t)*pnt++ << 8;
rd_as->as |= (u_int16_t)*pnt++;
rd_as->val = ((u_int32_t)*pnt++ << 24);
rd_as->val |= ((u_int32_t)*pnt++ << 16);
rd_as->val |= ((u_int32_t)*pnt++ << 8);
rd_as->val |= (u_int32_t)*pnt;
}
/* type == RD_TYPE_AS4 */
void decode_rd_as4(u_char *pnt, struct rd_as *rd_as)
{
rd_as->as = (u_int32_t)*pnt++ << 24;
rd_as->as |= (u_int32_t)*pnt++ << 16;
rd_as->as |= (u_int32_t)*pnt++ << 8;
rd_as->as |= (u_int32_t)*pnt++;
rd_as->val = ((u_int16_t)*pnt++ << 8);
rd_as->val |= (u_int16_t)*pnt;
}
/* type == RD_TYPE_IP */
void decode_rd_ip(u_char *pnt, struct rd_ip *rd_ip)
{
memcpy(&rd_ip->ip, pnt, 4);
pnt += 4;
rd_ip->val = ((u_int16_t)*pnt++ << 8);
rd_ip->val |= (u_int16_t)*pnt;
}
#if ENABLE_BGP_VNC
/* type == RD_TYPE_VNC_ETH */
void decode_rd_vnc_eth(u_char *pnt, struct rd_vnc_eth *rd_vnc_eth)
{
rd_vnc_eth->type = RD_TYPE_VNC_ETH;
rd_vnc_eth->local_nve_id = pnt[1];
memcpy(rd_vnc_eth->macaddr.octet, pnt + 2, ETHER_ADDR_LEN);
}
#endif
int str2prefix_rd(const char *str, struct prefix_rd *prd)
{
int ret; /* ret of called functions */
int lret; /* local ret, of this func */
char *p;
char *p2;
struct stream *s = NULL;
char *half = NULL;
struct in_addr addr;
s = stream_new(8);
prd->family = AF_UNSPEC;
prd->prefixlen = 64;
lret = 0;
p = strchr(str, ':');
if (!p)
goto out;
if (!all_digit(p + 1))
goto out;
half = XMALLOC(MTYPE_TMP, (p - str) + 1);
memcpy(half, str, (p - str));
half[p - str] = '\0';
p2 = strchr(str, '.');
if (!p2) {
unsigned long as_val;
if (!all_digit(half))
goto out;
as_val = atol(half);
if (as_val > 0xffff) {
stream_putw(s, RD_TYPE_AS4);
stream_putl(s, as_val);
stream_putw(s, atol(p + 1));
} else {
stream_putw(s, RD_TYPE_AS);
stream_putw(s, as_val);
stream_putl(s, atol(p + 1));
}
} else {
ret = inet_aton(half, &addr);
if (!ret)
goto out;
stream_putw(s, RD_TYPE_IP);
stream_put_in_addr(s, &addr);
stream_putw(s, atol(p + 1));
}
memcpy(prd->val, s->data, 8);
lret = 1;
out:
if (s)
stream_free(s);
if (half)
XFREE(MTYPE_TMP, half);
return lret;
}
char *prefix_rd2str(struct prefix_rd *prd, char *buf, size_t size)
{
u_char *pnt;
u_int16_t type;
struct rd_as rd_as;
struct rd_ip rd_ip;
if (size < RD_ADDRSTRLEN)
return NULL;
pnt = prd->val;
type = decode_rd_type(pnt);
if (type == RD_TYPE_AS) {
decode_rd_as(pnt + 2, &rd_as);
snprintf(buf, size, "%u:%d", rd_as.as, rd_as.val);
return buf;
} else if (type == RD_TYPE_AS4) {
decode_rd_as4(pnt + 2, &rd_as);
snprintf(buf, size, "%u:%d", rd_as.as, rd_as.val);
return buf;
} else if (type == RD_TYPE_IP) {
decode_rd_ip(pnt + 2, &rd_ip);
snprintf(buf, size, "%s:%d", inet_ntoa(rd_ip.ip), rd_ip.val);
return buf;
}
#if ENABLE_BGP_VNC
else if (type == RD_TYPE_VNC_ETH) {
snprintf(buf, size, "LHI:%d, %02x:%02x:%02x:%02x:%02x:%02x",
*(pnt + 1), /* LHI */
*(pnt + 2), /* MAC[0] */
*(pnt + 3), *(pnt + 4), *(pnt + 5), *(pnt + 6),
*(pnt + 7));
return buf;
}
#endif
return NULL;
}

70
bgpd/bgp_rd.h Normal file
View File

@ -0,0 +1,70 @@
/* BGP RD definitions for BGP-based VPNs (IP/EVPN)
* -- brought over from bgpd/bgp_mplsvpn.h
* Copyright (C) 2000 Kunihiro Ishiguro <kunihiro@zebra.org>
*
* This file is part of FRR.
*
* FRR is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2, or (at your option) any
* later version.
*
* FRR is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with FRR; see the file COPYING. If not, write to the Free
* Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#ifndef _QUAGGA_BGP_RD_H
#define _QUAGGA_BGP_RD_H
/* RD types */
#define RD_TYPE_AS 0
#define RD_TYPE_IP 1
#define RD_TYPE_AS4 2
#if ENABLE_BGP_VNC
#define RD_TYPE_VNC_ETH 0xff00 /* VNC L2VPN */
#endif
#define RD_ADDRSTRLEN 28
struct rd_as {
u_int16_t type;
as_t as;
u_int32_t val;
};
struct rd_ip {
u_int16_t type;
struct in_addr ip;
u_int16_t val;
};
#if ENABLE_BGP_VNC
struct rd_vnc_eth {
u_int16_t type;
uint8_t local_nve_id;
struct ethaddr macaddr;
};
#endif
extern u_int16_t decode_rd_type(u_char *pnt);
extern void encode_rd_type(u_int16_t, u_char *);
extern void decode_rd_as(u_char *pnt, struct rd_as *rd_as);
extern void decode_rd_as4(u_char *pnt, struct rd_as *rd_as);
extern void decode_rd_ip(u_char *pnt, struct rd_ip *rd_ip);
#if ENABLE_BGP_VNC
extern void decode_rd_vnc_eth(u_char *pnt, struct rd_vnc_eth *rd_vnc_eth);
#endif
extern int str2prefix_rd(const char *, struct prefix_rd *);
extern char *prefix_rd2str(struct prefix_rd *, char *, size_t);
#endif /* _QUAGGA_BGP_RD_H */

View File

@ -31,65 +31,59 @@
#include "bgp_regex.h"
/* Character `_' has special mean. It represents [,{}() ] and the
beginning of the line(^) and the end of the line ($).
beginning of the line(^) and the end of the line ($).
(^|[,{}() ]|$) */
regex_t *
bgp_regcomp (const char *regstr)
regex_t *bgp_regcomp(const char *regstr)
{
/* Convert _ character to generic regular expression. */
int i, j;
int len;
int magic = 0;
char *magic_str;
char magic_regexp[] = "(^|[,{}() ]|$)";
int ret;
regex_t *regex;
/* Convert _ character to generic regular expression. */
int i, j;
int len;
int magic = 0;
char *magic_str;
char magic_regexp[] = "(^|[,{}() ]|$)";
int ret;
regex_t *regex;
len = strlen (regstr);
for (i = 0; i < len; i++)
if (regstr[i] == '_')
magic++;
len = strlen(regstr);
for (i = 0; i < len; i++)
if (regstr[i] == '_')
magic++;
magic_str = XMALLOC (MTYPE_TMP, len + (14 * magic) + 1);
for (i = 0, j = 0; i < len; i++)
{
if (regstr[i] == '_')
{
memcpy (magic_str + j, magic_regexp, strlen (magic_regexp));
j += strlen (magic_regexp);
magic_str = XMALLOC(MTYPE_TMP, len + (14 * magic) + 1);
for (i = 0, j = 0; i < len; i++) {
if (regstr[i] == '_') {
memcpy(magic_str + j, magic_regexp,
strlen(magic_regexp));
j += strlen(magic_regexp);
} else
magic_str[j++] = regstr[i];
}
else
magic_str[j++] = regstr[i];
}
magic_str[j] = '\0';
magic_str[j] = '\0';
regex = XMALLOC (MTYPE_BGP_REGEXP, sizeof (regex_t));
regex = XMALLOC(MTYPE_BGP_REGEXP, sizeof(regex_t));
ret = regcomp (regex, magic_str, REG_EXTENDED|REG_NOSUB);
ret = regcomp(regex, magic_str, REG_EXTENDED | REG_NOSUB);
XFREE (MTYPE_TMP, magic_str);
XFREE(MTYPE_TMP, magic_str);
if (ret != 0)
{
XFREE (MTYPE_BGP_REGEXP, regex);
return NULL;
}
if (ret != 0) {
XFREE(MTYPE_BGP_REGEXP, regex);
return NULL;
}
return regex;
return regex;
}
int
bgp_regexec (regex_t *regex, struct aspath *aspath)
int bgp_regexec(regex_t *regex, struct aspath *aspath)
{
return regexec (regex, aspath->str, 0, NULL, 0);
return regexec(regex, aspath->str, 0, NULL, 0);
}
void
bgp_regex_free (regex_t *regex)
void bgp_regex_free(regex_t *regex)
{
regfree (regex);
XFREE (MTYPE_BGP_REGEXP, regex);
regfree(regex);
XFREE(MTYPE_BGP_REGEXP, regex);
}

View File

@ -24,13 +24,13 @@
#include <zebra.h>
#ifdef HAVE_LIBPCREPOSIX
# include <pcreposix.h>
#include <pcreposix.h>
#else
# include <regex.h>
#include <regex.h>
#endif /* HAVE_LIBPCREPOSIX */
extern void bgp_regex_free (regex_t *regex);
extern regex_t *bgp_regcomp (const char *str);
extern int bgp_regexec (regex_t *regex, struct aspath *aspath);
extern void bgp_regex_free(regex_t *regex);
extern regex_t *bgp_regcomp(const char *str);
extern int bgp_regexec(regex_t *regex, struct aspath *aspath);
#endif /* _QUAGGA_BGP_REGEX_H */

File diff suppressed because it is too large Load Diff

View File

@ -27,116 +27,125 @@
struct bgp_nexthop_cache;
struct bgp_route_evpn;
enum bgp_show_type
{
bgp_show_type_normal,
bgp_show_type_regexp,
bgp_show_type_prefix_list,
bgp_show_type_filter_list,
bgp_show_type_route_map,
bgp_show_type_neighbor,
bgp_show_type_cidr_only,
bgp_show_type_prefix_longer,
bgp_show_type_community_all,
bgp_show_type_community,
bgp_show_type_community_exact,
bgp_show_type_community_list,
bgp_show_type_community_list_exact,
bgp_show_type_lcommunity_all,
bgp_show_type_lcommunity,
bgp_show_type_lcommunity_list,
bgp_show_type_flap_statistics,
bgp_show_type_flap_neighbor,
bgp_show_type_dampend_paths,
bgp_show_type_damp_neighbor
enum bgp_show_type {
bgp_show_type_normal,
bgp_show_type_regexp,
bgp_show_type_prefix_list,
bgp_show_type_filter_list,
bgp_show_type_route_map,
bgp_show_type_neighbor,
bgp_show_type_cidr_only,
bgp_show_type_prefix_longer,
bgp_show_type_community_all,
bgp_show_type_community,
bgp_show_type_community_exact,
bgp_show_type_community_list,
bgp_show_type_community_list_exact,
bgp_show_type_lcommunity_all,
bgp_show_type_lcommunity,
bgp_show_type_lcommunity_list,
bgp_show_type_flap_statistics,
bgp_show_type_flap_neighbor,
bgp_show_type_dampend_paths,
bgp_show_type_damp_neighbor
};
#define BGP_SHOW_SCODE_HEADER "Status codes: s suppressed, d damped, "\
"h history, * valid, > best, = multipath,%s"\
" i internal, r RIB-failure, S Stale, R Removed"
#define BGP_SHOW_OCODE_HEADER "Origin codes: i - IGP, e - EGP, ? - incomplete%s"
#define BGP_SHOW_HEADER " Network Next Hop Metric LocPrf Weight Path"
#define BGP_SHOW_SCODE_HEADER \
"Status codes: s suppressed, d damped, " \
"h history, * valid, > best, = multipath,\n" \
" i internal, r RIB-failure, S Stale, R Removed\n"
#define BGP_SHOW_OCODE_HEADER "Origin codes: i - IGP, e - EGP, ? - incomplete\n\n"
#define BGP_SHOW_HEADER " Network Next Hop Metric LocPrf Weight Path\n"
/* Ancillary information to struct bgp_info,
/* Ancillary information to struct bgp_info,
* used for uncommonly used data (aggregation, MPLS, etc.)
* and lazily allocated to save memory.
*/
struct bgp_info_extra
{
/* Pointer to dampening structure. */
struct bgp_damp_info *damp_info;
struct bgp_info_extra {
/* Pointer to dampening structure. */
struct bgp_damp_info *damp_info;
/* This route is suppressed with aggregation. */
int suppress;
/* This route is suppressed with aggregation. */
int suppress;
/* Nexthop reachability check. */
u_int32_t igpmetric;
/* Nexthop reachability check. */
u_int32_t igpmetric;
/* MPLS label. */
u_char tag[3];
/* MPLS label. */
mpls_label_t label;
#if ENABLE_BGP_VNC
union {
union {
struct {
void *rfapi_handle; /* export: NVE advertising this route */
struct list *local_nexthops; /* optional, for static routes */
} export;
struct {
void *rfapi_handle; /* export: NVE advertising this
route */
struct list *local_nexthops; /* optional, for static
routes */
} export;
struct {
struct thread *timer;
void *hme; /* encap monitor, if this is a VPN route */
struct prefix_rd rd; /* import: route's route-distinguisher */
u_char un_family; /* family of cached un address, 0 if unset */
union {
struct in_addr addr4;
struct in6_addr addr6;
} un; /* cached un address */
time_t create_time;
struct prefix aux_prefix; /* AFI_L2VPN: the IP addr, if family set */
} import;
struct {
struct thread *timer;
void *hme; /* encap monitor, if this is a VPN route */
struct prefix_rd
rd; /* import: route's route-distinguisher */
u_char un_family; /* family of cached un address, 0 if
unset */
union {
struct in_addr addr4;
struct in6_addr addr6;
} un; /* cached un address */
time_t create_time;
struct
prefix
aux_prefix; /* AFI_L2VPN: the IP addr,
if family set */
} import;
} vnc;
} vnc;
#endif
/* For imported routes into a VNI (or VRF), this points to the parent.
*/
void *parent;
};
struct bgp_info
{
/* For linked list. */
struct bgp_info *next;
struct bgp_info *prev;
struct bgp_info {
/* For linked list. */
struct bgp_info *next;
struct bgp_info *prev;
/* For nexthop linked list */
LIST_ENTRY(bgp_info) nh_thread;
/* For nexthop linked list */
LIST_ENTRY(bgp_info) nh_thread;
/* Back pointer to the prefix node */
struct bgp_node *net;
/* Back pointer to the prefix node */
struct bgp_node *net;
/* Back pointer to the nexthop structure */
struct bgp_nexthop_cache *nexthop;
/* Back pointer to the nexthop structure */
struct bgp_nexthop_cache *nexthop;
/* Peer structure. */
struct peer *peer;
/* Peer structure. */
struct peer *peer;
/* Attribute structure. */
struct attr *attr;
/* Extra information */
struct bgp_info_extra *extra;
/* Attribute structure. */
struct attr *attr;
/* Multipath information */
struct bgp_info_mpath *mpath;
/* Extra information */
struct bgp_info_extra *extra;
/* Uptime. */
time_t uptime;
/* reference count */
int lock;
/* BGP information status. */
u_int16_t flags;
/* Multipath information */
struct bgp_info_mpath *mpath;
/* Uptime. */
time_t uptime;
/* reference count */
int lock;
/* BGP information status. */
u_int16_t flags;
#define BGP_INFO_IGP_CHANGED (1 << 0)
#define BGP_INFO_DAMPED (1 << 1)
#define BGP_INFO_HISTORY (1 << 2)
@ -152,12 +161,12 @@ struct bgp_info
#define BGP_INFO_MULTIPATH_CHG (1 << 12)
#define BGP_INFO_RIB_ATTR_CHG (1 << 13)
/* BGP route type. This can be static, RIP, OSPF, BGP etc. */
u_char type;
/* BGP route type. This can be static, RIP, OSPF, BGP etc. */
u_char type;
/* When above type is BGP. This sub type specify BGP sub type
information. */
u_char sub_type;
/* When above type is BGP. This sub type specify BGP sub type
information. */
u_char sub_type;
#define BGP_ROUTE_NORMAL 0
#define BGP_ROUTE_STATIC 1
#define BGP_ROUTE_AGGREGATE 2
@ -166,78 +175,81 @@ struct bgp_info
# define BGP_ROUTE_RFP 4
#endif
u_short instance;
u_short instance;
/* Addpath identifiers */
u_int32_t addpath_rx_id;
u_int32_t addpath_tx_id;
/* Addpath identifiers */
u_int32_t addpath_rx_id;
u_int32_t addpath_tx_id;
};
/* Structure used in BGP path selection */
struct bgp_info_pair {
struct bgp_info *old;
struct bgp_info *new;
};
/* BGP static route configuration. */
struct bgp_static
{
/* Backdoor configuration. */
int backdoor;
struct bgp_static {
/* Backdoor configuration. */
int backdoor;
/* Label index configuration; applies to LU prefixes. */
u_int32_t label_index;
/* Label index configuration; applies to LU prefixes. */
u_int32_t label_index;
#define BGP_INVALID_LABEL_INDEX 0xFFFFFFFF
/* Import check status. */
u_char valid;
/* Import check status. */
u_char valid;
/* IGP metric. */
u_int32_t igpmetric;
/* IGP metric. */
u_int32_t igpmetric;
/* IGP nexthop. */
struct in_addr igpnexthop;
/* IGP nexthop. */
struct in_addr igpnexthop;
/* Atomic set reference count (ie cause of pathlimit) */
u_int32_t atomic;
/* BGP redistribute route-map. */
struct
{
char *name;
struct route_map *map;
} rmap;
/* Atomic set reference count (ie cause of pathlimit) */
u_int32_t atomic;
/* Route Distinguisher */
struct prefix_rd prd;
/* BGP redistribute route-map. */
struct {
char *name;
struct route_map *map;
} rmap;
/* MPLS label. */
u_char tag[3];
/* Route Distinguisher */
struct prefix_rd prd;
/* EVPN */
struct eth_segment_id *eth_s_id;
struct ethaddr *router_mac;
uint16_t encap_tunneltype;
struct prefix gatewayIp;
/* MPLS label. */
mpls_label_t label;
/* EVPN */
struct eth_segment_id *eth_s_id;
struct ethaddr *router_mac;
uint16_t encap_tunneltype;
struct prefix gatewayIp;
};
#define BGP_NEXTHOP_AFI_FROM_NHLEN(nhlen) \
((nhlen) < IPV4_MAX_BYTELEN ? 0 : \
((nhlen) < IPV6_MAX_BYTELEN ? AFI_IP : AFI_IP6))
#define BGP_NEXTHOP_AFI_FROM_NHLEN(nhlen) \
((nhlen) < IPV4_MAX_BYTELEN \
? 0 \
: ((nhlen) < IPV6_MAX_BYTELEN ? AFI_IP : AFI_IP6))
#define BGP_ATTR_NEXTHOP_AFI_IP6(attr) \
(! CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP)) && \
(attr)->extra && ((attr)->extra->mp_nexthop_len == 16 || \
(attr)->extra->mp_nexthop_len == 32))
#define BGP_INFO_COUNTABLE(BI) \
(! CHECK_FLAG ((BI)->flags, BGP_INFO_HISTORY) \
&& ! CHECK_FLAG ((BI)->flags, BGP_INFO_REMOVED))
#define BGP_ATTR_NEXTHOP_AFI_IP6(attr) \
(!CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP)) \
&& ((attr)->mp_nexthop_len == 16 || (attr)->mp_nexthop_len == 32))
#define BGP_INFO_COUNTABLE(BI) \
(!CHECK_FLAG((BI)->flags, BGP_INFO_HISTORY) \
&& !CHECK_FLAG((BI)->flags, BGP_INFO_REMOVED))
/* Flags which indicate a route is unuseable in some form */
#define BGP_INFO_UNUSEABLE \
(BGP_INFO_HISTORY|BGP_INFO_DAMPED|BGP_INFO_REMOVED)
#define BGP_INFO_UNUSEABLE \
(BGP_INFO_HISTORY | BGP_INFO_DAMPED | BGP_INFO_REMOVED)
/* Macro to check BGP information is alive or not. Sadly,
* not equivalent to just checking previous, because of the
* sense of the additional VALID flag.
*/
#define BGP_INFO_HOLDDOWN(BI) \
(! CHECK_FLAG ((BI)->flags, BGP_INFO_VALID) \
|| CHECK_FLAG ((BI)->flags, BGP_INFO_UNUSEABLE))
#define BGP_INFO_HOLDDOWN(BI) \
(!CHECK_FLAG((BI)->flags, BGP_INFO_VALID) \
|| CHECK_FLAG((BI)->flags, BGP_INFO_UNUSEABLE))
#define DISTRIBUTE_IN_NAME(F) ((F)->dlist[FILTER_IN].name)
#define DISTRIBUTE_IN(F) ((F)->dlist[FILTER_IN].alist)
@ -265,141 +277,167 @@ struct bgp_static
/* path PREFIX (addpath rxid NUMBER) */
#define PATH_ADDPATH_STR_BUFFER PREFIX2STR_BUFFER + 32
enum bgp_path_type
{
BGP_PATH_ALL,
BGP_PATH_BESTPATH,
BGP_PATH_MULTIPATH
};
enum bgp_path_type { BGP_PATH_ALL, BGP_PATH_BESTPATH, BGP_PATH_MULTIPATH };
static inline void
bgp_bump_version (struct bgp_node *node)
static inline void bgp_bump_version(struct bgp_node *node)
{
node->version = bgp_table_next_version(bgp_node_table(node));
node->version = bgp_table_next_version(bgp_node_table(node));
}
static inline int
bgp_fibupd_safi (safi_t safi)
static inline int bgp_fibupd_safi(safi_t safi)
{
if (safi == SAFI_UNICAST ||
safi == SAFI_MULTICAST ||
safi == SAFI_LABELED_UNICAST)
return 1;
return 0;
if (safi == SAFI_UNICAST || safi == SAFI_MULTICAST
|| safi == SAFI_LABELED_UNICAST)
return 1;
return 0;
}
/* Prototypes. */
extern void bgp_process_queue_init (void);
extern void bgp_route_init (void);
extern void bgp_route_finish (void);
extern void bgp_cleanup_routes (struct bgp *);
extern void bgp_announce_route (struct peer *, afi_t, safi_t);
extern void bgp_process_queue_init(void);
extern void bgp_route_init(void);
extern void bgp_route_finish(void);
extern void bgp_cleanup_routes(struct bgp *);
extern void bgp_announce_route(struct peer *, afi_t, safi_t);
extern void bgp_stop_announce_route_timer(struct peer_af *paf);
extern void bgp_announce_route_all (struct peer *);
extern void bgp_default_originate (struct peer *, afi_t, safi_t, int);
extern void bgp_soft_reconfig_in (struct peer *, afi_t, safi_t);
extern void bgp_clear_route (struct peer *, afi_t, safi_t);
extern void bgp_clear_route_all (struct peer *);
extern void bgp_clear_adj_in (struct peer *, afi_t, safi_t);
extern void bgp_clear_stale_route (struct peer *, afi_t, safi_t);
extern void bgp_announce_route_all(struct peer *);
extern void bgp_default_originate(struct peer *, afi_t, safi_t, int);
extern void bgp_soft_reconfig_in(struct peer *, afi_t, safi_t);
extern void bgp_clear_route(struct peer *, afi_t, safi_t);
extern void bgp_clear_route_all(struct peer *);
extern void bgp_clear_adj_in(struct peer *, afi_t, safi_t);
extern void bgp_clear_stale_route(struct peer *, afi_t, safi_t);
extern struct bgp_node *bgp_afi_node_get (struct bgp_table *table, afi_t afi,
safi_t safi, struct prefix *p,
struct prefix_rd *prd);
extern struct bgp_info *bgp_info_lock (struct bgp_info *);
extern struct bgp_info *bgp_info_unlock (struct bgp_info *);
extern void bgp_info_add (struct bgp_node *rn, struct bgp_info *ri);
extern void bgp_info_delete (struct bgp_node *rn, struct bgp_info *ri);
extern struct bgp_info_extra *bgp_info_extra_get (struct bgp_info *);
extern void bgp_info_set_flag (struct bgp_node *, struct bgp_info *, u_int32_t);
extern void bgp_info_unset_flag (struct bgp_node *, struct bgp_info *, u_int32_t);
extern void bgp_info_path_with_addpath_rx_str (struct bgp_info *ri, char *buf);
extern struct bgp_node *bgp_afi_node_get(struct bgp_table *table, afi_t afi,
safi_t safi, struct prefix *p,
struct prefix_rd *prd);
extern struct bgp_info *bgp_info_lock(struct bgp_info *);
extern struct bgp_info *bgp_info_unlock(struct bgp_info *);
extern void bgp_info_add(struct bgp_node *rn, struct bgp_info *ri);
extern void bgp_info_reap(struct bgp_node *rn, struct bgp_info *ri);
extern void bgp_info_delete(struct bgp_node *rn, struct bgp_info *ri);
extern struct bgp_info_extra *bgp_info_extra_get(struct bgp_info *);
extern void bgp_info_set_flag(struct bgp_node *, struct bgp_info *, u_int32_t);
extern void bgp_info_unset_flag(struct bgp_node *, struct bgp_info *,
u_int32_t);
extern void bgp_info_path_with_addpath_rx_str(struct bgp_info *ri, char *buf);
extern int bgp_nlri_parse_ip (struct peer *, struct attr *, struct bgp_nlri *);
extern int bgp_nlri_parse_ip(struct peer *, struct attr *, struct bgp_nlri *);
extern int bgp_maximum_prefix_overflow (struct peer *, afi_t, safi_t, int);
extern int bgp_maximum_prefix_overflow(struct peer *, afi_t, safi_t, int);
extern void bgp_redistribute_add (struct bgp *, struct prefix *, const struct in_addr *,
const struct in6_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);
extern void bgp_redistribute_withdraw (struct bgp *, afi_t, int, u_short);
extern void bgp_redistribute_add(struct bgp *, struct prefix *,
const struct in_addr *,
const struct in6_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);
extern void bgp_redistribute_withdraw(struct bgp *, afi_t, int, u_short);
extern void bgp_static_add (struct bgp *);
extern void bgp_static_delete (struct bgp *);
extern void bgp_static_redo_import_check (struct bgp *);
extern void bgp_purge_static_redist_routes (struct bgp *bgp);
extern void bgp_static_update (struct bgp *, struct prefix *, struct bgp_static *,
afi_t, safi_t);
extern void bgp_static_withdraw (struct bgp *, struct prefix *, afi_t, safi_t);
extern int bgp_static_set_safi (afi_t afi, safi_t safi, struct vty *vty, const char *,
const char *, const char *, const char *,
int, const char *, const char *, const char *, const char *);
extern void bgp_static_add(struct bgp *);
extern void bgp_static_delete(struct bgp *);
extern void bgp_static_redo_import_check(struct bgp *);
extern void bgp_purge_static_redist_routes(struct bgp *bgp);
extern void bgp_static_update(struct bgp *, struct prefix *,
struct bgp_static *, afi_t, safi_t);
extern void bgp_static_withdraw(struct bgp *, struct prefix *, afi_t, safi_t);
extern int bgp_static_unset_safi (afi_t afi, safi_t safi, struct vty *, const char *,
const char *, const char *,
int, const char *, const char *, const char *);
extern int bgp_static_set_safi(afi_t afi, safi_t safi, struct vty *vty,
const char *, const char *, const char *,
const char *, int, const char *, const char *,
const char *, const char *);
extern int bgp_static_unset_safi(afi_t afi, safi_t safi, struct vty *,
const char *, const char *, const char *, int,
const char *, const char *, const char *);
/* this is primarily for MPLS-VPN */
extern int bgp_update (struct peer *, struct prefix *, u_int32_t, struct attr *,
afi_t, safi_t, int, int, struct prefix_rd *,
u_char *, int, struct bgp_route_evpn *);
extern int bgp_withdraw (struct peer *, struct prefix *, u_int32_t, struct attr *,
afi_t, safi_t, int, int, struct prefix_rd *, u_char *,
struct bgp_route_evpn *);
extern int bgp_update(struct peer *, struct prefix *, u_int32_t, struct attr *,
afi_t, safi_t, int, int, struct prefix_rd *,
mpls_label_t *, int, struct bgp_route_evpn *);
extern int bgp_withdraw(struct peer *, struct prefix *, u_int32_t,
struct attr *, afi_t, safi_t, int, int,
struct prefix_rd *, mpls_label_t *,
struct bgp_route_evpn *);
/* for bgp_nexthop and bgp_damp */
extern void bgp_process (struct bgp *, struct bgp_node *, afi_t, safi_t);
extern void bgp_process(struct bgp *, struct bgp_node *, afi_t, safi_t);
/*
* Add an end-of-initial-update marker to the process queue. This is just a
* queue element with NULL bgp node.
*/
extern void bgp_add_eoiu_mark (struct bgp *);
extern int bgp_config_write_table_map (struct vty *, struct bgp *, afi_t, safi_t,
int *);
extern int bgp_config_write_network (struct vty *, struct bgp *, afi_t, safi_t, int *);
extern int bgp_config_write_distance (struct vty *, struct bgp *, afi_t, safi_t, int *);
extern void bgp_add_eoiu_mark(struct bgp *);
extern int bgp_config_write_table_map(struct vty *, struct bgp *, afi_t, safi_t,
int *);
extern int bgp_config_write_network(struct vty *, struct bgp *, afi_t, safi_t,
int *);
extern int bgp_config_write_distance(struct vty *, struct bgp *, afi_t, safi_t,
int *);
extern void bgp_aggregate_increment (struct bgp *, struct prefix *, struct bgp_info *,
afi_t, safi_t);
extern void bgp_aggregate_decrement (struct bgp *, struct prefix *, struct bgp_info *,
afi_t, safi_t);
extern void bgp_aggregate_increment(struct bgp *, struct prefix *,
struct bgp_info *, afi_t, safi_t);
extern void bgp_aggregate_decrement(struct bgp *, struct prefix *,
struct bgp_info *, afi_t, safi_t);
extern u_char bgp_distance_apply (struct prefix *, struct bgp_info *, afi_t, safi_t, struct bgp *);
extern u_char bgp_distance_apply(struct prefix *, struct bgp_info *, afi_t,
safi_t, struct bgp *);
extern afi_t bgp_node_afi (struct vty *);
extern safi_t bgp_node_safi (struct vty *);
extern afi_t bgp_node_afi(struct vty *);
extern safi_t bgp_node_safi(struct vty *);
extern void route_vty_out (struct vty *, struct prefix *, struct bgp_info *, int, safi_t, json_object *);
extern void route_vty_out_tag (struct vty *, struct prefix *, struct bgp_info *, int, safi_t, json_object *);
extern void route_vty_out_tmp (struct vty *, struct prefix *, struct attr *, safi_t, u_char, json_object *);
extern void
route_vty_out_overlay (struct vty *vty, struct prefix *p,
struct bgp_info *binfo, int display, json_object *json);
extern struct bgp_info *info_make(int type, int sub_type, u_short instance,
struct peer *peer, struct attr *attr,
struct bgp_node *rn);
extern int
subgroup_process_announce_selected (struct update_subgroup *subgrp,
struct bgp_info *selected,
struct bgp_node *rn,
u_int32_t addpath_tx_id);
extern void route_vty_out(struct vty *, struct prefix *, struct bgp_info *, int,
safi_t, json_object *);
extern void route_vty_out_tag(struct vty *, struct prefix *, struct bgp_info *,
int, safi_t, json_object *);
extern void route_vty_out_tmp(struct vty *, struct prefix *, struct attr *,
safi_t, u_char, json_object *);
extern void route_vty_out_overlay(struct vty *vty, struct prefix *p,
struct bgp_info *binfo, int display,
json_object *json);
extern int subgroup_process_announce_selected(struct update_subgroup *subgrp,
struct bgp_info *selected,
struct bgp_node *rn,
u_int32_t addpath_tx_id);
extern int subgroup_announce_check(struct bgp_node *rn, struct bgp_info *ri,
struct update_subgroup *subgrp,
struct prefix *p, struct attr *attr);
extern void bgp_peer_clear_node_queue_drain_immediate (struct peer *peer);
extern void bgp_process_queues_drain_immediate (void);
extern void bgp_peer_clear_node_queue_drain_immediate(struct peer *peer);
extern void bgp_process_queues_drain_immediate(void);
/* for encap/vpn */
extern struct bgp_node *
bgp_afi_node_get (struct bgp_table *, afi_t , safi_t , struct prefix *,
struct prefix_rd *);
extern struct bgp_info *bgp_info_new (void);
extern void bgp_info_restore (struct bgp_node *, struct bgp_info *);
extern struct bgp_node *bgp_afi_node_get(struct bgp_table *, afi_t, safi_t,
struct prefix *, struct prefix_rd *);
extern struct bgp_node *bgp_afi_node_lookup(struct bgp_table *table, afi_t afi,
safi_t safi, struct prefix *p,
struct prefix_rd *prd);
extern struct bgp_info *bgp_info_new(void);
extern void bgp_info_restore(struct bgp_node *, struct bgp_info *);
extern int bgp_info_cmp_compatible (struct bgp *, struct bgp_info *,
struct bgp_info *, afi_t, safi_t );
extern int bgp_info_cmp_compatible(struct bgp *, struct bgp_info *,
struct bgp_info *, char *pfx_buf, afi_t afi,
safi_t safi);
extern void bgp_best_selection(struct bgp *bgp, struct bgp_node *rn,
struct bgp_maxpaths_cfg *mpath_cfg,
struct bgp_info_pair *result, afi_t afi,
safi_t safi);
extern void bgp_zebra_clear_route_change_flags(struct bgp_node *rn);
extern int bgp_zebra_has_route_changed(struct bgp_node *rn,
struct bgp_info *selected);
extern void route_vty_out_detail_header(struct vty *vty, struct bgp *bgp,
struct bgp_node *rn,
struct prefix_rd *prd, afi_t afi,
safi_t safi, json_object *json);
extern void route_vty_out_detail(struct vty *vty, struct bgp *bgp,
struct prefix *p, struct bgp_info *binfo,
afi_t afi, safi_t safi,
json_object *json_paths);
#endif /* _QUAGGA_BGP_ROUTE_H */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -30,91 +30,82 @@
#include "bgpd/bgpd.h"
#include "bgpd/bgp_table.h"
void
bgp_table_lock (struct bgp_table *rt)
void bgp_table_lock(struct bgp_table *rt)
{
rt->lock++;
rt->lock++;
}
void
bgp_table_unlock (struct bgp_table *rt)
void bgp_table_unlock(struct bgp_table *rt)
{
assert (rt->lock > 0);
rt->lock--;
assert(rt->lock > 0);
rt->lock--;
if (rt->lock != 0)
{
return;
}
if (rt->lock != 0) {
return;
}
route_table_finish (rt->route_table);
rt->route_table = NULL;
route_table_finish(rt->route_table);
rt->route_table = NULL;
XFREE (MTYPE_BGP_TABLE, rt);
XFREE(MTYPE_BGP_TABLE, rt);
}
void
bgp_table_finish (struct bgp_table **rt)
void bgp_table_finish(struct bgp_table **rt)
{
if (*rt != NULL)
{
bgp_table_unlock(*rt);
*rt = NULL;
}
if (*rt != NULL) {
bgp_table_unlock(*rt);
*rt = NULL;
}
}
/*
* bgp_node_create
*/
static struct route_node *
bgp_node_create (route_table_delegate_t *delegate, struct route_table *table)
static struct route_node *bgp_node_create(route_table_delegate_t *delegate,
struct route_table *table)
{
struct bgp_node *node;
node = XCALLOC (MTYPE_BGP_NODE, sizeof (struct bgp_node));
return bgp_node_to_rnode (node);
struct bgp_node *node;
node = XCALLOC(MTYPE_BGP_NODE, sizeof(struct bgp_node));
return bgp_node_to_rnode(node);
}
/*
* bgp_node_destroy
*/
static void
bgp_node_destroy (route_table_delegate_t *delegate,
struct route_table *table, struct route_node *node)
static void bgp_node_destroy(route_table_delegate_t *delegate,
struct route_table *table, struct route_node *node)
{
struct bgp_node *bgp_node;
bgp_node = bgp_node_from_rnode (node);
XFREE (MTYPE_BGP_NODE, bgp_node);
struct bgp_node *bgp_node;
bgp_node = bgp_node_from_rnode(node);
XFREE(MTYPE_BGP_NODE, bgp_node);
}
/*
* Function vector to customize the behavior of the route table
* library for BGP route tables.
*/
route_table_delegate_t bgp_table_delegate = {
.create_node = bgp_node_create,
.destroy_node = bgp_node_destroy
};
route_table_delegate_t bgp_table_delegate = {.create_node = bgp_node_create,
.destroy_node = bgp_node_destroy};
/*
* bgp_table_init
*/
struct bgp_table *
bgp_table_init (afi_t afi, safi_t safi)
struct bgp_table *bgp_table_init(afi_t afi, safi_t safi)
{
struct bgp_table *rt;
struct bgp_table *rt;
rt = XCALLOC (MTYPE_BGP_TABLE, sizeof (struct bgp_table));
rt = XCALLOC(MTYPE_BGP_TABLE, sizeof(struct bgp_table));
rt->route_table = route_table_init_with_delegate (&bgp_table_delegate);
rt->route_table = route_table_init_with_delegate(&bgp_table_delegate);
/*
* Set up back pointer to bgp_table.
*/
rt->route_table->info = rt;
/*
* Set up back pointer to bgp_table.
*/
rt->route_table->info = rt;
bgp_table_lock (rt);
rt->afi = afi;
rt->safi = safi;
bgp_table_lock(rt);
rt->afi = afi;
rt->safi = safi;
return rt;
return rt;
}

View File

@ -21,42 +21,41 @@
#ifndef _QUAGGA_BGP_TABLE_H
#define _QUAGGA_BGP_TABLE_H
#include "mpls.h"
#include "table.h"
struct bgp_table
{
/* afi/safi of this table */
afi_t afi;
safi_t safi;
int lock;
struct bgp_table {
/* afi/safi of this table */
afi_t afi;
safi_t safi;
struct route_table *route_table;
uint64_t version;
int lock;
struct route_table *route_table;
uint64_t version;
};
struct bgp_node
{
/*
* CAUTION
*
* These fields must be the very first fields in this structure.
*
* @see bgp_node_to_rnode
* @see bgp_node_from_rnode
*/
ROUTE_NODE_FIELDS
struct bgp_node {
/*
* CAUTION
*
* These fields must be the very first fields in this structure.
*
* @see bgp_node_to_rnode
* @see bgp_node_from_rnode
*/
ROUTE_NODE_FIELDS
struct bgp_adj_out *adj_out;
struct bgp_adj_out *adj_out;
struct bgp_adj_in *adj_in;
struct bgp_adj_in *adj_in;
struct bgp_node *prn;
struct bgp_node *prn;
u_char local_label[3];
mpls_label_t local_label;
uint64_t version;
u_char flags;
uint64_t version;
u_char flags;
#define BGP_NODE_PROCESS_SCHEDULED (1 << 0)
#define BGP_NODE_USER_CLEAR (1 << 1)
#define BGP_NODE_LABEL_CHANGED (1 << 2)
@ -65,19 +64,18 @@ struct bgp_node
/*
* bgp_table_iter_t
*
*
* Structure that holds state for iterating over a bgp table.
*/
typedef struct bgp_table_iter_t_
{
struct bgp_table *table;
route_table_iter_t rt_iter;
typedef struct bgp_table_iter_t_ {
struct bgp_table *table;
route_table_iter_t rt_iter;
} bgp_table_iter_t;
extern struct bgp_table *bgp_table_init (afi_t, safi_t);
extern void bgp_table_lock (struct bgp_table *);
extern void bgp_table_unlock (struct bgp_table *);
extern void bgp_table_finish (struct bgp_table **);
extern struct bgp_table *bgp_table_init(afi_t, safi_t);
extern void bgp_table_lock(struct bgp_table *);
extern void bgp_table_unlock(struct bgp_table *);
extern void bgp_table_finish(struct bgp_table **);
/*
@ -85,10 +83,9 @@ extern void bgp_table_finish (struct bgp_table **);
*
* Returns the bgp_node structure corresponding to a route_node.
*/
static inline struct bgp_node *
bgp_node_from_rnode (struct route_node *rnode)
static inline struct bgp_node *bgp_node_from_rnode(struct route_node *rnode)
{
return (struct bgp_node *) rnode;
return (struct bgp_node *)rnode;
}
/*
@ -96,10 +93,9 @@ bgp_node_from_rnode (struct route_node *rnode)
*
* Returns the route_node structure corresponding to a bgp_node.
*/
static inline struct route_node *
bgp_node_to_rnode (struct bgp_node *node)
static inline struct route_node *bgp_node_to_rnode(struct bgp_node *node)
{
return (struct route_node *) node;
return (struct route_node *)node;
}
/*
@ -107,10 +103,9 @@ bgp_node_to_rnode (struct bgp_node *node)
*
* Returns the bgp_table that the given node is in.
*/
static inline struct bgp_table *
bgp_node_table (struct bgp_node *node)
static inline struct bgp_table *bgp_node_table(struct bgp_node *node)
{
return bgp_node_to_rnode (node)->table->info;
return bgp_node_to_rnode(node)->table->info;
}
/*
@ -118,19 +113,17 @@ bgp_node_table (struct bgp_node *node)
*
* Gets the parent node of the given node without locking it.
*/
static inline struct bgp_node *
bgp_node_parent_nolock (struct bgp_node *node)
static inline struct bgp_node *bgp_node_parent_nolock(struct bgp_node *node)
{
return bgp_node_from_rnode (node->parent);
return bgp_node_from_rnode(node->parent);
}
/*
* bgp_unlock_node
*/
static inline void
bgp_unlock_node (struct bgp_node *node)
static inline void bgp_unlock_node(struct bgp_node *node)
{
route_unlock_node (bgp_node_to_rnode (node));
route_unlock_node(bgp_node_to_rnode(node));
}
/*
@ -141,183 +134,173 @@ bgp_unlock_node (struct bgp_node *node)
* @see bgp_table_top
*/
static inline struct bgp_node *
bgp_table_top_nolock (const struct bgp_table *const table)
bgp_table_top_nolock(const struct bgp_table *const table)
{
return bgp_node_from_rnode (table->route_table->top);
return bgp_node_from_rnode(table->route_table->top);
}
/*
* bgp_table_top
*/
static inline struct bgp_node *
bgp_table_top (const struct bgp_table *const table)
bgp_table_top(const struct bgp_table *const table)
{
return bgp_node_from_rnode (route_top (table->route_table));
return bgp_node_from_rnode(route_top(table->route_table));
}
/*
* bgp_route_next
*/
static inline struct bgp_node *
bgp_route_next (struct bgp_node *node)
static inline struct bgp_node *bgp_route_next(struct bgp_node *node)
{
return bgp_node_from_rnode (route_next (bgp_node_to_rnode (node)));
return bgp_node_from_rnode(route_next(bgp_node_to_rnode(node)));
}
/*
* bgp_route_next_until
*/
static inline struct bgp_node *
bgp_route_next_until (struct bgp_node *node, struct bgp_node *limit)
static inline struct bgp_node *bgp_route_next_until(struct bgp_node *node,
struct bgp_node *limit)
{
struct route_node *rnode;
struct route_node *rnode;
rnode = route_next_until (bgp_node_to_rnode (node),
bgp_node_to_rnode (limit));
return bgp_node_from_rnode (rnode);
rnode = route_next_until(bgp_node_to_rnode(node),
bgp_node_to_rnode(limit));
return bgp_node_from_rnode(rnode);
}
/*
* bgp_node_get
*/
static inline struct bgp_node *
bgp_node_get (struct bgp_table *const table, struct prefix *p)
static inline struct bgp_node *bgp_node_get(struct bgp_table *const table,
struct prefix *p)
{
return bgp_node_from_rnode (route_node_get (table->route_table, p));
return bgp_node_from_rnode(route_node_get(table->route_table, p));
}
/*
* bgp_node_lookup
*/
static inline struct bgp_node *
bgp_node_lookup (const struct bgp_table *const table, struct prefix *p)
bgp_node_lookup(const struct bgp_table *const table, struct prefix *p)
{
return bgp_node_from_rnode (route_node_lookup (table->route_table, p));
return bgp_node_from_rnode(route_node_lookup(table->route_table, p));
}
/*
* bgp_lock_node
*/
static inline struct bgp_node *
bgp_lock_node (struct bgp_node *node)
static inline struct bgp_node *bgp_lock_node(struct bgp_node *node)
{
return bgp_node_from_rnode (route_lock_node (bgp_node_to_rnode (node)));
return bgp_node_from_rnode(route_lock_node(bgp_node_to_rnode(node)));
}
/*
* bgp_node_match
*/
static inline struct bgp_node *
bgp_node_match (const struct bgp_table *table, struct prefix *p)
static inline struct bgp_node *bgp_node_match(const struct bgp_table *table,
struct prefix *p)
{
return bgp_node_from_rnode (route_node_match (table->route_table, p));
return bgp_node_from_rnode(route_node_match(table->route_table, p));
}
/*
* bgp_node_match_ipv4
*/
static inline struct bgp_node *
bgp_node_match_ipv4 (const struct bgp_table *table, struct in_addr *addr)
bgp_node_match_ipv4(const struct bgp_table *table, struct in_addr *addr)
{
return bgp_node_from_rnode (route_node_match_ipv4 (table->route_table,
addr));
return bgp_node_from_rnode(
route_node_match_ipv4(table->route_table, addr));
}
/*
* bgp_node_match_ipv6
*/
static inline struct bgp_node *
bgp_node_match_ipv6 (const struct bgp_table *table, struct in6_addr *addr)
bgp_node_match_ipv6(const struct bgp_table *table, struct in6_addr *addr)
{
return bgp_node_from_rnode (route_node_match_ipv6 (table->route_table,
addr));
return bgp_node_from_rnode(
route_node_match_ipv6(table->route_table, addr));
}
static inline unsigned long
bgp_table_count (const struct bgp_table *const table)
static inline unsigned long bgp_table_count(const struct bgp_table *const table)
{
return route_table_count (table->route_table);
return route_table_count(table->route_table);
}
/*
* bgp_table_get_next
*/
static inline struct bgp_node *
bgp_table_get_next (const struct bgp_table *table, struct prefix *p)
static inline struct bgp_node *bgp_table_get_next(const struct bgp_table *table,
struct prefix *p)
{
return bgp_node_from_rnode (route_table_get_next (table->route_table, p));
return bgp_node_from_rnode(route_table_get_next(table->route_table, p));
}
/*
* bgp_table_iter_init
*/
static inline void
bgp_table_iter_init (bgp_table_iter_t * iter, struct bgp_table *table)
static inline void bgp_table_iter_init(bgp_table_iter_t *iter,
struct bgp_table *table)
{
bgp_table_lock (table);
iter->table = table;
route_table_iter_init (&iter->rt_iter, table->route_table);
bgp_table_lock(table);
iter->table = table;
route_table_iter_init(&iter->rt_iter, table->route_table);
}
/*
* bgp_table_iter_next
*/
static inline struct bgp_node *
bgp_table_iter_next (bgp_table_iter_t * iter)
static inline struct bgp_node *bgp_table_iter_next(bgp_table_iter_t *iter)
{
return bgp_node_from_rnode (route_table_iter_next (&iter->rt_iter));
return bgp_node_from_rnode(route_table_iter_next(&iter->rt_iter));
}
/*
* bgp_table_iter_cleanup
*/
static inline void
bgp_table_iter_cleanup (bgp_table_iter_t * iter)
static inline void bgp_table_iter_cleanup(bgp_table_iter_t *iter)
{
route_table_iter_cleanup (&iter->rt_iter);
bgp_table_unlock (iter->table);
iter->table = NULL;
route_table_iter_cleanup(&iter->rt_iter);
bgp_table_unlock(iter->table);
iter->table = NULL;
}
/*
* bgp_table_iter_pause
*/
static inline void
bgp_table_iter_pause (bgp_table_iter_t * iter)
static inline void bgp_table_iter_pause(bgp_table_iter_t *iter)
{
route_table_iter_pause (&iter->rt_iter);
route_table_iter_pause(&iter->rt_iter);
}
/*
* bgp_table_iter_is_done
*/
static inline int
bgp_table_iter_is_done (bgp_table_iter_t * iter)
static inline int bgp_table_iter_is_done(bgp_table_iter_t *iter)
{
return route_table_iter_is_done (&iter->rt_iter);
return route_table_iter_is_done(&iter->rt_iter);
}
/*
* bgp_table_iter_started
*/
static inline int
bgp_table_iter_started (bgp_table_iter_t * iter)
static inline int bgp_table_iter_started(bgp_table_iter_t *iter)
{
return route_table_iter_started (&iter->rt_iter);
return route_table_iter_started(&iter->rt_iter);
}
/* This would benefit from a real atomic operation...
* until then. */
static inline uint64_t
bgp_table_next_version (struct bgp_table *table)
static inline uint64_t bgp_table_next_version(struct bgp_table *table)
{
return ++table->version;
return ++table->version;
}
static inline uint64_t
bgp_table_version (struct bgp_table *table)
static inline uint64_t bgp_table_version(struct bgp_table *table)
{
return table->version;
return table->version;
}
#endif /* _QUAGGA_BGP_TABLE_H */

File diff suppressed because it is too large Load Diff

View File

@ -31,46 +31,34 @@
#define BGP_DEFAULT_SUBGROUP_COALESCE_TIME 200
#define PEER_UPDGRP_FLAGS (PEER_FLAG_LOCAL_AS_NO_PREPEND | \
PEER_FLAG_LOCAL_AS_REPLACE_AS)
#define PEER_UPDGRP_FLAGS \
(PEER_FLAG_LOCAL_AS_NO_PREPEND | PEER_FLAG_LOCAL_AS_REPLACE_AS)
#define PEER_UPDGRP_AF_FLAGS (PEER_FLAG_SEND_COMMUNITY | \
PEER_FLAG_SEND_EXT_COMMUNITY | \
PEER_FLAG_DEFAULT_ORIGINATE | \
PEER_FLAG_REFLECTOR_CLIENT | \
PEER_FLAG_RSERVER_CLIENT | \
PEER_FLAG_NEXTHOP_SELF | \
PEER_FLAG_NEXTHOP_UNCHANGED | \
PEER_FLAG_FORCE_NEXTHOP_SELF | \
PEER_FLAG_AS_PATH_UNCHANGED | \
PEER_FLAG_MED_UNCHANGED | \
PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED | \
PEER_FLAG_REMOVE_PRIVATE_AS | \
PEER_FLAG_REMOVE_PRIVATE_AS_ALL | \
PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE | \
PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE | \
PEER_FLAG_ADDPATH_TX_ALL_PATHS | \
PEER_FLAG_ADDPATH_TX_BESTPATH_PER_AS | \
PEER_FLAG_AS_OVERRIDE)
#define PEER_UPDGRP_AF_FLAGS \
(PEER_FLAG_SEND_COMMUNITY | PEER_FLAG_SEND_EXT_COMMUNITY \
| PEER_FLAG_DEFAULT_ORIGINATE | PEER_FLAG_REFLECTOR_CLIENT \
| PEER_FLAG_RSERVER_CLIENT | PEER_FLAG_NEXTHOP_SELF \
| PEER_FLAG_NEXTHOP_UNCHANGED | PEER_FLAG_FORCE_NEXTHOP_SELF \
| PEER_FLAG_AS_PATH_UNCHANGED | PEER_FLAG_MED_UNCHANGED \
| PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED | PEER_FLAG_REMOVE_PRIVATE_AS \
| PEER_FLAG_REMOVE_PRIVATE_AS_ALL \
| PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE \
| PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE \
| PEER_FLAG_ADDPATH_TX_ALL_PATHS \
| PEER_FLAG_ADDPATH_TX_BESTPATH_PER_AS | PEER_FLAG_AS_OVERRIDE)
#define PEER_UPDGRP_CAP_FLAGS (PEER_CAP_AS4_RCV)
#define PEER_UPDGRP_AF_CAP_FLAGS (PEER_CAP_ORF_PREFIX_SM_RCV | \
PEER_CAP_ORF_PREFIX_SM_OLD_RCV |\
PEER_CAP_ADDPATH_AF_TX_ADV |\
PEER_CAP_ADDPATH_AF_RX_RCV |\
PEER_CAP_ENHE_AF_NEGO)
#define PEER_UPDGRP_AF_CAP_FLAGS \
(PEER_CAP_ORF_PREFIX_SM_RCV | PEER_CAP_ORF_PREFIX_SM_OLD_RCV \
| PEER_CAP_ADDPATH_AF_TX_ADV | PEER_CAP_ADDPATH_AF_RX_RCV \
| PEER_CAP_ENHE_AF_NEGO)
typedef enum
{
BGP_ATTR_VEC_NH = 0,
BGP_ATTR_VEC_MAX
} bpacket_attr_vec_type;
typedef enum { BGP_ATTR_VEC_NH = 0, BGP_ATTR_VEC_MAX } bpacket_attr_vec_type;
typedef struct
{
u_int32_t flags;
unsigned long offset;
typedef struct {
u_int32_t flags;
unsigned long offset;
} bpacket_attr_vec;
#define BPKT_ATTRVEC_FLAGS_UPDATED (1 << 0)
@ -81,28 +69,25 @@ typedef struct
#define BPKT_ATTRVEC_FLAGS_RMAP_IPV6_GNH_CHANGED (1 << 5)
#define BPKT_ATTRVEC_FLAGS_RMAP_IPV6_LNH_CHANGED (1 << 6)
typedef struct bpacket_attr_vec_arr
{
bpacket_attr_vec entries[BGP_ATTR_VEC_MAX];
typedef struct bpacket_attr_vec_arr {
bpacket_attr_vec entries[BGP_ATTR_VEC_MAX];
} bpacket_attr_vec_arr;
struct bpacket
{
/* for being part of an update subgroup's message list */
TAILQ_ENTRY (bpacket) pkt_train;
struct bpacket {
/* for being part of an update subgroup's message list */
TAILQ_ENTRY(bpacket) pkt_train;
/* list of peers (well, peer_afs) that the packet needs to be sent to */
LIST_HEAD (pkt_peer_list, peer_af) peers;
/* list of peers (well, peer_afs) that the packet needs to be sent to */
LIST_HEAD(pkt_peer_list, peer_af) peers;
struct stream *buffer;
bpacket_attr_vec_arr arr;
struct stream *buffer;
bpacket_attr_vec_arr arr;
unsigned int ver;
unsigned int ver;
};
struct bpacket_queue
{
TAILQ_HEAD (pkt_queue, bpacket) pkts;
struct bpacket_queue {
TAILQ_HEAD(pkt_queue, bpacket) pkts;
#if 0
/* A dummy packet that is used to thread all peers that have
@ -110,149 +95,146 @@ struct bpacket_queue
struct bpacket sentinel;
#endif
unsigned int conf_max_count;
unsigned int curr_count;
unsigned int hwm_count;
unsigned int max_count_reached_count;
unsigned int conf_max_count;
unsigned int curr_count;
unsigned int hwm_count;
unsigned int max_count_reached_count;
};
struct update_group
{
/* back pointer to the BGP instance */
struct bgp *bgp;
struct update_group {
/* back pointer to the BGP instance */
struct bgp *bgp;
/* list of subgroups that belong to the update group */
LIST_HEAD (subgrp_list, update_subgroup) subgrps;
/* list of subgroups that belong to the update group */
LIST_HEAD(subgrp_list, update_subgroup) subgrps;
/* lazy way to store configuration common to all peers
hash function will compute from this data */
struct peer *conf;
/* lazy way to store configuration common to all peers
hash function will compute from this data */
struct peer *conf;
afi_t afi;
safi_t safi;
int afid;
afi_t afi;
safi_t safi;
int afid;
uint64_t id;
time_t uptime;
uint64_t id;
time_t uptime;
u_int32_t join_events;
u_int32_t prune_events;
u_int32_t merge_events;
u_int32_t updgrp_switch_events;
u_int32_t peer_refreshes_combined;
u_int32_t adj_count;
u_int32_t split_events;
u_int32_t merge_checks_triggered;
u_int32_t join_events;
u_int32_t prune_events;
u_int32_t merge_events;
u_int32_t updgrp_switch_events;
u_int32_t peer_refreshes_combined;
u_int32_t adj_count;
u_int32_t split_events;
u_int32_t merge_checks_triggered;
u_int32_t subgrps_created;
u_int32_t subgrps_deleted;
u_int32_t subgrps_created;
u_int32_t subgrps_deleted;
u_int32_t num_dbg_en_peers;
u_int32_t num_dbg_en_peers;
};
/*
* Shorthand for a global statistics counter.
*/
#define UPDGRP_GLOBAL_STAT(updgrp, stat) \
((updgrp)->bgp->update_group_stats.stat)
#define UPDGRP_GLOBAL_STAT(updgrp, stat) \
((updgrp)->bgp->update_group_stats.stat)
/*
* Add the given value to a counter on an update group and the bgp
* instance.
*/
#define UPDGRP_INCR_STAT_BY(updgrp, stat, value) \
do { \
(updgrp)->stat += (value); \
UPDGRP_GLOBAL_STAT(updgrp, stat) += (value); \
} while (0)
#define UPDGRP_INCR_STAT_BY(updgrp, stat, value) \
do { \
(updgrp)->stat += (value); \
UPDGRP_GLOBAL_STAT(updgrp, stat) += (value); \
} while (0)
/*
* Increment a counter on a update group and its parent structures.
*/
#define UPDGRP_INCR_STAT(subgrp, stat) \
UPDGRP_INCR_STAT_BY(subgrp, stat, 1)
#define UPDGRP_INCR_STAT(subgrp, stat) UPDGRP_INCR_STAT_BY(subgrp, stat, 1)
struct update_subgroup
{
/* back pointer to the parent update group */
struct update_group *update_group;
struct update_subgroup {
/* back pointer to the parent update group */
struct update_group *update_group;
/* list of peers that belong to the subgroup */
LIST_HEAD (peer_list, peer_af) peers;
int peer_count;
/* list of peers that belong to the subgroup */
LIST_HEAD(peer_list, peer_af) peers;
int peer_count;
/* for being part of an update group's subgroup list */
LIST_ENTRY (update_subgroup) updgrp_train;
/* for being part of an update group's subgroup list */
LIST_ENTRY(update_subgroup) updgrp_train;
struct bpacket_queue pkt_queue;
struct bpacket_queue pkt_queue;
/*
* List of adj-out structures for this subgroup.
* It essentially represents the snapshot of every prefix that
* has been advertised to the members of the subgroup
*/
TAILQ_HEAD (adjout_queue, bgp_adj_out) adjq;
/*
* List of adj-out structures for this subgroup.
* It essentially represents the snapshot of every prefix that
* has been advertised to the members of the subgroup
*/
TAILQ_HEAD(adjout_queue, bgp_adj_out) adjq;
/* packet buffer for update generation */
struct stream *work;
/* packet buffer for update generation */
struct stream *work;
/* We use a separate stream to encode MP_REACH_NLRI for efficient
* NLRI packing. peer->work stores all the other attributes. The
* actual packet is then constructed by concatenating the two.
*/
struct stream *scratch;
/* We use a separate stream to encode MP_REACH_NLRI for efficient
* NLRI packing. peer->work stores all the other attributes. The
* actual packet is then constructed by concatenating the two.
*/
struct stream *scratch;
/* synchronization list and time */
struct bgp_synchronize *sync;
/* synchronization list and time */
struct bgp_synchronize *sync;
/* send prefix count */
unsigned long scount;
/* send prefix count */
unsigned long scount;
/* announcement attribute hash */
struct hash *hash;
/* announcement attribute hash */
struct hash *hash;
struct thread *t_coalesce;
u_int32_t v_coalesce;
struct thread *t_coalesce;
u_int32_t v_coalesce;
struct thread *t_merge_check;
struct thread *t_merge_check;
/* table version that the subgroup has caught up to. */
uint64_t version;
/* table version that the subgroup has caught up to. */
uint64_t version;
/* version maintained to record adj changes */
uint64_t adj_version;
/* version maintained to record adj changes */
uint64_t adj_version;
time_t uptime;
time_t uptime;
/*
* Identifying information about the subgroup that this subgroup was split
* from, if any.
*/
struct
{
uint64_t update_group_id;
uint64_t subgroup_id;
} split_from;
/*
* Identifying information about the subgroup that this subgroup was
* split
* from, if any.
*/
struct {
uint64_t update_group_id;
uint64_t subgroup_id;
} split_from;
u_int32_t join_events;
u_int32_t prune_events;
u_int32_t join_events;
u_int32_t prune_events;
/*
* This is bumped up when another subgroup merges into this one.
*/
u_int32_t merge_events;
u_int32_t updgrp_switch_events;
u_int32_t peer_refreshes_combined;
u_int32_t adj_count;
u_int32_t split_events;
u_int32_t merge_checks_triggered;
/*
* This is bumped up when another subgroup merges into this one.
*/
u_int32_t merge_events;
u_int32_t updgrp_switch_events;
u_int32_t peer_refreshes_combined;
u_int32_t adj_count;
u_int32_t split_events;
u_int32_t merge_checks_triggered;
uint64_t id;
uint64_t id;
u_int16_t sflags;
u_int16_t sflags;
/* Subgroup flags, see below */
u_int16_t flags;
/* Subgroup flags, see below */
u_int16_t flags;
};
/*
@ -267,43 +249,41 @@ struct update_subgroup
* Add the given value to the specified counter on a subgroup and its
* parent structures.
*/
#define SUBGRP_INCR_STAT_BY(subgrp, stat, value) \
do { \
(subgrp)->stat += (value); \
if ((subgrp)->update_group) \
UPDGRP_INCR_STAT_BY((subgrp)->update_group, stat, value); \
} while (0)
#define SUBGRP_INCR_STAT_BY(subgrp, stat, value) \
do { \
(subgrp)->stat += (value); \
if ((subgrp)->update_group) \
UPDGRP_INCR_STAT_BY((subgrp)->update_group, stat, \
value); \
} while (0)
/*
* Increment a counter on a subgroup and its parent structures.
*/
#define SUBGRP_INCR_STAT(subgrp, stat) \
SUBGRP_INCR_STAT_BY(subgrp, stat, 1)
#define SUBGRP_INCR_STAT(subgrp, stat) SUBGRP_INCR_STAT_BY(subgrp, stat, 1)
/*
* Decrement a counter on a subgroup and its parent structures.
*/
#define SUBGRP_DECR_STAT(subgrp, stat) \
SUBGRP_INCR_STAT_BY(subgrp, stat, -1)
#define SUBGRP_DECR_STAT(subgrp, stat) SUBGRP_INCR_STAT_BY(subgrp, stat, -1)
typedef int (*updgrp_walkcb) (struct update_group * updgrp, void *ctx);
typedef int (*updgrp_walkcb)(struct update_group *updgrp, void *ctx);
/* really a private structure */
struct updwalk_context
{
struct vty *vty;
struct bgp_node *rn;
struct bgp_info *ri;
uint64_t updgrp_id;
uint64_t subgrp_id;
bgp_policy_type_e policy_type;
const char *policy_name;
int policy_event_start_flag;
int policy_route_update;
updgrp_walkcb cb;
void *context;
u_int8_t flags;
struct updwalk_context {
struct vty *vty;
struct bgp_node *rn;
struct bgp_info *ri;
uint64_t updgrp_id;
uint64_t subgrp_id;
bgp_policy_type_e policy_type;
const char *policy_name;
int policy_event_start_flag;
int policy_route_update;
updgrp_walkcb cb;
void *context;
u_int8_t flags;
#define UPDWALK_FLAGS_ADVQUEUE (1 << 0)
#define UPDWALK_FLAGS_ADVERTISED (1 << 1)
@ -321,8 +301,7 @@ struct updwalk_context
#define UPDGRP_AFI(u) ((u)->afi)
#define UPDGRP_SAFI(u) ((u)->safi)
#define UPDGRP_INST(u) ((u)->bgp)
#define UPDGRP_AFFLAGS(u) \
((u)->conf->af_flags[UPDGRP_AFI(u)][UPDGRP_SAFI(u)])
#define UPDGRP_AFFLAGS(u) ((u)->conf->af_flags[UPDGRP_AFI(u)][UPDGRP_SAFI(u)])
#define UPDGRP_DBG_ON(u) ((u)->num_dbg_en_peers)
#define UPDGRP_PEER_DBG_EN(u) (((u)->num_dbg_en_peers)++)
#define UPDGRP_PEER_DBG_DIS(u) (((u)->num_dbg_en_peers)--)
@ -341,149 +320,137 @@ struct updwalk_context
/*
* Walk all subgroups in an update group.
*/
#define UPDGRP_FOREACH_SUBGRP(updgrp, subgrp) \
LIST_FOREACH(subgrp, &((updgrp)->subgrps), updgrp_train)
#define UPDGRP_FOREACH_SUBGRP(updgrp, subgrp) \
LIST_FOREACH(subgrp, &((updgrp)->subgrps), updgrp_train)
#define UPDGRP_FOREACH_SUBGRP_SAFE(updgrp, subgrp, tmp_subgrp) \
LIST_FOREACH_SAFE(subgrp, &((updgrp)->subgrps), updgrp_train, tmp_subgrp)
#define UPDGRP_FOREACH_SUBGRP_SAFE(updgrp, subgrp, tmp_subgrp) \
LIST_FOREACH_SAFE(subgrp, &((updgrp)->subgrps), updgrp_train, \
tmp_subgrp)
#define SUBGRP_FOREACH_PEER(subgrp, paf) \
LIST_FOREACH(paf, &(subgrp->peers), subgrp_train)
#define SUBGRP_FOREACH_PEER(subgrp, paf) \
LIST_FOREACH(paf, &(subgrp->peers), subgrp_train)
#define SUBGRP_FOREACH_PEER_SAFE(subgrp, paf, temp_paf) \
LIST_FOREACH_SAFE(paf, &(subgrp->peers), subgrp_train, temp_paf)
#define SUBGRP_FOREACH_PEER_SAFE(subgrp, paf, temp_paf) \
LIST_FOREACH_SAFE(paf, &(subgrp->peers), subgrp_train, temp_paf)
#define SUBGRP_FOREACH_ADJ(subgrp, adj) \
TAILQ_FOREACH(adj, &(subgrp->adjq), subgrp_adj_train)
#define SUBGRP_FOREACH_ADJ(subgrp, adj) \
TAILQ_FOREACH(adj, &(subgrp->adjq), subgrp_adj_train)
#define SUBGRP_FOREACH_ADJ_SAFE(subgrp, adj, adj_temp) \
TAILQ_FOREACH_SAFE(adj, &(subgrp->adjq), subgrp_adj_train, adj_temp)
#define SUBGRP_FOREACH_ADJ_SAFE(subgrp, adj, adj_temp) \
TAILQ_FOREACH_SAFE(adj, &(subgrp->adjq), subgrp_adj_train, adj_temp)
/* Prototypes. */
/* bgp_updgrp.c */
extern void update_bgp_group_init (struct bgp *);
extern void udpate_bgp_group_free (struct bgp *);
extern void update_bgp_group_init(struct bgp *);
extern void udpate_bgp_group_free(struct bgp *);
extern void
update_group_show (struct bgp *bgp, afi_t afi, safi_t safi, struct vty *vty, uint64_t subgrp_id);
extern void update_group_show_stats (struct bgp *bgp, struct vty *vty);
extern void update_group_adjust_peer (struct peer_af *paf);
extern int update_group_adjust_soloness (struct peer *peer, int set);
extern void update_group_show(struct bgp *bgp, afi_t afi, safi_t safi,
struct vty *vty, uint64_t subgrp_id);
extern void update_group_show_stats(struct bgp *bgp, struct vty *vty);
extern void update_group_adjust_peer(struct peer_af *paf);
extern int update_group_adjust_soloness(struct peer *peer, int set);
extern void
update_subgroup_remove_peer (struct update_subgroup *, struct peer_af *);
extern struct bgp_table *update_subgroup_rib (struct update_subgroup *);
extern void
update_subgroup_split_peer (struct peer_af *, struct update_group *);
extern void update_subgroup_remove_peer(struct update_subgroup *,
struct peer_af *);
extern struct bgp_table *update_subgroup_rib(struct update_subgroup *);
extern void update_subgroup_split_peer(struct peer_af *, struct update_group *);
extern int update_subgroup_check_merge(struct update_subgroup *, const char *);
extern int update_subgroup_trigger_merge_check(struct update_subgroup *,
int force);
extern void update_group_policy_update(struct bgp *bgp, bgp_policy_type_e ptype,
const char *pname, int route_update,
int start_event);
extern void update_group_af_walk(struct bgp *bgp, afi_t afi, safi_t safi,
updgrp_walkcb cb, void *ctx);
extern void update_group_walk(struct bgp *bgp, updgrp_walkcb cb, void *ctx);
extern void update_group_periodic_merge(struct bgp *bgp);
extern int
update_subgroup_check_merge (struct update_subgroup *, const char *);
extern int
update_subgroup_trigger_merge_check (struct update_subgroup *,
int force);
extern void update_group_policy_update (struct bgp *bgp,
bgp_policy_type_e ptype, const char *pname,
int route_update, int start_event);
extern void update_group_af_walk (struct bgp *bgp, afi_t afi, safi_t safi,
updgrp_walkcb cb, void *ctx);
extern void update_group_walk (struct bgp *bgp, updgrp_walkcb cb, void *ctx);
extern void update_group_periodic_merge (struct bgp *bgp);
extern int update_group_refresh_default_originate_route_map (struct thread *thread);
extern void update_group_start_advtimer (struct bgp *bgp);
update_group_refresh_default_originate_route_map(struct thread *thread);
extern void update_group_start_advtimer(struct bgp *bgp);
extern void update_subgroup_inherit_info (struct update_subgroup *to,
struct update_subgroup *from);
extern void update_subgroup_inherit_info(struct update_subgroup *to,
struct update_subgroup *from);
/* bgp_updgrp_packet.c */
extern struct bpacket *bpacket_alloc (void);
extern void bpacket_free (struct bpacket *pkt);
extern void bpacket_queue_init (struct bpacket_queue *q);
extern void bpacket_queue_cleanup (struct bpacket_queue *q);
extern void bpacket_queue_sanity_check (struct bpacket_queue *q);
extern struct bpacket *bpacket_queue_add (struct bpacket_queue *q,
struct stream *s,
struct bpacket_attr_vec_arr
*vecarr);
struct bpacket *bpacket_queue_remove (struct bpacket_queue *q);
extern struct bpacket *bpacket_queue_first (struct bpacket_queue *q);
struct bpacket *bpacket_queue_last (struct bpacket_queue *q);
unsigned int bpacket_queue_length (struct bpacket_queue *q);
unsigned int bpacket_queue_hwm_length (struct bpacket_queue *q);
int bpacket_queue_is_full (struct bgp *bgp, struct bpacket_queue *q);
extern void bpacket_queue_advance_peer (struct peer_af *paf);
extern void bpacket_queue_remove_peer (struct peer_af *paf);
extern void bpacket_add_peer (struct bpacket *pkt, struct peer_af *paf);
unsigned int bpacket_queue_virtual_length (struct peer_af *paf);
extern void bpacket_queue_show_vty (struct bpacket_queue *q, struct vty *vty);
int subgroup_packets_to_build (struct update_subgroup *subgrp);
extern struct bpacket *subgroup_update_packet (struct update_subgroup *s);
extern struct bpacket *subgroup_withdraw_packet (struct update_subgroup *s);
extern struct stream *bpacket_reformat_for_peer (struct bpacket *pkt,
struct peer_af *paf);
extern void bpacket_attr_vec_arr_reset (struct bpacket_attr_vec_arr *vecarr);
extern void bpacket_attr_vec_arr_set_vec (struct bpacket_attr_vec_arr *vecarr,
bpacket_attr_vec_type type,
struct stream *s,
struct attr *attr);
extern void
subgroup_default_update_packet (struct update_subgroup *subgrp,
struct attr *attr, struct peer *from);
extern void subgroup_default_withdraw_packet (struct update_subgroup *subgrp);
extern struct bpacket *bpacket_alloc(void);
extern void bpacket_free(struct bpacket *pkt);
extern void bpacket_queue_init(struct bpacket_queue *q);
extern void bpacket_queue_cleanup(struct bpacket_queue *q);
extern void bpacket_queue_sanity_check(struct bpacket_queue *q);
extern struct bpacket *bpacket_queue_add(struct bpacket_queue *q,
struct stream *s,
struct bpacket_attr_vec_arr *vecarr);
struct bpacket *bpacket_queue_remove(struct bpacket_queue *q);
extern struct bpacket *bpacket_queue_first(struct bpacket_queue *q);
struct bpacket *bpacket_queue_last(struct bpacket_queue *q);
unsigned int bpacket_queue_length(struct bpacket_queue *q);
unsigned int bpacket_queue_hwm_length(struct bpacket_queue *q);
int bpacket_queue_is_full(struct bgp *bgp, struct bpacket_queue *q);
extern void bpacket_queue_advance_peer(struct peer_af *paf);
extern void bpacket_queue_remove_peer(struct peer_af *paf);
extern void bpacket_add_peer(struct bpacket *pkt, struct peer_af *paf);
unsigned int bpacket_queue_virtual_length(struct peer_af *paf);
extern void bpacket_queue_show_vty(struct bpacket_queue *q, struct vty *vty);
int subgroup_packets_to_build(struct update_subgroup *subgrp);
extern struct bpacket *subgroup_update_packet(struct update_subgroup *s);
extern struct bpacket *subgroup_withdraw_packet(struct update_subgroup *s);
extern struct stream *bpacket_reformat_for_peer(struct bpacket *pkt,
struct peer_af *paf);
extern void bpacket_attr_vec_arr_reset(struct bpacket_attr_vec_arr *vecarr);
extern void bpacket_attr_vec_arr_set_vec(struct bpacket_attr_vec_arr *vecarr,
bpacket_attr_vec_type type,
struct stream *s, struct attr *attr);
extern void subgroup_default_update_packet(struct update_subgroup *subgrp,
struct attr *attr,
struct peer *from);
extern void subgroup_default_withdraw_packet(struct update_subgroup *subgrp);
/* bgp_updgrp_adv.c */
extern struct bgp_advertise *bgp_advertise_clean_subgroup (struct
update_subgroup
*subgrp,
struct bgp_adj_out
*adj);
extern void update_group_show_adj_queue (struct bgp *bgp, afi_t afi,
extern struct bgp_advertise *
bgp_advertise_clean_subgroup(struct update_subgroup *subgrp,
struct bgp_adj_out *adj);
extern void update_group_show_adj_queue(struct bgp *bgp, afi_t afi, safi_t safi,
struct vty *vty, uint64_t id);
extern void update_group_show_advertised(struct bgp *bgp, afi_t afi,
safi_t safi, struct vty *vty,
uint64_t id);
extern void update_group_show_advertised (struct bgp *bgp, afi_t afi,
safi_t safi, struct vty *vty,
uint64_t id);
extern void update_group_show_packet_queue (struct bgp *bgp, afi_t afi,
safi_t safi, struct vty *vty,
uint64_t id);
extern void subgroup_announce_route (struct update_subgroup *subgrp);
extern void subgroup_announce_all (struct update_subgroup *subgrp);
extern void update_group_show_packet_queue(struct bgp *bgp, afi_t afi,
safi_t safi, struct vty *vty,
uint64_t id);
extern void subgroup_announce_route(struct update_subgroup *subgrp);
extern void subgroup_announce_all(struct update_subgroup *subgrp);
extern void
subgroup_default_originate (struct update_subgroup *subgrp, int withdraw);
extern void
group_announce_route (struct bgp *bgp, afi_t afi, safi_t safi,
struct bgp_node *rn, struct bgp_info *ri);
extern void subgroup_clear_table (struct update_subgroup *subgrp);
extern void update_group_announce (struct bgp *bgp);
extern void update_group_announce_rrclients (struct bgp *bgp);
extern void peer_af_announce_route (struct peer_af *paf, int combine);
extern struct bgp_adj_out *bgp_adj_out_alloc (struct update_subgroup *subgrp,
struct bgp_node *rn,
u_int32_t addpath_tx_id);
extern void bgp_adj_out_remove_subgroup (struct bgp_node *rn,
struct bgp_adj_out *adj,
struct update_subgroup *subgrp);
extern void
bgp_adj_out_set_subgroup (struct bgp_node *rn,
struct update_subgroup *subgrp,
struct attr *attr, struct bgp_info *binfo);
extern void
bgp_adj_out_unset_subgroup (struct bgp_node *rn,
struct update_subgroup *subgrp,
char withdraw,
u_int32_t addpath_tx_id);
void
subgroup_announce_table (struct update_subgroup *subgrp,
struct bgp_table *table);
extern void
subgroup_trigger_write (struct update_subgroup *subgrp);
extern void subgroup_default_originate(struct update_subgroup *subgrp,
int withdraw);
extern void group_announce_route(struct bgp *bgp, afi_t afi, safi_t safi,
struct bgp_node *rn, struct bgp_info *ri);
extern void subgroup_clear_table(struct update_subgroup *subgrp);
extern void update_group_announce(struct bgp *bgp);
extern void update_group_announce_rrclients(struct bgp *bgp);
extern void peer_af_announce_route(struct peer_af *paf, int combine);
extern struct bgp_adj_out *bgp_adj_out_alloc(struct update_subgroup *subgrp,
struct bgp_node *rn,
u_int32_t addpath_tx_id);
extern void bgp_adj_out_remove_subgroup(struct bgp_node *rn,
struct bgp_adj_out *adj,
struct update_subgroup *subgrp);
extern void bgp_adj_out_set_subgroup(struct bgp_node *rn,
struct update_subgroup *subgrp,
struct attr *attr, struct bgp_info *binfo);
extern void bgp_adj_out_unset_subgroup(struct bgp_node *rn,
struct update_subgroup *subgrp,
char withdraw, u_int32_t addpath_tx_id);
void subgroup_announce_table(struct update_subgroup *subgrp,
struct bgp_table *table);
extern void subgroup_trigger_write(struct update_subgroup *subgrp);
extern int
update_group_clear_update_dbg (struct update_group *updgrp, void *arg);
extern int update_group_clear_update_dbg(struct update_group *updgrp,
void *arg);
extern void update_bgp_group_free(struct bgp *bgp);
extern int bgp_addpath_encode_tx (struct peer *peer, afi_t afi, safi_t safi);
extern int bgp_addpath_tx_path (struct peer *peer, afi_t afi, safi_t safi,
struct bgp_info *ri);
extern int bgp_addpath_encode_tx(struct peer *peer, afi_t afi, safi_t safi);
extern int bgp_addpath_tx_path(struct peer *peer, afi_t afi, safi_t safi,
struct bgp_info *ri);
/*
* Inline functions
@ -492,18 +459,17 @@ extern int bgp_addpath_tx_path (struct peer *peer, afi_t afi, safi_t safi,
/*
* bpacket_queue_is_empty
*/
static inline int
bpacket_queue_is_empty (struct bpacket_queue *queue)
static inline int bpacket_queue_is_empty(struct bpacket_queue *queue)
{
/*
* The packet queue is empty if it only contains a sentinel.
*/
if (queue->curr_count != 1)
return 0;
/*
* The packet queue is empty if it only contains a sentinel.
*/
if (queue->curr_count != 1)
return 0;
assert (bpacket_queue_first (queue)->buffer == NULL);
return 1;
assert(bpacket_queue_first(queue)->buffer == NULL);
return 1;
}
/*
@ -511,10 +477,9 @@ bpacket_queue_is_empty (struct bpacket_queue *queue)
*
* Returns the packet after the given packet in a bpacket queue.
*/
static inline struct bpacket *
bpacket_next (struct bpacket *pkt)
static inline struct bpacket *bpacket_next(struct bpacket *pkt)
{
return TAILQ_NEXT (pkt, pkt_train);
return TAILQ_NEXT(pkt, pkt_train);
}
/*
@ -522,18 +487,16 @@ bpacket_next (struct bpacket *pkt)
*
* Adjust all peer_af structures for the given peer.
*/
static inline void
update_group_adjust_peer_afs (struct peer *peer)
static inline void update_group_adjust_peer_afs(struct peer *peer)
{
struct peer_af *paf;
int afidx;
struct peer_af *paf;
int afidx;
for (afidx = BGP_AF_START; afidx < BGP_AF_MAX; afidx++)
{
paf = peer->peer_af_array[afidx];
if (paf != NULL)
update_group_adjust_peer (paf);
}
for (afidx = BGP_AF_START; afidx < BGP_AF_MAX; afidx++) {
paf = peer->peer_af_array[afidx];
if (paf != NULL)
update_group_adjust_peer(paf);
}
}
/*
@ -541,53 +504,51 @@ update_group_adjust_peer_afs (struct peer *peer)
*
* Remove all peer_af structures for the given peer from their subgroups.
*/
static inline void
update_group_remove_peer_afs (struct peer *peer)
static inline void update_group_remove_peer_afs(struct peer *peer)
{
struct peer_af *paf;
int afidx;
struct peer_af *paf;
int afidx;
for (afidx = BGP_AF_START; afidx < BGP_AF_MAX; afidx++)
{
paf = peer->peer_af_array[afidx];
if (paf != NULL)
update_subgroup_remove_peer (PAF_SUBGRP (paf), paf);
}
for (afidx = BGP_AF_START; afidx < BGP_AF_MAX; afidx++) {
paf = peer->peer_af_array[afidx];
if (paf != NULL)
update_subgroup_remove_peer(PAF_SUBGRP(paf), paf);
}
}
/*
* update_subgroup_needs_refresh
*/
static inline int
update_subgroup_needs_refresh (const struct update_subgroup *subgrp)
update_subgroup_needs_refresh(const struct update_subgroup *subgrp)
{
if (CHECK_FLAG (subgrp->flags, SUBGRP_FLAG_NEEDS_REFRESH))
return 1;
else
return 0;
if (CHECK_FLAG(subgrp->flags, SUBGRP_FLAG_NEEDS_REFRESH))
return 1;
else
return 0;
}
/*
* update_subgroup_set_needs_refresh
*/
static inline void
update_subgroup_set_needs_refresh (struct update_subgroup *subgrp, int value)
update_subgroup_set_needs_refresh(struct update_subgroup *subgrp, int value)
{
if (value)
SET_FLAG (subgrp->flags, SUBGRP_FLAG_NEEDS_REFRESH);
else
UNSET_FLAG (subgrp->flags, SUBGRP_FLAG_NEEDS_REFRESH);
if (value)
SET_FLAG(subgrp->flags, SUBGRP_FLAG_NEEDS_REFRESH);
else
UNSET_FLAG(subgrp->flags, SUBGRP_FLAG_NEEDS_REFRESH);
}
static inline struct update_subgroup *
peer_subgroup (struct peer *peer, afi_t afi, safi_t safi)
static inline struct update_subgroup *peer_subgroup(struct peer *peer,
afi_t afi, safi_t safi)
{
struct peer_af *paf;
struct peer_af *paf;
paf = peer_af_find (peer, afi, safi);
if (paf)
return PAF_SUBGRP (paf);
return NULL;
paf = peer_af_find(peer, afi, safi);
if (paf)
return PAF_SUBGRP(paf);
return NULL;
}
/*
@ -595,34 +556,30 @@ peer_subgroup (struct peer *peer, afi_t afi, safi_t safi)
*
* Adjust all peer_af structures for the given peer.
*/
static inline void
bgp_announce_peer (struct peer *peer)
static inline void bgp_announce_peer(struct peer *peer)
{
struct peer_af *paf;
int afidx;
struct peer_af *paf;
int afidx;
for (afidx = BGP_AF_START; afidx < BGP_AF_MAX; afidx++)
{
paf = peer->peer_af_array[afidx];
if (paf != NULL)
subgroup_announce_all (PAF_SUBGRP (paf));
}
for (afidx = BGP_AF_START; afidx < BGP_AF_MAX; afidx++) {
paf = peer->peer_af_array[afidx];
if (paf != NULL)
subgroup_announce_all(PAF_SUBGRP(paf));
}
}
/**
* advertise_list_is_empty
*/
static inline int
advertise_list_is_empty (struct update_subgroup *subgrp)
static inline int advertise_list_is_empty(struct update_subgroup *subgrp)
{
if (!BGP_ADV_FIFO_EMPTY (&subgrp->sync->update) ||
!BGP_ADV_FIFO_EMPTY (&subgrp->sync->withdraw) ||
!BGP_ADV_FIFO_EMPTY (&subgrp->sync->withdraw_low))
{
return 0;
}
if (!BGP_ADV_FIFO_EMPTY(&subgrp->sync->update)
|| !BGP_ADV_FIFO_EMPTY(&subgrp->sync->withdraw)
|| !BGP_ADV_FIFO_EMPTY(&subgrp->sync->withdraw_low)) {
return 0;
}
return 1;
return 1;
}
#endif /* _QUAGGA_BGP_UPDGRP_H */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,4 @@
/*
/*
* Copyright 2015-2016, LabN Consulting, L.L.C.
*
* This program is free software; you can redistribute it and/or
@ -21,20 +21,20 @@
#if ENABLE_BGP_VNC
typedef enum {
BGP_VNC_SUBTLV_TYPE_LIFETIME=1,
BGP_VNC_SUBTLV_TYPE_RFPOPTION=2, /* deprecated */
BGP_VNC_SUBTLV_TYPE_LIFETIME = 1,
BGP_VNC_SUBTLV_TYPE_RFPOPTION = 2, /* deprecated */
} bgp_vnc_subtlv_types;
/*
* VNC Attribute subtlvs
*/
struct bgp_vnc_subtlv_lifetime {
uint32_t lifetime;
uint32_t lifetime;
};
struct bgp_vnc_subtlv_unaddr {
struct prefix un_address; /* IPv4 or IPv6; pfx length ignored */
struct prefix un_address; /* IPv4 or IPv6; pfx length ignored */
};
#endif /* ENABLE_BGP_VNC */
#endif /* ENABLE_BGP_VNC */
#endif /* _QUAGGA_BGP_VNC_TYPES_H */

View File

@ -30,171 +30,221 @@
#include "bgpd/bgp_mplsvpn.h"
#include "bgpd/bgp_vpn.h"
int
show_adj_route_vpn (struct vty *vty, struct peer *peer, struct prefix_rd *prd,
afi_t afi, safi_t safi, u_char use_json)
int show_adj_route_vpn(struct vty *vty, struct peer *peer,
struct prefix_rd *prd, afi_t afi, safi_t safi,
u_char use_json)
{
struct bgp *bgp;
struct bgp_table *table;
struct bgp_node *rn;
struct bgp_node *rm;
struct attr *attr;
int rd_header;
int header = 1;
json_object *json = NULL;
json_object *json_scode = NULL;
json_object *json_ocode = NULL;
json_object *json_routes = NULL;
json_object *json_array = NULL;
struct bgp *bgp;
struct bgp_table *table;
struct bgp_node *rn;
struct bgp_node *rm;
struct attr *attr;
int rd_header;
int header = 1;
json_object *json = NULL;
json_object *json_scode = NULL;
json_object *json_ocode = NULL;
json_object *json_routes = NULL;
json_object *json_array = NULL;
bgp = bgp_get_default ();
if (bgp == NULL)
{
if (!use_json)
vty_outln (vty, "No BGP process is configured");
return CMD_WARNING;
}
bgp = bgp_get_default();
if (bgp == NULL) {
if (!use_json)
vty_out(vty, "No BGP process is configured\n");
return CMD_WARNING;
}
if (use_json)
{
json_scode = json_object_new_object();
json_ocode = json_object_new_object();
json_routes = json_object_new_object();
json = json_object_new_object();
if (use_json) {
json_scode = json_object_new_object();
json_ocode = json_object_new_object();
json_routes = json_object_new_object();
json = json_object_new_object();
json_object_string_add(json_scode, "suppressed", "s");
json_object_string_add(json_scode, "damped", "d");
json_object_string_add(json_scode, "history", "h");
json_object_string_add(json_scode, "valid", "*");
json_object_string_add(json_scode, "best", ">");
json_object_string_add(json_scode, "internal", "i");
json_object_string_add(json_scode, "suppressed", "s");
json_object_string_add(json_scode, "damped", "d");
json_object_string_add(json_scode, "history", "h");
json_object_string_add(json_scode, "valid", "*");
json_object_string_add(json_scode, "best", ">");
json_object_string_add(json_scode, "internal", "i");
json_object_string_add(json_ocode, "igp", "i");
json_object_string_add(json_ocode, "egp", "e");
json_object_string_add(json_ocode, "incomplete", "?");
}
json_object_string_add(json_ocode, "igp", "i");
json_object_string_add(json_ocode, "egp", "e");
json_object_string_add(json_ocode, "incomplete", "?");
}
for (rn = bgp_table_top (bgp->rib[afi][SAFI_MPLS_VPN]); rn;
rn = bgp_route_next (rn))
{
if (prd && memcmp (rn->p.u.val, prd->val, 8) != 0)
continue;
for (rn = bgp_table_top(bgp->rib[afi][SAFI_MPLS_VPN]); rn;
rn = bgp_route_next(rn)) {
if (prd && memcmp(rn->p.u.val, prd->val, 8) != 0)
continue;
if ((table = rn->info) != NULL)
{
if (use_json)
json_array = json_object_new_array();
else
json_array = NULL;
if ((table = rn->info) != NULL) {
if (use_json)
json_array = json_object_new_array();
else
json_array = NULL;
rd_header = 1;
rd_header = 1;
for (rm = bgp_table_top (table); rm; rm = bgp_route_next (rm))
{
if ((attr = rm->info) != NULL)
{
if (header)
{
if (use_json)
{
json_object_int_add(json, "bgpTableVersion", 0);
json_object_string_add(json, "bgpLocalRouterId", inet_ntoa (bgp->router_id));
json_object_object_add(json, "bgpStatusCodes", json_scode);
json_object_object_add(json, "bgpOriginCodes", json_ocode);
}
else
{
vty_outln (vty, "BGP table version is 0, local router ID is %s",
inet_ntoa(bgp->router_id));
vty_outln (vty,
"Status codes: s suppressed, d damped, h history, * valid, > best, i - internal");
vty_outln (vty, "Origin codes: i - IGP, e - EGP, ? - incomplete%s",
VTYNL);
vty_outln (vty, V4_HEADER);
}
header = 0;
}
for (rm = bgp_table_top(table); rm;
rm = bgp_route_next(rm)) {
if ((attr = rm->info) != NULL) {
if (header) {
if (use_json) {
json_object_int_add(
json,
"bgpTableVersion",
0);
json_object_string_add(
json,
"bgpLocalRouterId",
inet_ntoa(
bgp->router_id));
json_object_object_add(
json,
"bgpStatusCodes",
json_scode);
json_object_object_add(
json,
"bgpOriginCodes",
json_ocode);
} else {
vty_out(vty,
"BGP table version is 0, local router ID is %s\n",
inet_ntoa(
bgp->router_id));
vty_out(vty,
"Status codes: s suppressed, d damped, h history, * valid, > best, i - internal\n");
vty_out(vty,
"Origin codes: i - IGP, e - EGP, ? - incomplete\n\n");
vty_out(vty, V4_HEADER);
}
header = 0;
}
if (rd_header)
{
u_int16_t type;
struct rd_as rd_as;
struct rd_ip rd_ip = {0};
if (rd_header) {
u_int16_t type;
struct rd_as rd_as;
struct rd_ip rd_ip = {0};
#if ENABLE_BGP_VNC
struct rd_vnc_eth rd_vnc_eth = {0};
struct rd_vnc_eth rd_vnc_eth = {
0};
#endif
u_char *pnt;
u_char *pnt;
pnt = rn->p.u.val;
pnt = rn->p.u.val;
/* Decode RD type. */
type = decode_rd_type (pnt);
/* Decode RD value. */
if (type == RD_TYPE_AS)
decode_rd_as (pnt + 2, &rd_as);
else if (type == RD_TYPE_AS4)
decode_rd_as4 (pnt + 2, &rd_as);
else if (type == RD_TYPE_IP)
decode_rd_ip (pnt + 2, &rd_ip);
/* Decode RD type. */
type = decode_rd_type(pnt);
/* Decode RD value. */
if (type == RD_TYPE_AS)
decode_rd_as(pnt + 2,
&rd_as);
else if (type == RD_TYPE_AS4)
decode_rd_as4(pnt + 2,
&rd_as);
else if (type == RD_TYPE_IP)
decode_rd_ip(pnt + 2,
&rd_ip);
#if ENABLE_BGP_VNC
else if (type == RD_TYPE_VNC_ETH)
decode_rd_vnc_eth (pnt, &rd_vnc_eth);
else if (type
== RD_TYPE_VNC_ETH)
decode_rd_vnc_eth(
pnt,
&rd_vnc_eth);
#endif
if (use_json)
{
char buffer[BUFSIZ];
if (type == RD_TYPE_AS || type == RD_TYPE_AS4)
sprintf (buffer, "%u:%d", rd_as.as, rd_as.val);
else if (type == RD_TYPE_IP)
sprintf (buffer, "%s:%d", inet_ntoa (rd_ip.ip), rd_ip.val);
json_object_string_add(json_routes, "routeDistinguisher", buffer);
}
else
{
vty_out (vty, "Route Distinguisher: ");
if (use_json) {
char buffer[BUFSIZ];
if (type == RD_TYPE_AS
|| type == RD_TYPE_AS4)
sprintf(buffer,
"%u:%d",
rd_as.as,
rd_as.val);
else if (type
== RD_TYPE_IP)
sprintf(buffer,
"%s:%d",
inet_ntoa(
rd_ip.ip),
rd_ip.val);
json_object_string_add(
json_routes,
"routeDistinguisher",
buffer);
} else {
vty_out(vty,
"Route Distinguisher: ");
if (type == RD_TYPE_AS || type == RD_TYPE_AS4)
vty_out (vty, "%u:%d", rd_as.as, rd_as.val);
else if (type == RD_TYPE_IP)
vty_out (vty, "%s:%d", inet_ntoa (rd_ip.ip), rd_ip.val);
if (type == RD_TYPE_AS
|| type == RD_TYPE_AS4)
vty_out(vty,
"%u:%d",
rd_as.as,
rd_as.val);
else if (type
== RD_TYPE_IP)
vty_out(vty,
"%s:%d",
inet_ntoa(
rd_ip.ip),
rd_ip.val);
#if ENABLE_BGP_VNC
else if (type == RD_TYPE_VNC_ETH)
vty_out (vty, "%u:%02x:%02x:%02x:%02x:%02x:%02x",
rd_vnc_eth.local_nve_id,
rd_vnc_eth.macaddr.octet[0],
rd_vnc_eth.macaddr.octet[1],
rd_vnc_eth.macaddr.octet[2],
rd_vnc_eth.macaddr.octet[3],
rd_vnc_eth.macaddr.octet[4],
rd_vnc_eth.macaddr.octet[5]);
else if (
type
== RD_TYPE_VNC_ETH)
vty_out(vty,
"%u:%02x:%02x:%02x:%02x:%02x:%02x",
rd_vnc_eth
.local_nve_id,
rd_vnc_eth
.macaddr
.octet[0],
rd_vnc_eth
.macaddr
.octet[1],
rd_vnc_eth
.macaddr
.octet[2],
rd_vnc_eth
.macaddr
.octet[3],
rd_vnc_eth
.macaddr
.octet[4],
rd_vnc_eth
.macaddr
.octet[5]);
#endif
vty_out (vty, VTYNL);
}
rd_header = 0;
}
route_vty_out_tmp (vty, &rm->p, attr, SAFI_MPLS_VPN, use_json, json_array);
}
}
if (use_json)
{
struct prefix *p;
char buf_a[BUFSIZ];
char buf_b[BUFSIZ];
p = &rm->p;
sprintf(buf_a, "%s/%d", inet_ntop (p->family, &p->u.prefix, buf_b, BUFSIZ), p->prefixlen);
json_object_object_add(json_routes, buf_a, json_array);
}
}
}
if (use_json)
{
json_object_object_add(json, "routes", json_routes);
vty_outln (vty, "%s",
json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY));
json_object_free(json);
}
return CMD_SUCCESS;
vty_out(vty, "\n");
}
rd_header = 0;
}
route_vty_out_tmp(vty, &rm->p, attr,
SAFI_MPLS_VPN,
use_json, json_array);
}
}
if (use_json) {
struct prefix *p;
char buf_a[BUFSIZ];
char buf_b[BUFSIZ];
p = &rm->p;
sprintf(buf_a, "%s/%d",
inet_ntop(p->family, &p->u.prefix,
buf_b, BUFSIZ),
p->prefixlen);
json_object_object_add(json_routes, buf_a,
json_array);
}
}
}
if (use_json) {
json_object_object_add(json, "routes", json_routes);
vty_out(vty, "%s\n", json_object_to_json_string_ext(
json, JSON_C_TO_STRING_PRETTY));
json_object_free(json);
}
return CMD_SUCCESS;
}

View File

@ -23,8 +23,8 @@
#include <zebra.h>
extern int
show_adj_route_vpn (struct vty *vty, struct peer *peer, struct prefix_rd *prd,
afi_t afi, safi_t safi, u_char use_json);
extern int show_adj_route_vpn(struct vty *vty, struct peer *peer,
struct prefix_rd *prd, afi_t afi, safi_t safi,
u_char use_json);
#endif /* _QUAGGA_BGP_VPN_H */

File diff suppressed because it is too large Load Diff

View File

@ -28,39 +28,46 @@ struct bgp;
#define BGP_AFI_CMD_STR "<ipv4|ipv6>"
#define BGP_AFI_HELP_STR "Address Family\nAddress Family\n"
#define BGP_SAFI_CMD_STR "<unicast|multicast|vpn|labeled-unicast>"
#define BGP_SAFI_HELP_STR \
"Address Family modifier\n" \
"Address Family modifier\n" \
"Address Family modifier\n" \
"Address Family modifier\n"
#define BGP_SAFI_CMD_STR "<unicast|multicast|vpn>"
#define BGP_SAFI_HELP_STR \
"Address Family modifier\n" \
"Address Family modifier\n" \
"Address Family modifier\n"
#define BGP_AFI_SAFI_CMD_STR BGP_AFI_CMD_STR" "BGP_SAFI_CMD_STR
#define BGP_AFI_SAFI_HELP_STR BGP_AFI_HELP_STR BGP_SAFI_HELP_STR
extern void bgp_vty_init (void);
extern const char *afi_safi_print (afi_t, safi_t);
extern const char *afi_safi_json (afi_t, safi_t);
extern int bgp_config_write_update_delay (struct vty *, struct bgp *);
#define BGP_SAFI_WITH_LABEL_CMD_STR "<unicast|multicast|vpn|labeled-unicast>"
#define BGP_SAFI_WITH_LABEL_HELP_STR \
"Address Family modifier\n" \
"Address Family modifier\n" \
"Address Family modifier\n" \
"Address Family modifier\n"
extern void bgp_vty_init(void);
extern const char *afi_safi_print(afi_t, safi_t);
extern const char *afi_safi_json(afi_t, safi_t);
extern int bgp_config_write_update_delay(struct vty *, struct bgp *);
extern int bgp_config_write_wpkt_quanta(struct vty *vty, struct bgp *bgp);
extern int bgp_config_write_listen(struct vty *vty, struct bgp *bgp);
extern int bgp_config_write_coalesce_time(struct vty *vty, struct bgp *bgp);
extern int bgp_vty_return (struct vty *vty, int ret);
extern struct peer *
peer_and_group_lookup_vty (struct vty *vty, const char *peer_str);
extern int bgp_vty_return(struct vty *vty, int ret);
extern struct peer *peer_and_group_lookup_vty(struct vty *vty,
const char *peer_str);
extern afi_t
bgp_vty_afi_from_str(const char *afi_str);
extern afi_t bgp_vty_afi_from_str(const char *afi_str);
extern safi_t
bgp_vty_safi_from_str(const char *safi_str);
extern safi_t bgp_vty_safi_from_str(const char *safi_str);
extern int
argv_find_and_parse_afi(struct cmd_token **argv, int argc, int *index, afi_t *afi);
extern int argv_find_and_parse_afi(struct cmd_token **argv, int argc,
int *index, afi_t *afi);
extern int
argv_find_and_parse_safi(struct cmd_token **argv, int argc, int *index, safi_t *safi);
extern int argv_find_and_parse_safi(struct cmd_token **argv, int argc,
int *index, safi_t *safi);
extern int
bgp_vty_find_and_parse_afi_safi_bgp (struct vty *vty, struct cmd_token **argv, int argc, int *idx,
afi_t *afi, safi_t *safi, struct bgp **bgp);
extern int bgp_vty_find_and_parse_afi_safi_bgp(struct vty *vty,
struct cmd_token **argv,
int argc, int *idx, afi_t *afi,
safi_t *safi, struct bgp **bgp);
extern int bgp_show_summary_vty(struct vty *vty, const char *name, afi_t afi,
safi_t safi, u_char use_json);
#endif /* _QUAGGA_BGP_VTY_H */

File diff suppressed because it is too large Load Diff

View File

@ -21,46 +21,43 @@
#ifndef _QUAGGA_BGP_ZEBRA_H
#define _QUAGGA_BGP_ZEBRA_H
#define BGP_NEXTHOP_BUF_SIZE (8 * sizeof (struct in_addr *))
#define BGP_IFINDICES_BUF_SIZE (8 * sizeof (unsigned int))
#define BGP_LABEL_BUF_SIZE (8 * sizeof (unsigned int))
extern void bgp_zebra_init(struct thread_master *master);
extern void bgp_zebra_destroy(void);
extern int bgp_if_update_all(void);
extern int bgp_config_write_maxpaths(struct vty *, struct bgp *, afi_t, safi_t,
int *);
extern int bgp_config_write_redistribute(struct vty *, struct bgp *, afi_t,
safi_t, int *);
extern void bgp_zebra_announce(struct bgp_node *, struct prefix *,
struct bgp_info *, struct bgp *, afi_t, safi_t);
extern void bgp_zebra_announce_table(struct bgp *, afi_t, safi_t);
extern void bgp_zebra_withdraw(struct prefix *, struct bgp_info *, safi_t);
extern struct stream *bgp_nexthop_buf;
extern struct stream *bgp_ifindices_buf;
extern struct stream *bgp_label_buf;
extern void bgp_zebra_initiate_radv(struct bgp *bgp, struct peer *peer);
extern void bgp_zebra_terminate_radv(struct bgp *bgp, struct peer *peer);
extern void bgp_zebra_init (struct thread_master *master);
extern void bgp_zebra_destroy (void);
extern int bgp_if_update_all (void);
extern int bgp_config_write_maxpaths (struct vty *, struct bgp *, afi_t,
safi_t, int *);
extern int bgp_config_write_redistribute (struct vty *, struct bgp *, afi_t, safi_t,
int *);
extern void bgp_zebra_announce (struct bgp_node *, struct prefix *,
struct bgp_info *, struct bgp *, afi_t, safi_t);
extern void bgp_zebra_announce_table (struct bgp *, afi_t, safi_t);
extern void bgp_zebra_withdraw (struct prefix *, struct bgp_info *, safi_t);
extern void bgp_zebra_instance_register(struct bgp *);
extern void bgp_zebra_instance_deregister(struct bgp *);
extern void bgp_zebra_initiate_radv (struct bgp *bgp, struct peer *peer);
extern void bgp_zebra_terminate_radv (struct bgp *bgp, struct peer *peer);
extern struct bgp_redist *bgp_redist_lookup(struct bgp *, afi_t, u_char,
u_short);
extern struct bgp_redist *bgp_redist_add(struct bgp *, afi_t, u_char, u_short);
extern int bgp_redistribute_set(struct bgp *, afi_t, int, u_short);
extern int bgp_redistribute_resend(struct bgp *, afi_t, int, u_short);
extern int bgp_redistribute_rmap_set(struct bgp_redist *, const char *);
extern int bgp_redistribute_metric_set(struct bgp *, struct bgp_redist *, afi_t,
int, u_int32_t);
extern int bgp_redistribute_unset(struct bgp *, afi_t, int, u_short);
extern int bgp_redistribute_unreg(struct bgp *, afi_t, int, u_short);
extern void bgp_zebra_instance_register (struct bgp *);
extern void bgp_zebra_instance_deregister (struct bgp *);
extern struct interface *if_lookup_by_ipv4(struct in_addr *, vrf_id_t);
extern struct interface *if_lookup_by_ipv4_exact(struct in_addr *, vrf_id_t);
extern struct interface *if_lookup_by_ipv6(struct in6_addr *, ifindex_t,
vrf_id_t);
extern struct interface *if_lookup_by_ipv6_exact(struct in6_addr *, ifindex_t,
vrf_id_t);
extern struct bgp_redist *bgp_redist_lookup (struct bgp *, afi_t, u_char, u_short);
extern struct bgp_redist *bgp_redist_add (struct bgp *, afi_t, u_char, u_short);
extern int bgp_redistribute_set (struct bgp *, afi_t, int, u_short);
extern int bgp_redistribute_resend (struct bgp *, afi_t, int, u_short);
extern int bgp_redistribute_rmap_set (struct bgp_redist *, const char *);
extern int bgp_redistribute_metric_set(struct bgp *, struct bgp_redist *,
afi_t, int, u_int32_t);
extern int bgp_redistribute_unset (struct bgp *, afi_t, int, u_short);
extern int bgp_redistribute_unreg (struct bgp *, afi_t, int, u_short);
extern struct interface *if_lookup_by_ipv4 (struct in_addr *, vrf_id_t);
extern struct interface *if_lookup_by_ipv4_exact (struct in_addr *, vrf_id_t);
extern struct interface *if_lookup_by_ipv6 (struct in6_addr *, ifindex_t, vrf_id_t);
extern struct interface *if_lookup_by_ipv6_exact (struct in6_addr *, ifindex_t, vrf_id_t);
extern int bgp_zebra_advertise_all_vni(struct bgp *, int);
extern int bgp_zebra_num_connects(void);

12264
bgpd/bgpd.c

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,4 @@
/*
/*
*
* Copyright 2009-2016, LabN Consulting, L.L.C.
*
@ -27,200 +27,195 @@
#if ENABLE_BGP_VNC
#include "rfapi.h"
struct rfapi_l2_group_cfg
{
char *name;
uint32_t logical_net_id;
struct list *labels; /* list of uint32_t */
struct ecommunity *rt_import_list;
struct ecommunity *rt_export_list;
void *rfp_cfg; /* rfp owned group config */
struct rfapi_l2_group_cfg {
char *name;
uint32_t logical_net_id;
struct list *labels; /* list of uint32_t */
struct ecommunity *rt_import_list;
struct ecommunity *rt_export_list;
void *rfp_cfg; /* rfp owned group config */
QOBJ_FIELDS
QOBJ_FIELDS
};
DECLARE_QOBJ_TYPE(rfapi_l2_group_cfg)
typedef enum
{
RFAPI_GROUP_CFG_NVE = 1,
RFAPI_GROUP_CFG_VRF,
RFAPI_GROUP_CFG_L2,
RFAPI_GROUP_CFG_MAX
typedef enum {
RFAPI_GROUP_CFG_NVE = 1,
RFAPI_GROUP_CFG_VRF,
RFAPI_GROUP_CFG_L2,
RFAPI_GROUP_CFG_MAX
} rfapi_group_cfg_type_t;
struct rfapi_nve_group_cfg
{
struct route_node *vn_node; /* backref */
struct route_node *un_node; /* backref */
struct rfapi_nve_group_cfg {
struct route_node *vn_node; /* backref */
struct route_node *un_node; /* backref */
rfapi_group_cfg_type_t type; /* NVE|VPN */
char *name; /* unique by type! */
struct prefix vn_prefix;
struct prefix un_prefix;
rfapi_group_cfg_type_t type; /* NVE|VPN */
char *name; /* unique by type! */
struct prefix vn_prefix;
struct prefix un_prefix;
struct prefix_rd rd;
uint8_t l2rd; /* 0 = VN addr LSB */
uint32_t response_lifetime;
uint32_t flags;
struct prefix_rd rd;
uint8_t l2rd; /* 0 = VN addr LSB */
uint32_t response_lifetime;
uint32_t flags;
#define RFAPI_RFG_RESPONSE_LIFETIME 0x01 /* bits */
#define RFAPI_RFG_L2RD 0x02
#define RFAPI_RFG_VPN_NH_SELF 0x04
struct ecommunity *rt_import_list;
struct ecommunity *rt_export_list;
struct rfapi_import_table *rfapi_import_table;
struct ecommunity *rt_import_list;
struct ecommunity *rt_export_list;
struct rfapi_import_table *rfapi_import_table;
void *rfp_cfg; /* rfp owned group config */
/*
* List of NVE descriptors that are assigned to this NVE group
*
* Currently (Mar 2010) this list is used only by the route
* export code to generate per-NVE nexthops for each route.
*
* The nve descriptors listed here have pointers back to
* this nve group config structure to enable them to delete
* their own list entries when they are closed. Consequently,
* if an instance of this nve group config structure is deleted,
* we must first set the nve descriptor references to it to NULL.
*/
struct list *nves;
void *rfp_cfg; /* rfp owned group config */
/*
* List of NVE descriptors that are assigned to this NVE group
*
* Currently (Mar 2010) this list is used only by the route
* export code to generate per-NVE nexthops for each route.
*
* The nve descriptors listed here have pointers back to
* this nve group config structure to enable them to delete
* their own list entries when they are closed. Consequently,
* if an instance of this nve group config structure is deleted,
* we must first set the nve descriptor references to it to NULL.
*/
struct list *nves;
/*
* Route filtering
*
* Prefix lists are segregated by afi (part of the base plist code)
* Route-maps are not segregated
*/
char *plist_export_bgp_name[AFI_MAX];
struct prefix_list *plist_export_bgp[AFI_MAX];
/*
* Route filtering
*
* Prefix lists are segregated by afi (part of the base plist code)
* Route-maps are not segregated
*/
char *plist_export_bgp_name[AFI_MAX];
struct prefix_list *plist_export_bgp[AFI_MAX];
char *plist_export_zebra_name[AFI_MAX];
struct prefix_list *plist_export_zebra[AFI_MAX];
char *plist_export_zebra_name[AFI_MAX];
struct prefix_list *plist_export_zebra[AFI_MAX];
char *plist_redist_name[ZEBRA_ROUTE_MAX][AFI_MAX];
struct prefix_list *plist_redist[ZEBRA_ROUTE_MAX][AFI_MAX];
char *plist_redist_name[ZEBRA_ROUTE_MAX][AFI_MAX];
struct prefix_list *plist_redist[ZEBRA_ROUTE_MAX][AFI_MAX];
char *routemap_export_bgp_name;
struct route_map *routemap_export_bgp;
char *routemap_export_bgp_name;
struct route_map *routemap_export_bgp;
char *routemap_export_zebra_name;
struct route_map *routemap_export_zebra;
char *routemap_export_zebra_name;
struct route_map *routemap_export_zebra;
char *routemap_redist_name[ZEBRA_ROUTE_MAX];
struct route_map *routemap_redist[ZEBRA_ROUTE_MAX];
char *routemap_redist_name[ZEBRA_ROUTE_MAX];
struct route_map *routemap_redist[ZEBRA_ROUTE_MAX];
/* for VRF type groups */
uint32_t label;
struct rfapi_descriptor *rfd;
QOBJ_FIELDS
/* for VRF type groups */
uint32_t label;
struct rfapi_descriptor *rfd;
QOBJ_FIELDS
};
DECLARE_QOBJ_TYPE(rfapi_nve_group_cfg)
struct rfapi_rfg_name
{
struct rfapi_nve_group_cfg *rfg;
char *name;
struct rfapi_rfg_name {
struct rfapi_nve_group_cfg *rfg;
char *name;
};
typedef enum
{
VNC_REDIST_MODE_PLAIN = 0, /* 0 = default */
VNC_REDIST_MODE_RFG,
VNC_REDIST_MODE_RESOLVE_NVE
typedef enum {
VNC_REDIST_MODE_PLAIN = 0, /* 0 = default */
VNC_REDIST_MODE_RFG,
VNC_REDIST_MODE_RESOLVE_NVE
} vnc_redist_mode_t;
struct rfapi_cfg
{
struct prefix_rd default_rd;
uint8_t default_l2rd;
struct ecommunity *default_rt_import_list;
struct ecommunity *default_rt_export_list;
uint32_t default_response_lifetime;
struct rfapi_cfg {
struct prefix_rd default_rd;
uint8_t default_l2rd;
struct ecommunity *default_rt_import_list;
struct ecommunity *default_rt_export_list;
uint32_t default_response_lifetime;
#define BGP_VNC_DEFAULT_RESPONSE_LIFETIME_DEFAULT 3600
void *default_rfp_cfg; /* rfp owned group config */
void *default_rfp_cfg; /* rfp owned group config */
struct list *l2_groups; /* rfapi_l2_group_cfg list */
/* three views into the same collection of rfapi_nve_group_cfg */
struct list *nve_groups_sequential;
struct route_table nve_groups_vn[AFI_MAX];
struct route_table nve_groups_un[AFI_MAX];
struct list *l2_groups; /* rfapi_l2_group_cfg list */
/* three views into the same collection of rfapi_nve_group_cfg */
struct list *nve_groups_sequential;
struct route_table nve_groups_vn[AFI_MAX];
struct route_table nve_groups_un[AFI_MAX];
/*
* For Single VRF export to ordinary routing protocols. This is
* the nve-group that the ordinary protocols belong to. We use it
* to set the RD when sending unicast Zebra routes to VNC
*/
uint8_t redist[AFI_MAX][ZEBRA_ROUTE_MAX];
uint32_t redist_lifetime;
vnc_redist_mode_t redist_mode;
/*
* For Single VRF export to ordinary routing protocols. This is
* the nve-group that the ordinary protocols belong to. We use it
* to set the RD when sending unicast Zebra routes to VNC
*/
uint8_t redist[AFI_MAX][ZEBRA_ROUTE_MAX];
uint32_t redist_lifetime;
vnc_redist_mode_t redist_mode;
/*
* view name of BGP unicast instance that holds
* exterior routes
*/
char *redist_bgp_exterior_view_name;
struct bgp *redist_bgp_exterior_view;
/*
* view name of BGP unicast instance that holds
* exterior routes
*/
char *redist_bgp_exterior_view_name;
struct bgp *redist_bgp_exterior_view;
/*
* nve group for redistribution of routes from zebra to VNC
* (which is probably not useful for production networks)
*/
char *rfg_redist_name;
struct rfapi_nve_group_cfg *rfg_redist;
/*
* nve group for redistribution of routes from zebra to VNC
* (which is probably not useful for production networks)
*/
char *rfg_redist_name;
struct rfapi_nve_group_cfg *rfg_redist;
/*
* List of NVE groups on whose behalf we will export VNC
* routes to zebra. ((NB: it's actually a list of <struct rfapi_rfg_name>)
* This list is used when BGP_VNC_CONFIG_EXPORT_ZEBRA_MODE_BITS is
* BGP_VNC_CONFIG_EXPORT_ZEBRA_MODE_GRP
*/
struct list *rfg_export_zebra_l;
/*
* List of NVE groups on whose behalf we will export VNC
* routes to zebra. ((NB: it's actually a list of <struct
* rfapi_rfg_name>)
* This list is used when BGP_VNC_CONFIG_EXPORT_ZEBRA_MODE_BITS is
* BGP_VNC_CONFIG_EXPORT_ZEBRA_MODE_GRP
*/
struct list *rfg_export_zebra_l;
/*
* List of NVE groups on whose behalf we will export VNC
* routes directly to the bgp unicast RIB. (NB: it's actually
* a list of <struct rfapi_rfg_name>)
* This list is used when BGP_VNC_CONFIG_EXPORT_BGP_MODE_BITS is
* BGP_VNC_CONFIG_EXPORT_BGP_MODE_GRP
*/
struct list *rfg_export_direct_bgp_l;
/*
* List of NVE groups on whose behalf we will export VNC
* routes directly to the bgp unicast RIB. (NB: it's actually
* a list of <struct rfapi_rfg_name>)
* This list is used when BGP_VNC_CONFIG_EXPORT_BGP_MODE_BITS is
* BGP_VNC_CONFIG_EXPORT_BGP_MODE_GRP
*/
struct list *rfg_export_direct_bgp_l;
/*
* Exported Route filtering
*
* Prefix lists are segregated by afi (part of the base plist code)
* Route-maps are not segregated
*/
char *plist_export_bgp_name[AFI_MAX];
struct prefix_list *plist_export_bgp[AFI_MAX];
/*
* Exported Route filtering
*
* Prefix lists are segregated by afi (part of the base plist code)
* Route-maps are not segregated
*/
char *plist_export_bgp_name[AFI_MAX];
struct prefix_list *plist_export_bgp[AFI_MAX];
char *plist_export_zebra_name[AFI_MAX];
struct prefix_list *plist_export_zebra[AFI_MAX];
char *plist_export_zebra_name[AFI_MAX];
struct prefix_list *plist_export_zebra[AFI_MAX];
char *routemap_export_bgp_name;
struct route_map *routemap_export_bgp;
char *routemap_export_bgp_name;
struct route_map *routemap_export_bgp;
char *routemap_export_zebra_name;
struct route_map *routemap_export_zebra;
char *routemap_export_zebra_name;
struct route_map *routemap_export_zebra;
/*
* Redistributed route filtering (routes from other
* protocols into VNC)
*/
char *plist_redist_name[ZEBRA_ROUTE_MAX][AFI_MAX];
struct prefix_list *plist_redist[ZEBRA_ROUTE_MAX][AFI_MAX];
/*
* Redistributed route filtering (routes from other
* protocols into VNC)
*/
char *plist_redist_name[ZEBRA_ROUTE_MAX][AFI_MAX];
struct prefix_list *plist_redist[ZEBRA_ROUTE_MAX][AFI_MAX];
char *routemap_redist_name[ZEBRA_ROUTE_MAX];
struct route_map *routemap_redist[ZEBRA_ROUTE_MAX];
char *routemap_redist_name[ZEBRA_ROUTE_MAX];
struct route_map *routemap_redist[ZEBRA_ROUTE_MAX];
/*
* For importing bgp unicast routes to VNC, we encode the CE
* (route nexthop) in a Route Origin extended community. The
* local part (16-bit) is user-configurable.
*/
uint16_t resolve_nve_roo_local_admin;
/*
* For importing bgp unicast routes to VNC, we encode the CE
* (route nexthop) in a Route Origin extended community. The
* local part (16-bit) is user-configurable.
*/
uint16_t resolve_nve_roo_local_admin;
#define BGP_VNC_CONFIG_RESOLVE_NVE_ROO_LOCAL_ADMIN_DEFAULT 5226
uint32_t flags;
uint32_t flags;
#define BGP_VNC_CONFIG_ADV_UN_METHOD_ENCAP 0x00000001
#define BGP_VNC_CONFIG_CALLBACK_DISABLE 0x00000002
#define BGP_VNC_CONFIG_RESPONSE_REMOVAL_DISABLE 0x00000004
@ -244,98 +239,76 @@ struct rfapi_cfg
/* Filter querying NVE's registrations from responses */
/* Default to updated-responses off */
/* Default to removal-responses off */
#define BGP_VNC_CONFIG_FLAGS_DEFAULT \
(BGP_VNC_CONFIG_FILTER_SELF_FROM_RSP |\
BGP_VNC_CONFIG_CALLBACK_DISABLE |\
BGP_VNC_CONFIG_RESPONSE_REMOVAL_DISABLE)
#define BGP_VNC_CONFIG_FLAGS_DEFAULT \
(BGP_VNC_CONFIG_FILTER_SELF_FROM_RSP | BGP_VNC_CONFIG_CALLBACK_DISABLE \
| BGP_VNC_CONFIG_RESPONSE_REMOVAL_DISABLE)
struct rfapi_rfp_cfg rfp_cfg; /* rfp related configuration */
struct rfapi_rfp_cfg rfp_cfg; /* rfp related configuration */
};
#define VNC_EXPORT_ZEBRA_GRP_ENABLED(hc) \
(((hc)->flags & BGP_VNC_CONFIG_EXPORT_ZEBRA_MODE_BITS) == \
BGP_VNC_CONFIG_EXPORT_ZEBRA_MODE_GRP)
#define VNC_EXPORT_ZEBRA_GRP_ENABLED(hc) \
(((hc)->flags & BGP_VNC_CONFIG_EXPORT_ZEBRA_MODE_BITS) \
== BGP_VNC_CONFIG_EXPORT_ZEBRA_MODE_GRP)
#define VNC_EXPORT_ZEBRA_RH_ENABLED(hc) \
(((hc)->flags & BGP_VNC_CONFIG_EXPORT_ZEBRA_MODE_BITS) == \
BGP_VNC_CONFIG_EXPORT_ZEBRA_MODE_RH)
#define VNC_EXPORT_ZEBRA_RH_ENABLED(hc) \
(((hc)->flags & BGP_VNC_CONFIG_EXPORT_ZEBRA_MODE_BITS) \
== BGP_VNC_CONFIG_EXPORT_ZEBRA_MODE_RH)
#define VNC_EXPORT_BGP_GRP_ENABLED(hc) \
(((hc)->flags & BGP_VNC_CONFIG_EXPORT_BGP_MODE_BITS) == \
BGP_VNC_CONFIG_EXPORT_BGP_MODE_GRP)
#define VNC_EXPORT_BGP_GRP_ENABLED(hc) \
(((hc)->flags & BGP_VNC_CONFIG_EXPORT_BGP_MODE_BITS) \
== BGP_VNC_CONFIG_EXPORT_BGP_MODE_GRP)
#define VNC_EXPORT_BGP_RH_ENABLED(hc) \
(((hc)->flags & BGP_VNC_CONFIG_EXPORT_BGP_MODE_BITS) == \
BGP_VNC_CONFIG_EXPORT_BGP_MODE_RH)
#define VNC_EXPORT_BGP_RH_ENABLED(hc) \
(((hc)->flags & BGP_VNC_CONFIG_EXPORT_BGP_MODE_BITS) \
== BGP_VNC_CONFIG_EXPORT_BGP_MODE_RH)
#define VNC_EXPORT_BGP_CE_ENABLED(hc) \
(((hc)->flags & BGP_VNC_CONFIG_EXPORT_BGP_MODE_BITS) == \
BGP_VNC_CONFIG_EXPORT_BGP_MODE_CE)
#define VNC_EXPORT_BGP_CE_ENABLED(hc) \
(((hc)->flags & BGP_VNC_CONFIG_EXPORT_BGP_MODE_BITS) \
== BGP_VNC_CONFIG_EXPORT_BGP_MODE_CE)
void
bgp_rfapi_cfg_init (void);
void bgp_rfapi_cfg_init(void);
struct rfapi_cfg *
bgp_rfapi_cfg_new (struct rfapi_rfp_cfg *cfg);
struct rfapi_cfg *bgp_rfapi_cfg_new(struct rfapi_rfp_cfg *cfg);
void
bgp_rfapi_cfg_destroy (struct bgp *bgp, struct rfapi_cfg *h);
void bgp_rfapi_cfg_destroy(struct bgp *bgp, struct rfapi_cfg *h);
int
bgp_rfapi_cfg_write (struct vty *vty, struct bgp *bgp);
int bgp_rfapi_cfg_write(struct vty *vty, struct bgp *bgp);
extern int
bgp_rfapi_is_vnc_configured (struct bgp *bgp);
extern int bgp_rfapi_is_vnc_configured(struct bgp *bgp);
extern void
nve_group_to_nve_list (
struct rfapi_nve_group_cfg *rfg,
struct list **nves,
uint8_t family); /* AF_INET, AF_INET6 */
extern void nve_group_to_nve_list(struct rfapi_nve_group_cfg *rfg,
struct list **nves,
uint8_t family); /* AF_INET, AF_INET6 */
struct rfapi_nve_group_cfg *bgp_rfapi_cfg_match_group(struct rfapi_cfg *hc,
struct prefix *vn,
struct prefix *un);
struct rfapi_nve_group_cfg *
bgp_rfapi_cfg_match_group (
struct rfapi_cfg *hc,
struct prefix *vn,
struct prefix *un);
bgp_rfapi_cfg_match_byname(struct bgp *bgp, const char *name,
rfapi_group_cfg_type_t type); /* _MAX = any */
struct rfapi_nve_group_cfg *
bgp_rfapi_cfg_match_byname (
struct bgp *bgp,
const char *name,
rfapi_group_cfg_type_t type); /* _MAX = any */
extern void vnc_prefix_list_update(struct bgp *bgp);
extern void
vnc_prefix_list_update (struct bgp *bgp);
extern void vnc_routemap_update(struct bgp *bgp, const char *unused);
extern void
vnc_routemap_update (struct bgp *bgp, const char *unused);
extern void bgp_rfapi_show_summary(struct bgp *bgp, struct vty *vty);
extern void
bgp_rfapi_show_summary (struct bgp *bgp, struct vty *vty);
extern struct rfapi_cfg *
bgp_rfapi_get_config (struct bgp *bgp);
extern struct rfapi_cfg *bgp_rfapi_get_config(struct bgp *bgp);
extern struct rfapi_l2_group_cfg *
bgp_rfapi_get_group_by_lni_label (
struct bgp *bgp,
uint32_t logical_net_id,
uint32_t label);
bgp_rfapi_get_group_by_lni_label(struct bgp *bgp, uint32_t logical_net_id,
uint32_t label);
extern struct ecommunity *
bgp_rfapi_get_ecommunity_by_lni_label (
struct bgp *bgp,
uint32_t is_import,
uint32_t logical_net_id,
uint32_t label); /* note, 20bit label! */
bgp_rfapi_get_ecommunity_by_lni_label(struct bgp *bgp, uint32_t is_import,
uint32_t logical_net_id,
uint32_t label); /* note, 20bit label! */
extern struct list *
bgp_rfapi_get_labellist_by_lni_label (
struct bgp *bgp,
uint32_t logical_net_id,
uint32_t label); /* note, 20bit label! */
bgp_rfapi_get_labellist_by_lni_label(struct bgp *bgp, uint32_t logical_net_id,
uint32_t label); /* note, 20bit label! */
#endif /* ENABLE_BGP_VNC */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,4 @@
/*
/*
*
* Copyright 2009-2016, LabN Consulting, L.L.C.
*
@ -83,541 +83,476 @@
* is used to spread out the sort for adbs with the same lifetime
* and thereby make the skip list operations more efficient.
*/
static int
sl_adb_lifetime_cmp (void *adb1, void *adb2)
static int sl_adb_lifetime_cmp(void *adb1, void *adb2)
{
struct rfapi_adb *a1 = adb1;
struct rfapi_adb *a2 = adb2;
struct rfapi_adb *a1 = adb1;
struct rfapi_adb *a2 = adb2;
if (a1->lifetime < a2->lifetime)
return -1;
if (a1->lifetime > a2->lifetime)
return 1;
if (a1->lifetime < a2->lifetime)
return -1;
if (a1->lifetime > a2->lifetime)
return 1;
if (a1 < a2)
return -1;
if (a1 > a2)
return 1;
if (a1 < a2)
return -1;
if (a1 > a2)
return 1;
return 0;
return 0;
}
void
rfapiApInit (struct rfapi_advertised_prefixes *ap)
void rfapiApInit(struct rfapi_advertised_prefixes *ap)
{
ap->ipN_by_prefix = skiplist_new (0, rfapi_rib_key_cmp, NULL);
ap->ip0_by_ether = skiplist_new (0, rfapi_rib_key_cmp, NULL);
ap->by_lifetime = skiplist_new (0, sl_adb_lifetime_cmp, NULL);
ap->ipN_by_prefix = skiplist_new(0, rfapi_rib_key_cmp, NULL);
ap->ip0_by_ether = skiplist_new(0, rfapi_rib_key_cmp, NULL);
ap->by_lifetime = skiplist_new(0, sl_adb_lifetime_cmp, NULL);
}
void
rfapiApRelease (struct rfapi_advertised_prefixes *ap)
void rfapiApRelease(struct rfapi_advertised_prefixes *ap)
{
struct rfapi_adb *adb;
struct rfapi_adb *adb;
/* Free ADBs and lifetime items */
while (0 == skiplist_first (ap->by_lifetime, NULL, (void **) &adb))
{
rfapiAdbFree (adb);
skiplist_delete_first (ap->by_lifetime);
}
/* Free ADBs and lifetime items */
while (0 == skiplist_first(ap->by_lifetime, NULL, (void **)&adb)) {
rfapiAdbFree(adb);
skiplist_delete_first(ap->by_lifetime);
}
while (0 == skiplist_delete_first (ap->ipN_by_prefix));
while (0 == skiplist_delete_first (ap->ip0_by_ether));
while (0 == skiplist_delete_first(ap->ipN_by_prefix))
;
while (0 == skiplist_delete_first(ap->ip0_by_ether))
;
/* Free lists */
skiplist_free (ap->ipN_by_prefix);
skiplist_free (ap->ip0_by_ether);
skiplist_free (ap->by_lifetime);
/* Free lists */
skiplist_free(ap->ipN_by_prefix);
skiplist_free(ap->ip0_by_ether);
skiplist_free(ap->by_lifetime);
ap->ipN_by_prefix = NULL;
ap->ip0_by_ether = NULL;
ap->by_lifetime = NULL;
ap->ipN_by_prefix = NULL;
ap->ip0_by_ether = NULL;
ap->by_lifetime = NULL;
}
int
rfapiApCount (struct rfapi_descriptor *rfd)
int rfapiApCount(struct rfapi_descriptor *rfd)
{
if (!rfd->advertised.by_lifetime)
return 0;
if (!rfd->advertised.by_lifetime)
return 0;
return skiplist_count (rfd->advertised.by_lifetime);
return skiplist_count(rfd->advertised.by_lifetime);
}
int
rfapiApCountAll (struct bgp *bgp)
int rfapiApCountAll(struct bgp *bgp)
{
struct rfapi *h;
struct listnode *node;
struct rfapi_descriptor *rfd;
int total = 0;
struct rfapi *h;
struct listnode *node;
struct rfapi_descriptor *rfd;
int total = 0;
h = bgp->rfapi;
if (h)
{
for (ALL_LIST_ELEMENTS_RO (&h->descriptors, node, rfd))
{
total += rfapiApCount (rfd);
}
}
return total;
h = bgp->rfapi;
if (h) {
for (ALL_LIST_ELEMENTS_RO(&h->descriptors, node, rfd)) {
total += rfapiApCount(rfd);
}
}
return total;
}
void
rfapiApReadvertiseAll (struct bgp *bgp, struct rfapi_descriptor *rfd)
void rfapiApReadvertiseAll(struct bgp *bgp, struct rfapi_descriptor *rfd)
{
struct rfapi_adb *adb;
void *cursor = NULL;
int rc;
struct rfapi_adb *adb;
void *cursor = NULL;
int rc;
for (rc =
skiplist_next (rfd->advertised.by_lifetime, NULL, (void **) &adb,
&cursor); rc == 0;
rc =
skiplist_next (rfd->advertised.by_lifetime, NULL, (void **) &adb,
&cursor))
{
for (rc = skiplist_next(rfd->advertised.by_lifetime, NULL,
(void **)&adb, &cursor);
rc == 0; rc = skiplist_next(rfd->advertised.by_lifetime, NULL,
(void **)&adb, &cursor)) {
struct prefix_rd prd;
uint32_t local_pref = rfp_cost_to_localpref (adb->cost);
struct prefix_rd prd;
uint32_t local_pref = rfp_cost_to_localpref(adb->cost);
prd = rfd->rd;
prd.family = AF_UNSPEC;
prd.prefixlen = 64;
prd = rfd->rd;
prd.family = AF_UNSPEC;
prd.prefixlen = 64;
/*
* TBD this is not quite right. When pfx_ip is 0/32 or 0/128,
* we need to substitute the VN address as the prefix
*/
add_vnc_route (rfd, bgp, SAFI_MPLS_VPN, &adb->u.s.prefix_ip, &prd, /* RD to use (0 for ENCAP) */
&rfd->vn_addr, /* nexthop */
&local_pref, &adb->lifetime, NULL, NULL, /* struct rfapi_un_option */
NULL, /* struct rfapi_vn_option */
rfd->rt_export_list, NULL, /* med */
NULL, ZEBRA_ROUTE_BGP, BGP_ROUTE_RFP, 0);
}
/*
* TBD this is not quite right. When pfx_ip is 0/32 or 0/128,
* we need to substitute the VN address as the prefix
*/
add_vnc_route(rfd, bgp, SAFI_MPLS_VPN, &adb->u.s.prefix_ip,
&prd, /* RD to use (0 for ENCAP) */
&rfd->vn_addr, /* nexthop */
&local_pref, &adb->lifetime, NULL,
NULL, /* struct rfapi_un_option */
NULL, /* struct rfapi_vn_option */
rfd->rt_export_list, NULL, /* med */
NULL, ZEBRA_ROUTE_BGP, BGP_ROUTE_RFP, 0);
}
}
void
rfapiApWithdrawAll (struct bgp *bgp, struct rfapi_descriptor *rfd)
void rfapiApWithdrawAll(struct bgp *bgp, struct rfapi_descriptor *rfd)
{
struct rfapi_adb *adb;
void *cursor;
int rc;
struct rfapi_adb *adb;
void *cursor;
int rc;
cursor = NULL;
for (rc =
skiplist_next (rfd->advertised.by_lifetime, NULL, (void **) &adb,
&cursor); rc == 0;
rc =
skiplist_next (rfd->advertised.by_lifetime, NULL, (void **) &adb,
&cursor))
{
cursor = NULL;
for (rc = skiplist_next(rfd->advertised.by_lifetime, NULL,
(void **)&adb, &cursor);
rc == 0; rc = skiplist_next(rfd->advertised.by_lifetime, NULL,
(void **)&adb, &cursor)) {
struct prefix pfx_vn_buf;
struct prefix *pfx_ip;
struct prefix pfx_vn_buf;
struct prefix *pfx_ip;
if (!(RFAPI_0_PREFIX (&adb->u.s.prefix_ip) &&
RFAPI_HOST_PREFIX (&adb->u.s.prefix_ip)))
{
if (!(RFAPI_0_PREFIX(&adb->u.s.prefix_ip)
&& RFAPI_HOST_PREFIX(&adb->u.s.prefix_ip))) {
pfx_ip = &adb->u.s.prefix_ip;
pfx_ip = &adb->u.s.prefix_ip;
}
else
{
} else {
pfx_ip = NULL;
pfx_ip = NULL;
/*
* 0/32 or 0/128 => mac advertisement
*/
if (rfapiRaddr2Qprefix (&rfd->vn_addr, &pfx_vn_buf))
{
/*
* Bad: it means we can't delete the route
*/
vnc_zlog_debug_verbose ("%s: BAD: handle has bad vn_addr: skipping",
__func__);
continue;
}
}
/*
* 0/32 or 0/128 => mac advertisement
*/
if (rfapiRaddr2Qprefix(&rfd->vn_addr, &pfx_vn_buf)) {
/*
* Bad: it means we can't delete the route
*/
vnc_zlog_debug_verbose(
"%s: BAD: handle has bad vn_addr: skipping",
__func__);
continue;
}
}
del_vnc_route (rfd, rfd->peer, bgp, SAFI_MPLS_VPN, pfx_ip ? pfx_ip : &pfx_vn_buf, &adb->u.s.prd, /* RD to use (0 for ENCAP) */
ZEBRA_ROUTE_BGP, BGP_ROUTE_RFP, NULL, 0);
}
del_vnc_route(rfd, rfd->peer, bgp, SAFI_MPLS_VPN,
pfx_ip ? pfx_ip : &pfx_vn_buf,
&adb->u.s.prd, /* RD to use (0 for ENCAP) */
ZEBRA_ROUTE_BGP, BGP_ROUTE_RFP, NULL, 0);
}
}
/*
* returns nonzero if tunnel readvertisement is needed, 0 otherwise
*/
static int
rfapiApAdjustLifetimeStats (
struct rfapi_descriptor *rfd,
uint32_t *old_lifetime, /* set if removing/replacing */
uint32_t *new_lifetime) /* set if replacing/adding */
static int rfapiApAdjustLifetimeStats(
struct rfapi_descriptor *rfd,
uint32_t *old_lifetime, /* set if removing/replacing */
uint32_t *new_lifetime) /* set if replacing/adding */
{
int advertise = 0;
int find_max = 0;
int find_min = 0;
int advertise = 0;
int find_max = 0;
int find_min = 0;
vnc_zlog_debug_verbose ("%s: rfd=%p, pOldLife=%p, pNewLife=%p",
__func__, rfd, old_lifetime, new_lifetime);
if (old_lifetime)
vnc_zlog_debug_verbose ("%s: OldLife=%d", __func__, *old_lifetime);
if (new_lifetime)
vnc_zlog_debug_verbose ("%s: NewLife=%d", __func__, *new_lifetime);
vnc_zlog_debug_verbose("%s: rfd=%p, pOldLife=%p, pNewLife=%p", __func__,
rfd, old_lifetime, new_lifetime);
if (old_lifetime)
vnc_zlog_debug_verbose("%s: OldLife=%d", __func__,
*old_lifetime);
if (new_lifetime)
vnc_zlog_debug_verbose("%s: NewLife=%d", __func__,
*new_lifetime);
if (new_lifetime)
{
/*
* Adding new lifetime
*/
if (old_lifetime)
{
/*
* replacing existing lifetime
*/
if (new_lifetime) {
/*
* Adding new lifetime
*/
if (old_lifetime) {
/*
* replacing existing lifetime
*/
/* old and new are same */
if (*old_lifetime == *new_lifetime)
return 0;
/* old and new are same */
if (*old_lifetime == *new_lifetime)
return 0;
if (*old_lifetime == rfd->min_prefix_lifetime)
{
find_min = 1;
}
if (*old_lifetime == rfd->max_prefix_lifetime)
{
find_max = 1;
}
if (*old_lifetime == rfd->min_prefix_lifetime) {
find_min = 1;
}
if (*old_lifetime == rfd->max_prefix_lifetime) {
find_max = 1;
}
/* no need to search if new value is at or equals min|max */
if (*new_lifetime <= rfd->min_prefix_lifetime)
{
rfd->min_prefix_lifetime = *new_lifetime;
find_min = 0;
}
if (*new_lifetime >= rfd->max_prefix_lifetime)
{
rfd->max_prefix_lifetime = *new_lifetime;
advertise = 1;
find_max = 0;
}
/* no need to search if new value is at or equals
* min|max */
if (*new_lifetime <= rfd->min_prefix_lifetime) {
rfd->min_prefix_lifetime = *new_lifetime;
find_min = 0;
}
if (*new_lifetime >= rfd->max_prefix_lifetime) {
rfd->max_prefix_lifetime = *new_lifetime;
advertise = 1;
find_max = 0;
}
}
else
{
/*
* Just adding new lifetime
*/
if (*new_lifetime < rfd->min_prefix_lifetime)
{
rfd->min_prefix_lifetime = *new_lifetime;
}
if (*new_lifetime > rfd->max_prefix_lifetime)
{
advertise = 1;
rfd->max_prefix_lifetime = *new_lifetime;
}
} else {
/*
* Just adding new lifetime
*/
if (*new_lifetime < rfd->min_prefix_lifetime) {
rfd->min_prefix_lifetime = *new_lifetime;
}
if (*new_lifetime > rfd->max_prefix_lifetime) {
advertise = 1;
rfd->max_prefix_lifetime = *new_lifetime;
}
}
} else {
/*
* Deleting
*/
}
}
else
{
/*
* Deleting
*/
/*
* See if the max prefix lifetime for this NVE has decreased.
* The easy optimization: track min & max; walk the table only
* if they are different.
* The general optimization: index the advertised_prefixes
* table by lifetime.
*
* Note: for a given nve_descriptor, only one of the
* advertised_prefixes[] tables will be used: viz., the
* address family that matches the VN address.
*
*/
if (rfd->max_prefix_lifetime == rfd->min_prefix_lifetime) {
/*
* See if the max prefix lifetime for this NVE has decreased.
* The easy optimization: track min & max; walk the table only
* if they are different.
* The general optimization: index the advertised_prefixes
* table by lifetime.
*
* Note: for a given nve_descriptor, only one of the
* advertised_prefixes[] tables will be used: viz., the
* address family that matches the VN address.
*
*/
if (rfd->max_prefix_lifetime == rfd->min_prefix_lifetime)
{
/*
* Common case: all lifetimes are the same. Only
* thing we need to do here is check if there are
* no exported routes left. In that case, reinitialize
* the max and min values.
*/
if (!rfapiApCount (rfd))
{
rfd->max_prefix_lifetime = 0;
rfd->min_prefix_lifetime = UINT32_MAX;
}
/*
* Common case: all lifetimes are the same. Only
* thing we need to do here is check if there are
* no exported routes left. In that case, reinitialize
* the max and min values.
*/
if (!rfapiApCount(rfd)) {
rfd->max_prefix_lifetime = 0;
rfd->min_prefix_lifetime = UINT32_MAX;
}
}
else
{
if (old_lifetime)
{
if (*old_lifetime == rfd->min_prefix_lifetime)
{
find_min = 1;
}
if (*old_lifetime == rfd->max_prefix_lifetime)
{
find_max = 1;
}
}
}
}
} else {
if (old_lifetime) {
if (*old_lifetime == rfd->min_prefix_lifetime) {
find_min = 1;
}
if (*old_lifetime == rfd->max_prefix_lifetime) {
find_max = 1;
}
}
}
}
if (find_min || find_max)
{
uint32_t min = UINT32_MAX;
uint32_t max = 0;
if (find_min || find_max) {
uint32_t min = UINT32_MAX;
uint32_t max = 0;
struct rfapi_adb *adb_min;
struct rfapi_adb *adb_max;
struct rfapi_adb *adb_min;
struct rfapi_adb *adb_max;
if (!skiplist_first
(rfd->advertised.by_lifetime, (void **) &adb_min, NULL)
&& !skiplist_last (rfd->advertised.by_lifetime, (void **) &adb_max,
NULL))
{
if (!skiplist_first(rfd->advertised.by_lifetime,
(void **)&adb_min, NULL)
&& !skiplist_last(rfd->advertised.by_lifetime,
(void **)&adb_max, NULL)) {
/*
* This should always work
*/
min = adb_min->lifetime;
max = adb_max->lifetime;
/*
* This should always work
*/
min = adb_min->lifetime;
max = adb_max->lifetime;
}
else
{
} else {
void *cursor;
struct rfapi_rib_key rk;
struct rfapi_adb *adb;
int rc;
void *cursor;
struct rfapi_rib_key rk;
struct rfapi_adb *adb;
int rc;
vnc_zlog_debug_verbose ("%s: walking to find new min/max", __func__);
vnc_zlog_debug_verbose(
"%s: walking to find new min/max", __func__);
cursor = NULL;
for (rc = skiplist_next (rfd->advertised.ipN_by_prefix,
(void **) &rk, (void **) &adb,
&cursor); !rc;
rc =
skiplist_next (rfd->advertised.ipN_by_prefix,
(void **) &rk, (void **) &adb, &cursor))
{
cursor = NULL;
for (rc = skiplist_next(rfd->advertised.ipN_by_prefix,
(void **)&rk, (void **)&adb,
&cursor);
!rc;
rc = skiplist_next(rfd->advertised.ipN_by_prefix,
(void **)&rk, (void **)&adb,
&cursor)) {
uint32_t lt = adb->lifetime;
uint32_t lt = adb->lifetime;
if (lt > max)
max = lt;
if (lt < min)
min = lt;
}
cursor = NULL;
for (rc = skiplist_next (rfd->advertised.ip0_by_ether,
(void **) &rk, (void **) &adb,
&cursor); !rc;
rc =
skiplist_next (rfd->advertised.ip0_by_ether, (void **) &rk,
(void **) &adb, &cursor))
{
if (lt > max)
max = lt;
if (lt < min)
min = lt;
}
cursor = NULL;
for (rc = skiplist_next(rfd->advertised.ip0_by_ether,
(void **)&rk, (void **)&adb,
&cursor);
!rc;
rc = skiplist_next(rfd->advertised.ip0_by_ether,
(void **)&rk, (void **)&adb,
&cursor)) {
uint32_t lt = adb->lifetime;
uint32_t lt = adb->lifetime;
if (lt > max)
max = lt;
if (lt < min)
min = lt;
}
}
if (lt > max)
max = lt;
if (lt < min)
min = lt;
}
}
/*
* trigger tunnel route update
* but only if we found a VPN route and it had
* a lifetime greater than 0
*/
if (max && rfd->max_prefix_lifetime != max)
advertise = 1;
rfd->max_prefix_lifetime = max;
rfd->min_prefix_lifetime = min;
}
/*
* trigger tunnel route update
* but only if we found a VPN route and it had
* a lifetime greater than 0
*/
if (max && rfd->max_prefix_lifetime != max)
advertise = 1;
rfd->max_prefix_lifetime = max;
rfd->min_prefix_lifetime = min;
}
vnc_zlog_debug_verbose ("%s: returning advertise=%d, min=%d, max=%d",
__func__, advertise, rfd->min_prefix_lifetime,
rfd->max_prefix_lifetime);
vnc_zlog_debug_verbose("%s: returning advertise=%d, min=%d, max=%d",
__func__, advertise, rfd->min_prefix_lifetime,
rfd->max_prefix_lifetime);
return (advertise != 0);
return (advertise != 0);
}
/*
/*
* Return Value
*
* 0 No need to advertise tunnel route
* non-0 advertise tunnel route
*/
int
rfapiApAdd (
struct bgp *bgp,
struct rfapi_descriptor *rfd,
struct prefix *pfx_ip,
struct prefix *pfx_eth,
struct prefix_rd *prd,
uint32_t lifetime,
uint8_t cost,
struct rfapi_l2address_option *l2o) /* other options TBD */
int rfapiApAdd(struct bgp *bgp, struct rfapi_descriptor *rfd,
struct prefix *pfx_ip, struct prefix *pfx_eth,
struct prefix_rd *prd, uint32_t lifetime, uint8_t cost,
struct rfapi_l2address_option *l2o) /* other options TBD */
{
int rc;
struct rfapi_adb *adb;
uint32_t old_lifetime = 0;
int use_ip0 = 0;
struct rfapi_rib_key rk;
int rc;
struct rfapi_adb *adb;
uint32_t old_lifetime = 0;
int use_ip0 = 0;
struct rfapi_rib_key rk;
rfapi_rib_key_init(pfx_ip, prd, pfx_eth, &rk);
if (RFAPI_0_PREFIX (pfx_ip) && RFAPI_HOST_PREFIX (pfx_ip))
{
use_ip0 = 1;
assert (pfx_eth);
rc =
skiplist_search (rfd->advertised.ip0_by_ether, &rk,
(void **) &adb);
rfapi_rib_key_init(pfx_ip, prd, pfx_eth, &rk);
if (RFAPI_0_PREFIX(pfx_ip) && RFAPI_HOST_PREFIX(pfx_ip)) {
use_ip0 = 1;
assert(pfx_eth);
rc = skiplist_search(rfd->advertised.ip0_by_ether, &rk,
(void **)&adb);
}
else
{
} else {
/* find prefix in advertised prefixes list */
rc =
skiplist_search (rfd->advertised.ipN_by_prefix, &rk,
(void **) &adb);
}
/* find prefix in advertised prefixes list */
rc = skiplist_search(rfd->advertised.ipN_by_prefix, &rk,
(void **)&adb);
}
if (rc)
{
/* Not found */
adb = XCALLOC (MTYPE_RFAPI_ADB, sizeof (struct rfapi_adb));
assert (adb);
adb->lifetime = lifetime;
adb->u.key = rk;
if (rc) {
/* Not found */
adb = XCALLOC(MTYPE_RFAPI_ADB, sizeof(struct rfapi_adb));
assert(adb);
adb->lifetime = lifetime;
adb->u.key = rk;
if (use_ip0)
{
assert (pfx_eth);
skiplist_insert (rfd->advertised.ip0_by_ether, &adb->u.key,
adb);
}
else
{
skiplist_insert (rfd->advertised.ipN_by_prefix, &adb->u.key,
adb);
}
if (use_ip0) {
assert(pfx_eth);
skiplist_insert(rfd->advertised.ip0_by_ether,
&adb->u.key, adb);
} else {
skiplist_insert(rfd->advertised.ipN_by_prefix,
&adb->u.key, adb);
}
skiplist_insert (rfd->advertised.by_lifetime, adb, adb);
}
else
{
old_lifetime = adb->lifetime;
if (old_lifetime != lifetime)
{
assert (!skiplist_delete (rfd->advertised.by_lifetime, adb, NULL));
adb->lifetime = lifetime;
assert (!skiplist_insert (rfd->advertised.by_lifetime, adb, adb));
}
}
adb->cost = cost;
if (l2o)
adb->l2o = *l2o;
else
memset (&adb->l2o, 0, sizeof (struct rfapi_l2address_option));
skiplist_insert(rfd->advertised.by_lifetime, adb, adb);
} else {
old_lifetime = adb->lifetime;
if (old_lifetime != lifetime) {
assert(!skiplist_delete(rfd->advertised.by_lifetime,
adb, NULL));
adb->lifetime = lifetime;
assert(!skiplist_insert(rfd->advertised.by_lifetime,
adb, adb));
}
}
adb->cost = cost;
if (l2o)
adb->l2o = *l2o;
else
memset(&adb->l2o, 0, sizeof(struct rfapi_l2address_option));
if (rfapiApAdjustLifetimeStats
(rfd, (rc ? NULL : &old_lifetime), &lifetime))
return 1;
if (rfapiApAdjustLifetimeStats(rfd, (rc ? NULL : &old_lifetime),
&lifetime))
return 1;
return 0;
return 0;
}
/*
* After this function returns successfully, caller should call
* rfapiAdjustLifetimeStats() and possibly rfapiTunnelRouteAnnounce()
*/
int
rfapiApDelete (
struct bgp *bgp,
struct rfapi_descriptor *rfd,
struct prefix *pfx_ip,
struct prefix *pfx_eth,
struct prefix_rd *prd,
int *advertise_tunnel) /* out */
int rfapiApDelete(struct bgp *bgp, struct rfapi_descriptor *rfd,
struct prefix *pfx_ip, struct prefix *pfx_eth,
struct prefix_rd *prd, int *advertise_tunnel) /* out */
{
int rc;
struct rfapi_adb *adb;
uint32_t old_lifetime;
int use_ip0 = 0;
struct rfapi_rib_key rk;
int rc;
struct rfapi_adb *adb;
uint32_t old_lifetime;
int use_ip0 = 0;
struct rfapi_rib_key rk;
if (advertise_tunnel)
*advertise_tunnel = 0;
if (advertise_tunnel)
*advertise_tunnel = 0;
rfapi_rib_key_init(pfx_ip, prd, pfx_eth, &rk);
/* find prefix in advertised prefixes list */
if (RFAPI_0_PREFIX (pfx_ip) && RFAPI_HOST_PREFIX (pfx_ip))
{
use_ip0 = 1;
assert (pfx_eth);
rfapi_rib_key_init(pfx_ip, prd, pfx_eth, &rk);
/* find prefix in advertised prefixes list */
if (RFAPI_0_PREFIX(pfx_ip) && RFAPI_HOST_PREFIX(pfx_ip)) {
use_ip0 = 1;
assert(pfx_eth);
rc =
skiplist_search (rfd->advertised.ip0_by_ether, &rk,
(void **) &adb);
rc = skiplist_search(rfd->advertised.ip0_by_ether, &rk,
(void **)&adb);
}
else
{
} else {
/* find prefix in advertised prefixes list */
rc =
skiplist_search (rfd->advertised.ipN_by_prefix, &rk,
(void **) &adb);
}
/* find prefix in advertised prefixes list */
rc = skiplist_search(rfd->advertised.ipN_by_prefix, &rk,
(void **)&adb);
}
if (rc)
{
return ENOENT;
}
if (rc) {
return ENOENT;
}
old_lifetime = adb->lifetime;
old_lifetime = adb->lifetime;
if (use_ip0)
{
rc = skiplist_delete (rfd->advertised.ip0_by_ether, &rk, NULL);
}
else
{
rc = skiplist_delete (rfd->advertised.ipN_by_prefix, &rk, NULL);
}
assert (!rc);
if (use_ip0) {
rc = skiplist_delete(rfd->advertised.ip0_by_ether, &rk, NULL);
} else {
rc = skiplist_delete(rfd->advertised.ipN_by_prefix, &rk, NULL);
}
assert(!rc);
rc = skiplist_delete (rfd->advertised.by_lifetime, adb, NULL);
assert (!rc);
rc = skiplist_delete(rfd->advertised.by_lifetime, adb, NULL);
assert(!rc);
rfapiAdbFree (adb);
rfapiAdbFree(adb);
if (rfapiApAdjustLifetimeStats (rfd, &old_lifetime, NULL))
{
if (advertise_tunnel)
*advertise_tunnel = 1;
}
if (rfapiApAdjustLifetimeStats(rfd, &old_lifetime, NULL)) {
if (advertise_tunnel)
*advertise_tunnel = 1;
}
return 0;
return 0;
}

View File

@ -1,4 +1,4 @@
/*
/*
*
* Copyright 2009-2016, LabN Consulting, L.L.C.
*
@ -56,44 +56,30 @@
#include "rfapi_rib.h"
extern void
rfapiApInit (struct rfapi_advertised_prefixes *ap);
extern void rfapiApInit(struct rfapi_advertised_prefixes *ap);
extern void
rfapiApRelease (struct rfapi_advertised_prefixes *ap);
extern void rfapiApRelease(struct rfapi_advertised_prefixes *ap);
extern int rfapiApCount(struct rfapi_descriptor *rfd);
extern int rfapiApCountAll(struct bgp *bgp);
extern void rfapiApReadvertiseAll(struct bgp *bgp,
struct rfapi_descriptor *rfd);
extern void rfapiApWithdrawAll(struct bgp *bgp, struct rfapi_descriptor *rfd);
extern int
rfapiApCount (struct rfapi_descriptor *rfd);
rfapiApAdd(struct bgp *bgp, struct rfapi_descriptor *rfd, struct prefix *pfx_ip,
struct prefix *pfx_eth, struct prefix_rd *prd, uint32_t lifetime,
uint8_t cost,
struct rfapi_l2address_option *l2o); /* other options TBD */
extern int
rfapiApCountAll (struct bgp *bgp);
extern void
rfapiApReadvertiseAll (struct bgp *bgp, struct rfapi_descriptor *rfd);
extern void
rfapiApWithdrawAll (struct bgp *bgp, struct rfapi_descriptor *rfd);
extern int
rfapiApAdd (
struct bgp *bgp,
struct rfapi_descriptor *rfd,
struct prefix *pfx_ip,
struct prefix *pfx_eth,
struct prefix_rd *prd,
uint32_t lifetime,
uint8_t cost,
struct rfapi_l2address_option *l2o); /* other options TBD */
extern int
rfapiApDelete (
struct bgp *bgp,
struct rfapi_descriptor *rfd,
struct prefix *pfx_ip,
struct prefix *pfx_eth,
struct prefix_rd *prd,
int *advertise_tunnel); /* out */
extern int rfapiApDelete(struct bgp *bgp, struct rfapi_descriptor *rfd,
struct prefix *pfx_ip, struct prefix *pfx_eth,
struct prefix_rd *prd,
int *advertise_tunnel); /* out */
#endif /* _QUAGGA_BGP_RFAPI_AP_H */

View File

@ -1,4 +1,4 @@
/*
/*
*
* Copyright 2009-2016, LabN Consulting, L.L.C.
*
@ -26,56 +26,44 @@
#include "bgpd/bgp_route.h"
#include "bgpd/bgp_nexthop.h"
extern void rfapi_init (void);
extern void vnc_zebra_init (struct thread_master *master);
extern void vnc_zebra_destroy (void);
extern void rfapi_init(void);
extern void vnc_zebra_init(struct thread_master *master);
extern void vnc_zebra_destroy(void);
extern void rfapi_delete (struct bgp *);
extern void rfapi_delete(struct bgp *);
struct rfapi *bgp_rfapi_new (struct bgp *bgp);
void bgp_rfapi_destroy (struct bgp *bgp, struct rfapi *h);
struct rfapi *bgp_rfapi_new(struct bgp *bgp);
void bgp_rfapi_destroy(struct bgp *bgp, struct rfapi *h);
extern void
rfapiProcessUpdate (struct peer *peer,
void *rfd,
struct prefix *p,
struct prefix_rd *prd,
struct attr *attr,
afi_t afi,
safi_t safi,
u_char type, u_char sub_type, uint32_t * label);
extern void rfapiProcessUpdate(struct peer *peer, void *rfd, struct prefix *p,
struct prefix_rd *prd, struct attr *attr,
afi_t afi, safi_t safi, u_char type,
u_char sub_type, uint32_t *label);
extern void
rfapiProcessWithdraw (struct peer *peer,
void *rfd,
struct prefix *p,
struct prefix_rd *prd,
struct attr *attr,
afi_t afi, safi_t safi, u_char type, int kill);
extern void rfapiProcessWithdraw(struct peer *peer, void *rfd, struct prefix *p,
struct prefix_rd *prd, struct attr *attr,
afi_t afi, safi_t safi, u_char type, int kill);
extern void rfapiProcessPeerDown (struct peer *peer);
extern void rfapiProcessPeerDown(struct peer *peer);
extern void
vnc_zebra_announce (struct prefix *p,
struct bgp_info *new_select, struct bgp *bgp);
extern void vnc_zebra_announce(struct prefix *p, struct bgp_info *new_select,
struct bgp *bgp);
extern void
vnc_zebra_withdraw (struct prefix *p, struct bgp_info *old_select);
extern void vnc_zebra_withdraw(struct prefix *p, struct bgp_info *old_select);
extern void
rfapi_vty_out_vncinfo (struct vty *vty,
struct prefix *p, struct bgp_info *bi, safi_t safi);
extern void rfapi_vty_out_vncinfo(struct vty *vty, struct prefix *p,
struct bgp_info *bi, safi_t safi);
extern void vnc_direct_bgp_vpn_enable (struct bgp *bgp, afi_t afi);
extern void vnc_direct_bgp_vpn_enable(struct bgp *bgp, afi_t afi);
extern void vnc_direct_bgp_vpn_disable (struct bgp *bgp, afi_t afi);
extern void vnc_direct_bgp_vpn_disable(struct bgp *bgp, afi_t afi);
extern void vnc_direct_bgp_rh_vpn_enable (struct bgp *bgp, afi_t afi);
extern void vnc_direct_bgp_rh_vpn_enable(struct bgp *bgp, afi_t afi);
extern void vnc_direct_bgp_rh_vpn_disable (struct bgp *bgp, afi_t afi);
extern void vnc_direct_bgp_rh_vpn_disable(struct bgp *bgp, afi_t afi);
#endif /* ENABLE_BGP_VNC */

View File

@ -1,4 +1,4 @@
/*
/*
*
* Copyright 2009-2016, LabN Consulting, L.L.C.
*
@ -36,15 +36,14 @@
#include "bgpd/rfapi/vnc_debug.h"
void *
rfapi_create_generic (struct rfapi_ip_addr *vn, struct rfapi_ip_addr *un)
void *rfapi_create_generic(struct rfapi_ip_addr *vn, struct rfapi_ip_addr *un)
{
struct rfapi_descriptor *rfd;
rfd = XCALLOC (MTYPE_RFAPI_DESC, sizeof (struct rfapi_descriptor));
vnc_zlog_debug_verbose ("%s: rfd=%p", __func__, rfd);
rfd->vn_addr = *vn;
rfd->un_addr = *un;
return (void *) rfd;
struct rfapi_descriptor *rfd;
rfd = XCALLOC(MTYPE_RFAPI_DESC, sizeof(struct rfapi_descriptor));
vnc_zlog_debug_verbose("%s: rfd=%p", __func__, rfd);
rfd->vn_addr = *vn;
rfd->un_addr = *un;
return (void *)rfd;
}
/*------------------------------------------
@ -52,20 +51,19 @@ rfapi_create_generic (struct rfapi_ip_addr *vn, struct rfapi_ip_addr *un)
*
* Compare two generic rfapi descriptors.
*
* input:
* input:
* grfd: rfapi descriptor returned by rfapi_open or rfapi_create_generic
*
* output:
*
* return value:
* return value:
*
*------------------------------------------*/
void
rfapi_free_generic (void *grfd)
void rfapi_free_generic(void *grfd)
{
struct rfapi_descriptor *rfd;
rfd = (struct rfapi_descriptor *) grfd;
XFREE (MTYPE_RFAPI_DESC, rfd);
struct rfapi_descriptor *rfd;
rfd = (struct rfapi_descriptor *)grfd;
XFREE(MTYPE_RFAPI_DESC, rfd);
}
@ -74,7 +72,7 @@ rfapi_free_generic (void *grfd)
*
* Compare two generic rfapi descriptors.
*
* input:
* input:
* rfd1: rfapi descriptor returned by rfapi_open or rfapi_create_generic
* rfd2: rfapi descriptor returned by rfapi_open or rfapi_create_generic
*
@ -84,48 +82,45 @@ rfapi_free_generic (void *grfd)
* 0 Mismatch
* 1 Match
*------------------------------------------*/
int
rfapi_compare_rfds (void *rfd1, void *rfd2)
int rfapi_compare_rfds(void *rfd1, void *rfd2)
{
struct rfapi_descriptor *rrfd1, *rrfd2;
int match = 0;
struct rfapi_descriptor *rrfd1, *rrfd2;
int match = 0;
rrfd1 = (struct rfapi_descriptor *) rfd1;
rrfd2 = (struct rfapi_descriptor *) rfd2;
rrfd1 = (struct rfapi_descriptor *)rfd1;
rrfd2 = (struct rfapi_descriptor *)rfd2;
if (rrfd1->vn_addr.addr_family == rrfd2->vn_addr.addr_family)
{
if (rrfd1->vn_addr.addr_family == AF_INET)
match = IPV4_ADDR_SAME (&(rrfd1->vn_addr.addr.v4),
&(rrfd2->vn_addr.addr.v4));
else
match = IPV6_ADDR_SAME (&(rrfd1->vn_addr.addr.v6),
&(rrfd2->vn_addr.addr.v6));
}
if (rrfd1->vn_addr.addr_family == rrfd2->vn_addr.addr_family) {
if (rrfd1->vn_addr.addr_family == AF_INET)
match = IPV4_ADDR_SAME(&(rrfd1->vn_addr.addr.v4),
&(rrfd2->vn_addr.addr.v4));
else
match = IPV6_ADDR_SAME(&(rrfd1->vn_addr.addr.v6),
&(rrfd2->vn_addr.addr.v6));
}
/*
* If the VN addresses don't match in all forms,
* give up.
*/
if (!match)
return 0;
/*
* If the VN addresses don't match in all forms,
* give up.
*/
if (!match)
return 0;
/*
* do the process again for the UN addresses.
*/
match = 0;
if (rrfd1->un_addr.addr_family == rrfd2->un_addr.addr_family)
{
/* VN addresses match
* UN address families match
* now check the actual UN addresses
*/
if (rrfd1->un_addr.addr_family == AF_INET)
match = IPV4_ADDR_SAME (&(rrfd1->un_addr.addr.v4),
&(rrfd2->un_addr.addr.v4));
else
match = IPV6_ADDR_SAME (&(rrfd1->un_addr.addr.v6),
&(rrfd2->un_addr.addr.v6));
}
return match;
/*
* do the process again for the UN addresses.
*/
match = 0;
if (rrfd1->un_addr.addr_family == rrfd2->un_addr.addr_family) {
/* VN addresses match
* UN address families match
* now check the actual UN addresses
*/
if (rrfd1->un_addr.addr_family == AF_INET)
match = IPV4_ADDR_SAME(&(rrfd1->un_addr.addr.v4),
&(rrfd2->un_addr.addr.v4));
else
match = IPV6_ADDR_SAME(&(rrfd1->un_addr.addr.v6),
&(rrfd2->un_addr.addr.v6));
}
return match;
}

View File

@ -1,4 +1,4 @@
/*
/*
*
* Copyright 2009-2016, LabN Consulting, L.L.C.
*
@ -19,20 +19,20 @@
*/
extern void *rfapi_create_generic (struct rfapi_ip_addr *vn,
struct rfapi_ip_addr *un);
extern void *rfapi_create_generic(struct rfapi_ip_addr *vn,
struct rfapi_ip_addr *un);
/*------------------------------------------
* rfapi_free_generic
*
* Compare two generic rfapi descriptors.
*
* input:
* input:
* grfd: rfapi descriptor returned by rfapi_open or rfapi_create_generic
*
* output:
*
* return value:
* return value:
*
*------------------------------------------*/
extern void rfapi_free_generic (void *grfd);
extern void rfapi_free_generic(void *grfd);

File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More