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.after
debian/autoreconf.before debian/autoreconf.before
debian/files debian/files
debian/quagga-dbg.debhelper.log debian/frr-dbg.debhelper.log
debian/quagga-dbg.substvars debian/frr-dbg.substvars
debian/quagga-dbg/ debian/frr-dbg/
debian/quagga-doc.debhelper.log debian/frr-doc.debhelper.log
debian/quagga-doc.substvars debian/frr-doc.substvars
debian/quagga-doc/ debian/frr-doc/
debian/quagga.debhelper.log debian/frr.debhelper.log
debian/quagga.postinst.debhelper debian/frr.postinst.debhelper
debian/quagga.postrm.debhelper debian/frr.postrm.debhelper
debian/quagga.prerm.debhelper debian/frr.prerm.debhelper
debian/quagga.substvars debian/frr.substvars
debian/quagga/ debian/frr/
debian/tmp/ debian/tmp/
*.pyc *.pyc
*.swp *.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. should use a DEFUN to encapsulate one setting as much as is possible.
Additionally as new DEFUN's are added to the system, documentation Additionally as new DEFUN's are added to the system, documentation
should be provided for the new commands. 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 \ DIST_SUBDIRS = lib qpb fpm zebra bgpd ripd ripngd ospfd ospf6d ldpd \
isisd watchfrr vtysh ospfclient doc m4 pkgsrc redhat tests \ isisd watchfrr vtysh ospfclient doc m4 pkgsrc redhat tests \
solaris pimd nhrpd eigrpd @LIBRFP@ @RFPTEST@ tools snapcraft \ solaris pimd nhrpd eigrpd bgpd/rfp-example/librfp \
babeld \ bgpd/rfp-example/rfptest tools snapcraft babeld python \
python \
# end # end
EXTRA_DIST = aclocal.m4 SERVICES REPORTING-BUGS \ EXTRA_DIST = aclocal.m4 SERVICES REPORTING-BUGS \

View File

@ -1,18 +1,18 @@
#!/bin/sh #!/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. # probably on any system using pkgsrc.
# One should have readline installed already (pkgsrc/devel/readline). # One should have readline installed already (pkgsrc/devel/readline).
MAKE=make 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. # BSD make fails. Enable this if statement as a workaround.
if false; then if false; then
MAKE=gmake MAKE=gmake
echo "WARNING: using gmake to work around nonportable makefiles" echo "WARNING: using gmake to work around nonportable makefiles"
fi 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 PREFIX=/usr/pkg
case $1 in 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. 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. 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 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 3. Problem description. Copy and paste relative commands and their output to
describe your network setup e.g. "zebra>show ip route". describe your network setup e.g. "zebra>show ip route".
Please, also give your simple network layout and output of relative OS 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); ret = babel_enable_if_add (argv[1]->arg);
if (ret < 0) { 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); argv[1]->arg);
return CMD_WARNING; return CMD_WARNING_CONFIG_FAILED;
} }
return CMD_SUCCESS; return CMD_SUCCESS;
@ -318,8 +318,8 @@ DEFUN (no_babel_network,
ret = babel_enable_if_delete (argv[2]->arg); ret = babel_enable_if_delete (argv[2]->arg);
if (ret < 0) { if (ret < 0) {
vty_outln (vty, "can't find network %s",argv[2]->arg); vty_out (vty, "can't find network %s\n",argv[2]->arg);
return CMD_WARNING; return CMD_WARNING_CONFIG_FAILED;
} }
return CMD_SUCCESS; return CMD_SUCCESS;
@ -861,31 +861,31 @@ show_babel_interface_sub (struct vty *vty, struct interface *ifp)
int is_up; int is_up;
babel_interface_nfo *babel_ifp; 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")); ((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)); ifp->ifindex, MIN(ifp->mtu, ifp->mtu6), if_flag_dump(ifp->flags));
if (!IS_ENABLE(ifp)) 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; return;
} }
if (!is_up) if (!is_up)
{ {
vty_outln (vty, vty_out (vty,
" Babel protocol is enabled, but not running on this interface"); " Babel protocol is enabled, but not running on this interface\n");
return; return;
} }
babel_ifp = babel_get_if_nfo (ifp); babel_ifp = babel_get_if_nfo (ifp);
vty_outln (vty, " Babel protocol is running on this interface"); vty_out (vty, " Babel protocol is running on this interface\n");
vty_outln (vty, " Operating mode is \"%s\"", vty_out (vty, " Operating mode is \"%s\"\n",
CHECK_FLAG(babel_ifp->flags, BABEL_IF_WIRED) ? "wired" : "wireless"); 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"); CHECK_FLAG(babel_ifp->flags, BABEL_IF_SPLIT_HORIZON) ? "On" : "Off");
vty_outln (vty, " Hello interval is %u ms", babel_ifp->hello_interval); vty_out (vty, " Hello interval is %u ms\n", babel_ifp->hello_interval);
vty_outln (vty, " Update interval is %u ms", babel_ifp->update_interval); vty_out (vty, " Update interval is %u ms\n", babel_ifp->update_interval);
vty_outln (vty, " Rxcost multiplier is %u", babel_ifp->cost); vty_out (vty, " Rxcost multiplier is %u\n", babel_ifp->cost);
} }
DEFUN (show_babel_interface, DEFUN (show_babel_interface,
@ -907,7 +907,7 @@ DEFUN (show_babel_interface,
} }
if ((ifp = if_lookup_by_name (argv[3]->arg, VRF_DEFAULT)) == NULL) 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; return CMD_WARNING;
} }
show_babel_interface_sub (vty, ifp); show_babel_interface_sub (vty, ifp);
@ -917,9 +917,9 @@ DEFUN (show_babel_interface,
static void static void
show_babel_neighbour_sub (struct vty *vty, struct neighbour *neigh) 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 " "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), format_address(neigh->address),
neigh->ifp->name, neigh->ifp->name,
neigh->reach, neigh->reach,
@ -949,7 +949,7 @@ DEFUN (show_babel_neighbour,
} }
if ((ifp = if_lookup_by_name (argv[3]->arg, VRF_DEFAULT)) == NULL) 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; return CMD_WARNING;
} }
FOR_ALL_NEIGHBOURS(neigh) { FOR_ALL_NEIGHBOURS(neigh) {
@ -1009,9 +1009,9 @@ show_babel_routes_sub(struct babel_route *route, struct vty *vty,
channels[0] = '\0'; channels[0] = '\0';
} }
vty_outln (vty, vty_out (vty,
"%s metric %d refmetric %d id %s seqno %d%s age %d " "%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), format_prefix(route->src->prefix, route->src->plen),
route_metric(route), route->refmetric, route_metric(route), route->refmetric,
format_eui64(route->src->id), 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)) if(prefix && !babel_prefix_eq(prefix, xroute->prefix, xroute->plen))
return; return;
vty_outln (vty, "%s metric %d (exported)", vty_out (vty, "%s metric %d (exported)\n",
format_prefix(xroute->prefix, xroute->plen), format_prefix(xroute->prefix, xroute->plen),
xroute->metric); xroute->metric);
} }
@ -1089,7 +1089,7 @@ DEFUN (show_babel_route_prefix,
ret = str2prefix(argv[3]->arg, &prefix); ret = str2prefix(argv[3]->arg, &prefix);
if(ret == 0) { if(ret == 0) {
vty_outln (vty, "%% Malformed address"); vty_out (vty, "%% Malformed address\n");
return CMD_WARNING; return CMD_WARNING;
} }
@ -1138,7 +1138,7 @@ DEFUN (show_babel_route_addr,
ret = inet_aton (argv[3]->arg, &addr); ret = inet_aton (argv[3]->arg, &addr);
if (ret <= 0) { if (ret <= 0) {
vty_outln (vty, "%% Malformed address"); vty_out (vty, "%% Malformed address\n");
return CMD_WARNING; return CMD_WARNING;
} }
@ -1147,7 +1147,7 @@ DEFUN (show_babel_route_addr,
ret = str2prefix(buf, &prefix); ret = str2prefix(buf, &prefix);
if (ret == 0) { 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; return CMD_WARNING;
} }
@ -1196,7 +1196,7 @@ DEFUN (show_babel_route_addr6,
ret = inet_pton (AF_INET6, argv[3]->arg, &addr); ret = inet_pton (AF_INET6, argv[3]->arg, &addr);
if (ret <= 0) { if (ret <= 0) {
vty_outln (vty, "%% Malformed address"); vty_out (vty, "%% Malformed address\n");
return CMD_WARNING; return CMD_WARNING;
} }
@ -1206,7 +1206,7 @@ DEFUN (show_babel_route_addr6,
ret = str2prefix(buf, &prefix); ret = str2prefix(buf, &prefix);
if (ret == 0) { 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; return CMD_WARNING;
} }
@ -1244,9 +1244,9 @@ DEFUN (show_babel_parameters,
"Babel information\n" "Babel information\n"
"Configuration information\n") "Configuration information\n")
{ {
vty_outln (vty, " -- Babel running configuration --"); vty_out (vty, " -- Babel running configuration --\n");
show_babel_main_configuration(vty); show_babel_main_configuration(vty);
vty_outln (vty, " -- distribution lists --"); vty_out (vty, " -- distribution lists --\n");
config_show_distribute(vty); config_show_distribute(vty);
return CMD_SUCCESS; return CMD_SUCCESS;
@ -1321,63 +1321,63 @@ interface_config_write (struct vty *vty)
int write = 0; int write = 0;
for (ALL_LIST_ELEMENTS_RO (vrf_iflist(VRF_DEFAULT), node, ifp)) { 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) 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); babel_interface_nfo *babel_ifp = babel_get_if_nfo (ifp);
/* wireless is the default*/ /* wireless is the default*/
if (CHECK_FLAG (babel_ifp->flags, BABEL_IF_WIRED)) if (CHECK_FLAG (babel_ifp->flags, BABEL_IF_WIRED))
{ {
vty_outln (vty, " babel wired"); vty_out (vty, " babel wired\n");
write++; write++;
} }
if (babel_ifp->hello_interval != BABEL_DEFAULT_HELLO_INTERVAL) 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); babel_ifp->hello_interval);
write++; write++;
} }
if (babel_ifp->update_interval != BABEL_DEFAULT_UPDATE_INTERVAL) 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); babel_ifp->update_interval);
write++; write++;
} }
/* Some parameters have different defaults for wired/wireless. */ /* 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_WIRED)) {
if (!CHECK_FLAG (babel_ifp->flags, BABEL_IF_SPLIT_HORIZON)) { 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++; write++;
} }
if (babel_ifp->cost != BABEL_DEFAULT_RXCOST_WIRED) { 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++; write++;
} }
if (babel_ifp->channel == BABEL_IF_CHANNEL_INTERFERING) { if (babel_ifp->channel == BABEL_IF_CHANNEL_INTERFERING) {
vty_outln (vty, " babel channel interfering"); vty_out (vty, " babel channel interfering\n");
write++; write++;
} else if(babel_ifp->channel != BABEL_IF_CHANNEL_NONINTERFERING) { } 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++; write++;
} }
} else { } else {
if (CHECK_FLAG (babel_ifp->flags, BABEL_IF_SPLIT_HORIZON)) { if (CHECK_FLAG (babel_ifp->flags, BABEL_IF_SPLIT_HORIZON)) {
vty_outln (vty, " babel split-horizon"); vty_out (vty, " babel split-horizon\n");
write++; write++;
} }
if (babel_ifp->cost != BABEL_DEFAULT_RXCOST_WIRELESS) { 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++; write++;
} }
if (babel_ifp->channel == BABEL_IF_CHANNEL_NONINTERFERING) { if (babel_ifp->channel == BABEL_IF_CHANNEL_NONINTERFERING) {
vty_outln (vty, " babel channel noninterfering"); vty_out (vty, " babel channel noninterfering\n");
write++; write++;
} else if(babel_ifp->channel != BABEL_IF_CHANNEL_INTERFERING) { } 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++; write++;
} }
} }
vty_outln (vty, "!"); vty_out (vty, "!\n");
write++; write++;
} }
return 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++) for (i = 0; i < vector_active (babel_enable_if); i++)
if ((str = vector_slot (babel_enable_if, i)) != NULL) if ((str = vector_slot (babel_enable_if, i)) != NULL)
{ {
vty_outln (vty, " network %s", str); vty_out (vty, " network %s\n", str);
lines++; lines++;
} }
return lines; return lines;

View File

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

View File

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

View File

@ -83,25 +83,25 @@ babel_config_write (struct vty *vty)
if (!babel_routing_process) if (!babel_routing_process)
return lines; return lines;
vty_outln (vty, "router babel"); vty_out (vty, "router babel\n");
if (diversity_kind != DIVERSITY_NONE) if (diversity_kind != DIVERSITY_NONE)
{ {
vty_outln (vty, " babel diversity"); vty_out (vty, " babel diversity\n");
lines++; lines++;
} }
if (diversity_factor != BABEL_DEFAULT_DIVERSITY_FACTOR) 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++; lines++;
} }
if (resend_delay != BABEL_DEFAULT_RESEND_DELAY) 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++; lines++;
} }
if (smoothing_half_life != BABEL_DEFAULT_SMOOTHING_HALF_LIFE) 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); smoothing_half_life);
lines++; lines++;
} }
@ -112,7 +112,7 @@ babel_config_write (struct vty *vty)
if (i != zclient->redist_default && if (i != zclient->redist_default &&
vrf_bitmap_check (zclient->redist[AFI_IP][i], VRF_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++; lines++;
} }
@ -617,8 +617,7 @@ DEFUN (no_router_babel,
"no router babel", "no router babel",
NO_STR NO_STR
"Disable a routing process\n" "Disable a routing process\n"
"Remove Babel instance command\n" "Remove Babel instance command\n")
"No attributes\n")
{ {
if(babel_routing_process) if(babel_routing_process)
babel_clean_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_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_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_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 = \ noinst_HEADERS = \
bgp_memory.h \ bgp_memory.h \
@ -95,7 +95,7 @@ noinst_HEADERS = \
bgp_advertise.h bgp_vty.h bgp_mpath.h bgp_nht.h \ 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_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_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_SOURCES = bgp_main.c
bgpd_LDADD = libbgp.a $(BGP_VNC_RFP_LIB) ../lib/libfrr.la @LIBCAP@ @LIBM@ 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 /* BGP advertise attribute is used for pack same attribute update into
one packet. To do that we maintain attribute hash in struct one packet. To do that we maintain attribute hash in struct
peer. */ peer. */
struct bgp_advertise_attr * struct bgp_advertise_attr *baa_new(void)
baa_new (void)
{ {
return (struct bgp_advertise_attr *) return (struct bgp_advertise_attr *)XCALLOC(
XCALLOC (MTYPE_BGP_ADVERTISE_ATTR, sizeof (struct bgp_advertise_attr)); MTYPE_BGP_ADVERTISE_ATTR, sizeof(struct bgp_advertise_attr));
} }
static void static void baa_free(struct bgp_advertise_attr *baa)
baa_free (struct bgp_advertise_attr *baa)
{ {
XFREE (MTYPE_BGP_ADVERTISE_ATTR, baa); XFREE(MTYPE_BGP_ADVERTISE_ATTR, baa);
} }
static void * static void *baa_hash_alloc(void *p)
baa_hash_alloc (void *p)
{ {
struct bgp_advertise_attr * ref = (struct bgp_advertise_attr *) p; struct bgp_advertise_attr *ref = (struct bgp_advertise_attr *)p;
struct bgp_advertise_attr *baa; struct bgp_advertise_attr *baa;
baa = baa_new (); baa = baa_new();
baa->attr = ref->attr; baa->attr = ref->attr;
return baa; return baa;
} }
unsigned int unsigned int baa_hash_key(void *p)
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 int baa_hash_cmp(const void *p1, const void *p2)
baa_hash_cmp (const void *p1, const void *p2)
{ {
const struct bgp_advertise_attr * baa1 = p1; const struct bgp_advertise_attr *baa1 = p1;
const struct bgp_advertise_attr * baa2 = p2; 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 /* BGP update and withdraw information is stored in BGP advertise
structure. This structure is referred from BGP adjacency structure. This structure is referred from BGP adjacency
information. */ information. */
struct bgp_advertise * struct bgp_advertise *bgp_advertise_new(void)
bgp_advertise_new (void)
{ {
return (struct bgp_advertise *) return (struct bgp_advertise *)XCALLOC(MTYPE_BGP_ADVERTISE,
XCALLOC (MTYPE_BGP_ADVERTISE, sizeof (struct bgp_advertise)); sizeof(struct bgp_advertise));
} }
void void bgp_advertise_free(struct bgp_advertise *adv)
bgp_advertise_free (struct bgp_advertise *adv)
{ {
if (adv->binfo) if (adv->binfo)
bgp_info_unlock (adv->binfo); /* bgp_advertise bgp_info reference */ bgp_info_unlock(
XFREE (MTYPE_BGP_ADVERTISE, adv); adv->binfo); /* bgp_advertise bgp_info reference */
XFREE(MTYPE_BGP_ADVERTISE, adv);
} }
void void bgp_advertise_add(struct bgp_advertise_attr *baa,
bgp_advertise_add (struct bgp_advertise_attr *baa, struct bgp_advertise *adv)
struct bgp_advertise *adv)
{ {
adv->next = baa->adv; adv->next = baa->adv;
if (baa->adv) if (baa->adv)
baa->adv->prev = adv; baa->adv->prev = adv;
baa->adv = adv; baa->adv = adv;
} }
void void bgp_advertise_delete(struct bgp_advertise_attr *baa,
bgp_advertise_delete (struct bgp_advertise_attr *baa, struct bgp_advertise *adv)
struct bgp_advertise *adv)
{ {
if (adv->next) if (adv->next)
adv->next->prev = adv->prev; adv->next->prev = adv->prev;
if (adv->prev) if (adv->prev)
adv->prev->next = adv->next; adv->prev->next = adv->next;
else else
baa->adv = adv->next; baa->adv = adv->next;
} }
struct bgp_advertise_attr * struct bgp_advertise_attr *bgp_advertise_intern(struct hash *hash,
bgp_advertise_intern (struct hash *hash, struct attr *attr) struct attr *attr)
{ {
struct bgp_advertise_attr ref; struct bgp_advertise_attr ref;
struct bgp_advertise_attr *baa; struct bgp_advertise_attr *baa;
ref.attr = bgp_attr_intern (attr); ref.attr = bgp_attr_intern(attr);
baa = (struct bgp_advertise_attr *) hash_get (hash, &ref, baa_hash_alloc); baa = (struct bgp_advertise_attr *)hash_get(hash, &ref, baa_hash_alloc);
baa->refcnt++; baa->refcnt++;
return baa; return baa;
} }
void void bgp_advertise_unintern(struct hash *hash, struct bgp_advertise_attr *baa)
bgp_advertise_unintern (struct hash *hash, struct bgp_advertise_attr *baa)
{ {
if (baa->refcnt) if (baa->refcnt)
baa->refcnt--; baa->refcnt--;
if (baa->refcnt && baa->attr) if (baa->refcnt && baa->attr)
bgp_attr_unintern (&baa->attr); bgp_attr_unintern(&baa->attr);
else else {
{ if (baa->attr) {
if (baa->attr) hash_release(hash, baa);
{ bgp_attr_unintern(&baa->attr);
hash_release (hash, baa); }
bgp_attr_unintern (&baa->attr); baa_free(baa);
} }
baa_free (baa);
}
} }
int int bgp_adj_out_lookup(struct peer *peer, struct bgp_node *rn,
bgp_adj_out_lookup (struct peer *peer, struct bgp_node *rn, u_int32_t addpath_tx_id)
u_int32_t addpath_tx_id)
{ {
struct bgp_adj_out *adj; struct bgp_adj_out *adj;
struct peer_af *paf; struct peer_af *paf;
afi_t afi; afi_t afi;
safi_t safi; safi_t safi;
int addpath_capable; int addpath_capable;
for (adj = rn->adj_out; adj; adj = adj->next) for (adj = rn->adj_out; adj; adj = adj->next)
SUBGRP_FOREACH_PEER(adj->subgroup, paf) SUBGRP_FOREACH_PEER(adj->subgroup, paf)
if (paf->peer == peer) if (paf->peer == peer) {
{ afi = SUBGRP_AFI(adj->subgroup);
afi = SUBGRP_AFI (adj->subgroup); safi = SUBGRP_SAFI(adj->subgroup);
safi = SUBGRP_SAFI (adj->subgroup); addpath_capable = bgp_addpath_encode_tx(peer, afi, safi);
addpath_capable = bgp_addpath_encode_tx (peer, afi, safi);
/* Match on a specific addpath_tx_id if we are using addpath for this /* Match on a specific addpath_tx_id if we are using addpath for
* peer and if an addpath_tx_id was specified */ * this
if (addpath_capable && addpath_tx_id && adj->addpath_tx_id != addpath_tx_id) * peer and if an addpath_tx_id was specified */
continue; if (addpath_capable && addpath_tx_id
&& adj->addpath_tx_id != addpath_tx_id)
continue;
return (adj->adv return (adj->adv ? (adj->adv->baa ? 1 : 0)
? (adj->adv->baa ? 1 : 0) : (adj->attr ? 1 : 0));
: (adj->attr ? 1 : 0));
} }
return 0; return 0;
} }
void void bgp_adj_in_set(struct bgp_node *rn, struct peer *peer, struct attr *attr,
bgp_adj_in_set (struct bgp_node *rn, struct peer *peer, struct attr *attr, u_int32_t addpath_id)
u_int32_t addpath_id)
{ {
struct bgp_adj_in *adj; struct bgp_adj_in *adj;
for (adj = rn->adj_in; adj; adj = adj->next) for (adj = rn->adj_in; adj; adj = adj->next) {
{ if (adj->peer == peer && adj->addpath_rx_id == addpath_id) {
if (adj->peer == peer && adj->addpath_rx_id == addpath_id) if (adj->attr != attr) {
{ bgp_attr_unintern(&adj->attr);
if (adj->attr != attr) adj->attr = bgp_attr_intern(attr);
{ }
bgp_attr_unintern (&adj->attr); return;
adj->attr = bgp_attr_intern (attr); }
}
return;
} }
} adj = XCALLOC(MTYPE_BGP_ADJ_IN, sizeof(struct bgp_adj_in));
adj = XCALLOC (MTYPE_BGP_ADJ_IN, sizeof (struct bgp_adj_in)); adj->peer = peer_lock(peer); /* adj_in peer reference */
adj->peer = peer_lock (peer); /* adj_in peer reference */ adj->attr = bgp_attr_intern(attr);
adj->attr = bgp_attr_intern (attr); adj->addpath_rx_id = addpath_id;
adj->addpath_rx_id = addpath_id; BGP_ADJ_IN_ADD(rn, adj);
BGP_ADJ_IN_ADD (rn, adj); bgp_lock_node(rn);
bgp_lock_node (rn);
} }
void void bgp_adj_in_remove(struct bgp_node *rn, struct bgp_adj_in *bai)
bgp_adj_in_remove (struct bgp_node *rn, struct bgp_adj_in *bai)
{ {
bgp_attr_unintern (&bai->attr); bgp_attr_unintern(&bai->attr);
BGP_ADJ_IN_DEL (rn, bai); BGP_ADJ_IN_DEL(rn, bai);
peer_unlock (bai->peer); /* adj_in peer reference */ peer_unlock(bai->peer); /* adj_in peer reference */
XFREE (MTYPE_BGP_ADJ_IN, bai); XFREE(MTYPE_BGP_ADJ_IN, bai);
} }
int int bgp_adj_in_unset(struct bgp_node *rn, struct peer *peer,
bgp_adj_in_unset (struct bgp_node *rn, struct peer *peer, u_int32_t addpath_id)
u_int32_t addpath_id)
{ {
struct bgp_adj_in *adj; struct bgp_adj_in *adj;
struct bgp_adj_in *adj_next; struct bgp_adj_in *adj_next;
adj = rn->adj_in; adj = rn->adj_in;
if (!adj) if (!adj)
return 0; return 0;
while (adj) while (adj) {
{ adj_next = adj->next;
adj_next = adj->next;
if (adj->peer == peer && adj->addpath_rx_id == addpath_id) if (adj->peer == peer && adj->addpath_rx_id == addpath_id) {
{ bgp_adj_in_remove(rn, adj);
bgp_adj_in_remove (rn, adj); bgp_unlock_node(rn);
bgp_unlock_node (rn); }
}
adj = adj_next; adj = adj_next;
} }
return 1; return 1;
} }
void void bgp_sync_init(struct peer *peer)
bgp_sync_init (struct peer *peer)
{ {
afi_t afi; afi_t afi;
safi_t safi; safi_t safi;
struct bgp_synchronize *sync; struct bgp_synchronize *sync;
for (afi = AFI_IP; afi < AFI_MAX; afi++) for (afi = AFI_IP; afi < AFI_MAX; afi++)
for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) {
{ sync = XCALLOC(MTYPE_BGP_SYNCHRONISE,
sync = XCALLOC (MTYPE_BGP_SYNCHRONISE, sizeof(struct bgp_synchronize));
sizeof (struct bgp_synchronize)); BGP_ADV_FIFO_INIT(&sync->update);
BGP_ADV_FIFO_INIT (&sync->update); BGP_ADV_FIFO_INIT(&sync->withdraw);
BGP_ADV_FIFO_INIT (&sync->withdraw); BGP_ADV_FIFO_INIT(&sync->withdraw_low);
BGP_ADV_FIFO_INIT (&sync->withdraw_low); peer->sync[afi][safi] = sync;
peer->sync[afi][safi] = sync; peer->hash[afi][safi] =
peer->hash[afi][safi] = hash_create (baa_hash_key, baa_hash_cmp, NULL); hash_create(baa_hash_key, baa_hash_cmp, NULL);
} }
} }
void void bgp_sync_delete(struct peer *peer)
bgp_sync_delete (struct peer *peer)
{ {
afi_t afi; afi_t afi;
safi_t safi; safi_t safi;
for (afi = AFI_IP; afi < AFI_MAX; afi++) for (afi = AFI_IP; afi < AFI_MAX; afi++)
for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) {
{ if (peer->sync[afi][safi])
if (peer->sync[afi][safi]) XFREE(MTYPE_BGP_SYNCHRONISE,
XFREE (MTYPE_BGP_SYNCHRONISE, peer->sync[afi][safi]); peer->sync[afi][safi]);
peer->sync[afi][safi] = NULL; peer->sync[afi][safi] = NULL;
if (peer->hash[afi][safi]) if (peer->hash[afi][safi])
hash_free (peer->hash[afi][safi]); hash_free(peer->hash[afi][safi]);
peer->hash[afi][safi] = NULL; peer->hash[afi][safi] = NULL;
} }
} }

View File

@ -26,172 +26,168 @@
struct update_subgroup; struct update_subgroup;
/* BGP advertise FIFO. */ /* BGP advertise FIFO. */
struct bgp_advertise_fifo struct bgp_advertise_fifo {
{ struct bgp_advertise *next;
struct bgp_advertise *next; struct bgp_advertise *prev;
struct bgp_advertise *prev; u_int32_t count;
u_int32_t count;
}; };
/* BGP advertise attribute. */ /* BGP advertise attribute. */
struct bgp_advertise_attr struct bgp_advertise_attr {
{ /* Head of advertisement pointer. */
/* Head of advertisement pointer. */ struct bgp_advertise *adv;
struct bgp_advertise *adv;
/* Reference counter. */ /* Reference counter. */
unsigned long refcnt; unsigned long refcnt;
/* Attribute pointer to be announced. */ /* Attribute pointer to be announced. */
struct attr *attr; struct attr *attr;
}; };
struct bgp_advertise struct bgp_advertise {
{ /* FIFO for advertisement. */
/* FIFO for advertisement. */ struct bgp_advertise_fifo fifo;
struct bgp_advertise_fifo fifo;
/* Link list for same attribute advertise. */ /* Link list for same attribute advertise. */
struct bgp_advertise *next; struct bgp_advertise *next;
struct bgp_advertise *prev; struct bgp_advertise *prev;
/* Prefix information. */ /* Prefix information. */
struct bgp_node *rn; struct bgp_node *rn;
/* Reference pointer. */ /* Reference pointer. */
struct bgp_adj_out *adj; struct bgp_adj_out *adj;
/* Advertisement attribute. */ /* Advertisement attribute. */
struct bgp_advertise_attr *baa; struct bgp_advertise_attr *baa;
/* BGP info. */ /* BGP info. */
struct bgp_info *binfo; struct bgp_info *binfo;
}; };
/* BGP adjacency out. */ /* BGP adjacency out. */
struct bgp_adj_out struct bgp_adj_out {
{ /* Lined list pointer. */
/* Lined list pointer. */ struct bgp_adj_out *next;
struct bgp_adj_out *next; struct bgp_adj_out *prev;
struct bgp_adj_out *prev;
/* Advertised subgroup. */ /* Advertised subgroup. */
struct update_subgroup *subgroup; struct update_subgroup *subgroup;
/* Threading that makes the adj part of subgroup's adj queue */ /* Threading that makes the adj part of subgroup's adj queue */
TAILQ_ENTRY(bgp_adj_out) subgrp_adj_train; TAILQ_ENTRY(bgp_adj_out) subgrp_adj_train;
/* Prefix information. */ /* Prefix information. */
struct bgp_node *rn; struct bgp_node *rn;
u_int32_t addpath_tx_id; u_int32_t addpath_tx_id;
/* Advertised attribute. */ /* Advertised attribute. */
struct attr *attr; struct attr *attr;
/* Advertisement information. */ /* Advertisement information. */
struct bgp_advertise *adv; struct bgp_advertise *adv;
}; };
/* BGP adjacency in. */ /* BGP adjacency in. */
struct bgp_adj_in struct bgp_adj_in {
{ /* Linked list pointer. */
/* Linked list pointer. */ struct bgp_adj_in *next;
struct bgp_adj_in *next; struct bgp_adj_in *prev;
struct bgp_adj_in *prev;
/* Received peer. */ /* Received peer. */
struct peer *peer; struct peer *peer;
/* Received attribute. */ /* Received attribute. */
struct attr *attr; struct attr *attr;
/* Addpath identifier */ /* Addpath identifier */
u_int32_t addpath_rx_id; u_int32_t addpath_rx_id;
}; };
/* BGP advertisement list. */ /* BGP advertisement list. */
struct bgp_synchronize struct bgp_synchronize {
{ struct bgp_advertise_fifo update;
struct bgp_advertise_fifo update; struct bgp_advertise_fifo withdraw;
struct bgp_advertise_fifo withdraw; struct bgp_advertise_fifo withdraw_low;
struct bgp_advertise_fifo withdraw_low;
}; };
/* BGP adjacency linked list. */ /* BGP adjacency linked list. */
#define BGP_INFO_ADD(N,A,TYPE) \ #define BGP_INFO_ADD(N, A, TYPE) \
do { \ do { \
(A)->prev = NULL; \ (A)->prev = NULL; \
(A)->next = (N)->TYPE; \ (A)->next = (N)->TYPE; \
if ((N)->TYPE) \ if ((N)->TYPE) \
(N)->TYPE->prev = (A); \ (N)->TYPE->prev = (A); \
(N)->TYPE = (A); \ (N)->TYPE = (A); \
} while (0) } while (0)
#define BGP_INFO_DEL(N,A,TYPE) \ #define BGP_INFO_DEL(N, A, TYPE) \
do { \ do { \
if ((A)->next) \ if ((A)->next) \
(A)->next->prev = (A)->prev; \ (A)->next->prev = (A)->prev; \
if ((A)->prev) \ if ((A)->prev) \
(A)->prev->next = (A)->next; \ (A)->prev->next = (A)->next; \
else \ else \
(N)->TYPE = (A)->next; \ (N)->TYPE = (A)->next; \
} while (0) } while (0)
#define BGP_ADJ_IN_ADD(N,A) BGP_INFO_ADD(N,A,adj_in) #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_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_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_ADJ_OUT_DEL(N,A) BGP_INFO_DEL(N,A,adj_out)
#define BGP_ADV_FIFO_ADD(F, N) \ #define BGP_ADV_FIFO_ADD(F, N) \
do { \ do { \
FIFO_ADD((F), (N)); \ FIFO_ADD((F), (N)); \
(F)->count++; \ (F)->count++; \
} while (0) } while (0)
#define BGP_ADV_FIFO_DEL(F, N) \ #define BGP_ADV_FIFO_DEL(F, N) \
do { \ do { \
FIFO_DEL((N)); \ FIFO_DEL((N)); \
(F)->count--; \ (F)->count--; \
} while (0) } while (0)
#define BGP_ADV_FIFO_INIT(F) \ #define BGP_ADV_FIFO_INIT(F) \
do { \ do { \
FIFO_INIT((F)); \ FIFO_INIT((F)); \
(F)->count = 0; \ (F)->count = 0; \
} while (0) } while (0)
#define BGP_ADV_FIFO_COUNT(F) \ #define BGP_ADV_FIFO_COUNT(F) (F)->count
(F)->count
#define BGP_ADV_FIFO_EMPTY(F) \ #define BGP_ADV_FIFO_EMPTY(F) \
(((struct bgp_advertise_fifo *)(F))->next == (struct bgp_advertise *)(F)) (((struct bgp_advertise_fifo *)(F))->next \
== (struct bgp_advertise *)(F))
#define BGP_ADV_FIFO_HEAD(F) \ #define BGP_ADV_FIFO_HEAD(F) \
((((struct bgp_advertise_fifo *)(F))->next == (struct bgp_advertise *)(F)) \ ((((struct bgp_advertise_fifo *)(F))->next \
? NULL : (F)->next) == (struct bgp_advertise *)(F)) \
? NULL \
: (F)->next)
/* Prototypes. */ /* Prototypes. */
extern int bgp_adj_out_lookup (struct peer *, struct bgp_node *, u_int32_t); 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 void bgp_adj_in_set(struct bgp_node *, struct peer *, struct attr *,
extern int bgp_adj_in_unset (struct bgp_node *, struct peer *, u_int32_t); u_int32_t);
extern void bgp_adj_in_remove (struct bgp_node *, struct bgp_adj_in *); 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_init(struct peer *);
extern void bgp_sync_delete (struct peer *); extern void bgp_sync_delete(struct peer *);
extern unsigned int baa_hash_key (void *p); extern unsigned int baa_hash_key(void *p);
extern int baa_hash_cmp (const void *p1, const void *p2); extern int baa_hash_cmp(const void *p1, const void *p2);
extern void bgp_advertise_add (struct bgp_advertise_attr *baa, extern void bgp_advertise_add(struct bgp_advertise_attr *baa,
struct bgp_advertise *adv); struct bgp_advertise *adv);
extern struct bgp_advertise *bgp_advertise_new (void); extern struct bgp_advertise *bgp_advertise_new(void);
extern void bgp_advertise_free (struct bgp_advertise *adv); extern void bgp_advertise_free(struct bgp_advertise *adv);
extern struct bgp_advertise_attr * extern struct bgp_advertise_attr *bgp_advertise_intern(struct hash *hash,
bgp_advertise_intern (struct hash *hash, struct attr *attr); struct attr *attr);
extern struct bgp_advertise_attr *baa_new (void); extern struct bgp_advertise_attr *baa_new(void);
extern void extern void bgp_advertise_delete(struct bgp_advertise_attr *baa,
bgp_advertise_delete (struct bgp_advertise_attr *baa, struct bgp_advertise *adv);
struct bgp_advertise *adv); extern void bgp_advertise_unintern(struct hash *hash,
extern void struct bgp_advertise_attr *baa);
bgp_advertise_unintern (struct hash *hash, struct bgp_advertise_attr *baa);
#endif /* _QUAGGA_BGP_ADVERTISE_H */ #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 */ /* Transition 16Bit AS as defined by IANA */
#define BGP_AS_TRANS 23456U #define BGP_AS_TRANS 23456U
#define BGP_AS_IS_PRIVATE(ASN) \ #define BGP_AS_IS_PRIVATE(ASN) \
(((ASN) >= BGP_PRIVATE_AS_MIN && (ASN) <= BGP_PRIVATE_AS_MAX) || \ (((ASN) >= BGP_PRIVATE_AS_MIN && (ASN) <= BGP_PRIVATE_AS_MAX) \
((ASN) >= BGP_PRIVATE_AS4_MIN && (ASN) <= BGP_PRIVATE_AS4_MAX)) || ((ASN) >= BGP_PRIVATE_AS4_MIN && (ASN) <= BGP_PRIVATE_AS4_MAX))
/* AS_PATH segment data in abstracted form, no limit is placed on length */ /* AS_PATH segment data in abstracted form, no limit is placed on length */
struct assegment struct assegment {
{ struct assegment *next;
struct assegment *next; as_t *as;
as_t *as; u_short length;
u_short length; u_char type;
u_char type;
}; };
/* AS path may be include some AsSegments. */ /* AS path may be include some AsSegments. */
struct aspath struct aspath {
{ /* Reference count to this aspath. */
/* Reference count to this aspath. */ unsigned long refcnt;
unsigned long refcnt;
/* segment data */ /* segment data */
struct assegment *segments; struct assegment *segments;
/* AS path as a json object */ /* AS path as a json object */
json_object *json; json_object *json;
/* String expression of AS path. This string is used by vty output /* String expression of AS path. This string is used by vty output
and AS path regular expression match. */ and AS path regular expression match. */
char *str; char *str;
unsigned short str_len; unsigned short str_len;
}; };
#define ASPATH_STR_DEFAULT_LEN 32 #define ASPATH_STR_DEFAULT_LEN 32
/* Prototypes. */ /* Prototypes. */
extern void aspath_init (void); extern void aspath_init(void);
extern void aspath_finish (void); extern void aspath_finish(void);
extern struct aspath *aspath_parse (struct stream *, size_t, int); extern struct aspath *aspath_parse(struct stream *, size_t, int);
extern struct aspath *aspath_dup (struct aspath *); extern struct aspath *aspath_dup(struct aspath *);
extern struct aspath *aspath_aggregate (struct aspath *, struct aspath *); extern struct aspath *aspath_aggregate(struct aspath *, struct aspath *);
extern struct aspath *aspath_prepend (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_filter_exclude(struct aspath *, struct aspath *);
extern struct aspath *aspath_add_seq_n (struct aspath *, as_t, unsigned); 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_seq(struct aspath *, as_t);
extern struct aspath *aspath_add_confed_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(const void *, const void *);
extern int aspath_cmp_left (const struct aspath *, const struct aspath *); extern int aspath_cmp_left(const struct aspath *, const struct aspath *);
extern int aspath_cmp_left_confed (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_delete_confed_seq(struct aspath *);
extern struct aspath *aspath_empty (void); extern struct aspath *aspath_empty(void);
extern struct aspath *aspath_empty_get (void); extern struct aspath *aspath_empty_get(void);
extern struct aspath *aspath_str2aspath (const char *); extern struct aspath *aspath_str2aspath(const char *);
extern void aspath_free (struct aspath *); extern void aspath_free(struct aspath *);
extern struct aspath *aspath_intern (struct aspath *); extern struct aspath *aspath_intern(struct aspath *);
extern void aspath_unintern (struct aspath **); extern void aspath_unintern(struct aspath **);
extern const char *aspath_print (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_vty(struct vty *, const char *, struct aspath *,
extern void aspath_print_all_vty (struct vty *); const char *);
extern unsigned int aspath_key_make (void *); extern void aspath_print_all_vty(struct vty *);
extern unsigned int aspath_get_first_as (struct aspath *); extern unsigned int aspath_key_make(void *);
extern unsigned int aspath_get_last_as (struct aspath *); extern unsigned int aspath_get_first_as(struct aspath *);
extern int aspath_loop_check (struct aspath *, as_t); extern unsigned int aspath_get_last_as(struct aspath *);
extern int aspath_private_as_check (struct aspath *); extern int aspath_loop_check(struct aspath *, as_t);
extern int aspath_single_asn_check (struct aspath *, as_t asn); extern int aspath_private_as_check(struct aspath *);
extern struct aspath *aspath_replace_specific_asn (struct aspath *aspath, as_t target_asn, as_t our_asn); extern int aspath_single_asn_check(struct aspath *, as_t asn);
extern struct aspath *aspath_replace_private_asns(struct aspath *aspath, as_t asn); extern struct aspath *aspath_replace_specific_asn(struct aspath *aspath,
extern struct aspath *aspath_remove_private_asns (struct aspath *aspath); as_t target_asn,
extern int aspath_firstas_check (struct aspath *, as_t); as_t our_asn);
extern int aspath_confed_check (struct aspath *); extern struct aspath *aspath_replace_private_asns(struct aspath *aspath,
extern int aspath_left_confed_check (struct aspath *); as_t asn);
extern unsigned long aspath_count (void); extern struct aspath *aspath_remove_private_asns(struct aspath *aspath);
extern unsigned int aspath_count_hops (const struct aspath *); extern int aspath_firstas_check(struct aspath *, as_t);
extern unsigned int aspath_count_confeds (struct aspath *); extern int aspath_confed_check(struct aspath *);
extern unsigned int aspath_size (struct aspath *); extern int aspath_left_confed_check(struct aspath *);
extern as_t aspath_highest (struct aspath *); extern unsigned long aspath_count(void);
extern as_t aspath_leftmost (struct aspath *); extern unsigned int aspath_count_hops(const struct aspath *);
extern size_t aspath_put (struct stream *, struct aspath *, int); 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 struct aspath *aspath_reconcile_as4(struct aspath *, struct aspath *);
extern unsigned int aspath_has_as4 (struct aspath *); extern unsigned int aspath_has_as4(struct aspath *);
/* For SNMP BGP4PATHATTRASPATHSEGMENT, might be useful for debug */ /* 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 */ #endif /* _QUAGGA_BGP_ASPATH_H */

File diff suppressed because it is too large Load Diff

View File

@ -21,20 +21,20 @@
#ifndef _QUAGGA_BGP_ATTR_H #ifndef _QUAGGA_BGP_ATTR_H
#define _QUAGGA_BGP_ATTR_H #define _QUAGGA_BGP_ATTR_H
#include "mpls.h"
#include "bgp_attr_evpn.h" #include "bgp_attr_evpn.h"
/* Simple bit mapping. */ /* Simple bit mapping. */
#define BITMAP_NBBY 8 #define BITMAP_NBBY 8
#define SET_BITMAP(MAP, NUM) \ #define SET_BITMAP(MAP, NUM) \
SET_FLAG (MAP[(NUM) / BITMAP_NBBY], 1 << ((NUM) % BITMAP_NBBY)) SET_FLAG(MAP[(NUM) / BITMAP_NBBY], 1 << ((NUM) % BITMAP_NBBY))
#define CHECK_BITMAP(MAP, NUM) \ #define CHECK_BITMAP(MAP, NUM) \
CHECK_FLAG (MAP[(NUM) / BITMAP_NBBY], 1 << ((NUM) % BITMAP_NBBY)) CHECK_FLAG(MAP[(NUM) / BITMAP_NBBY], 1 << ((NUM) % BITMAP_NBBY))
#define BGP_MED_MAX UINT32_MAX #define BGP_MED_MAX UINT32_MAX
/* BGP Attribute type range. */ /* BGP Attribute type range. */
#define BGP_ATTR_TYPE_RANGE 256 #define BGP_ATTR_TYPE_RANGE 256
#define BGP_ATTR_BITMAP_SIZE (BGP_ATTR_TYPE_RANGE / BITMAP_NBBY) #define BGP_ATTR_BITMAP_SIZE (BGP_ATTR_TYPE_RANGE / BITMAP_NBBY)
@ -67,12 +67,12 @@
#define BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH 6 #define BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH 6
struct bgp_attr_encap_subtlv { struct bgp_attr_encap_subtlv {
struct bgp_attr_encap_subtlv *next; /* for chaining */ struct bgp_attr_encap_subtlv *next; /* for chaining */
/* Reference count of this attribute. */ /* Reference count of this attribute. */
unsigned long refcnt; unsigned long refcnt;
uint16_t type; uint16_t type;
uint16_t length; uint16_t length;
uint8_t value[1]; /* will be extended */ uint8_t value[1]; /* will be extended */
}; };
#if ENABLE_BGP_VNC #if ENABLE_BGP_VNC
@ -80,111 +80,108 @@ struct bgp_attr_encap_subtlv {
* old rfp<->rfapi representation * old rfp<->rfapi representation
*/ */
struct bgp_tea_options { struct bgp_tea_options {
struct bgp_tea_options *next; struct bgp_tea_options *next;
uint8_t options_count; uint8_t options_count;
uint16_t options_length; /* each TLV may be 256 in length */ uint16_t options_length; /* each TLV may be 256 in length */
uint8_t type; uint8_t type;
uint8_t length; uint8_t length;
void *value; /* pointer to data */ void *value; /* pointer to data */
}; };
#endif #endif
/* Overlay Index Info */ /* Overlay Index Info */
struct overlay_index struct overlay_index {
{ struct eth_segment_id eth_s_id;
struct eth_segment_id eth_s_id; union gw_addr gw_ip;
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;
}; };
/* BGP core attribute structure. */ /* BGP core attribute structure. */
struct attr struct attr {
{ /* AS Path structure */
/* AS Path structure */ struct aspath *aspath;
struct aspath *aspath;
/* Community structure */ /* Community structure */
struct community *community; struct community *community;
/* Lazily allocated pointer to extra attributes */ /* Reference count of this attribute. */
struct attr_extra *extra; unsigned long refcnt;
/* Reference count of this attribute. */ /* Flag of attribute is set or not. */
unsigned long refcnt; uint64_t flag;
/* Flag of attribute is set or not. */ /* Apart from in6_addr, the remaining static attributes */
uint64_t flag; struct in_addr nexthop;
u_int32_t med;
u_int32_t local_pref;
ifindex_t nh_ifindex;
/* Apart from in6_addr, the remaining static attributes */ /* Path origin attribute */
struct in_addr nexthop; u_char origin;
u_int32_t med;
u_int32_t local_pref;
ifindex_t nh_ifindex;
/* Path origin attribute */ /* has the route-map changed any attribute?
u_char origin; Used on the peer outbound side. */
u_int32_t rmap_change_flags;
/* has the route-map changed any attribute? /* Multi-Protocol Nexthop, AFI IPv6 */
Used on the peer outbound side. */ struct in6_addr mp_nexthop_global;
u_int32_t rmap_change_flags; 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 */ /* rmap_change_flags definition */
@ -197,99 +194,97 @@ struct attr
#define BATTR_RMAP_IPV6_PREFER_GLOBAL_CHANGED (1 << 6) #define BATTR_RMAP_IPV6_PREFER_GLOBAL_CHANGED (1 << 6)
/* Router Reflector related structure. */ /* Router Reflector related structure. */
struct cluster_list struct cluster_list {
{ unsigned long refcnt;
unsigned long refcnt; int length;
int length; struct in_addr *list;
struct in_addr *list;
}; };
/* Unknown transit attribute. */ /* Unknown transit attribute. */
struct transit struct transit {
{ unsigned long refcnt;
unsigned long refcnt; int length;
int length; u_char *val;
u_char *val;
}; };
#define ATTR_FLAG_BIT(X) (1ULL << ((X) - 1)) #define ATTR_FLAG_BIT(X) (1ULL << ((X) - 1))
#define BGP_CLUSTER_LIST_LENGTH(attr) \ #define BGP_CLUSTER_LIST_LENGTH(attr) \
(((attr)->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST)) ? \ (((attr)->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST)) \
(attr)->extra->cluster->length : 0) ? (attr)->cluster->length \
: 0)
typedef enum { typedef enum {
BGP_ATTR_PARSE_PROCEED = 0, BGP_ATTR_PARSE_PROCEED = 0,
BGP_ATTR_PARSE_ERROR = -1, BGP_ATTR_PARSE_ERROR = -1,
BGP_ATTR_PARSE_WITHDRAW = -2, BGP_ATTR_PARSE_WITHDRAW = -2,
/* only used internally, send notify + convert to BGP_ATTR_PARSE_ERROR */ /* only used internally, send notify + convert to BGP_ATTR_PARSE_ERROR
BGP_ATTR_PARSE_ERROR_NOTIFYPLS = -3, */
BGP_ATTR_PARSE_ERROR_NOTIFYPLS = -3,
} bgp_attr_parse_ret_t; } bgp_attr_parse_ret_t;
struct bpacket_attr_vec_arr; struct bpacket_attr_vec_arr;
/* Prototypes. */ /* Prototypes. */
extern void bgp_attr_init (void); extern void bgp_attr_init(void);
extern void bgp_attr_finish (void); extern void bgp_attr_finish(void);
extern bgp_attr_parse_ret_t bgp_attr_parse (struct peer *, struct attr *, extern bgp_attr_parse_ret_t bgp_attr_parse(struct peer *, struct attr *,
bgp_size_t, struct bgp_nlri *, bgp_size_t, struct bgp_nlri *,
struct bgp_nlri *); struct bgp_nlri *);
extern struct attr_extra *bgp_attr_extra_get (struct attr *); extern void bgp_attr_dup(struct attr *, struct attr *);
extern void bgp_attr_extra_free (struct attr *); extern void bgp_attr_deep_dup(struct attr *, struct attr *);
extern void bgp_attr_dup (struct attr *, struct attr *); extern void bgp_attr_deep_free(struct attr *);
extern void bgp_attr_deep_dup (struct attr *, struct attr *); extern struct attr *bgp_attr_intern(struct attr *attr);
extern void bgp_attr_deep_free (struct attr *); extern struct attr *bgp_attr_refcount(struct attr *attr);
extern struct attr *bgp_attr_intern (struct attr *attr); extern void bgp_attr_unintern_sub(struct attr *);
extern struct attr *bgp_attr_refcount (struct attr *attr); extern void bgp_attr_unintern(struct attr **);
extern void bgp_attr_unintern_sub (struct attr *); extern void bgp_attr_flush(struct attr *);
extern void bgp_attr_unintern (struct attr **); extern struct attr *bgp_attr_default_set(struct attr *attr, u_char);
extern void bgp_attr_flush (struct attr *); extern struct attr *bgp_attr_aggregate_intern(struct bgp *, u_char,
extern struct attr *bgp_attr_default_set (struct attr *attr, u_char); struct aspath *,
extern struct attr *bgp_attr_aggregate_intern (struct bgp *, u_char, struct community *, int as_set,
struct aspath *, u_char);
struct community *, int as_set, u_char); extern bgp_size_t bgp_packet_attribute(struct bgp *bgp, struct peer *,
extern bgp_size_t bgp_packet_attribute (struct bgp *bgp, struct peer *, struct stream *, struct attr *,
struct stream *, struct attr *, struct bpacket_attr_vec_arr *vecarr,
struct bpacket_attr_vec_arr *vecarr, struct prefix *, afi_t, safi_t,
struct prefix *, afi_t, safi_t, struct peer *, struct prefix_rd *,
struct peer *, struct prefix_rd *, mpls_label_t *, int, u_int32_t);
u_char *, int, u_int32_t); extern void bgp_dump_routes_attr(struct stream *, struct attr *,
extern void bgp_dump_routes_attr (struct stream *, struct attr *, struct prefix *);
struct prefix *); extern int attrhash_cmp(const void *, const void *);
extern int attrhash_cmp (const void *, const void *); extern unsigned int attrhash_key_make(void *);
extern unsigned int attrhash_key_make (void *); extern void attr_show_all(struct vty *);
extern void attr_show_all (struct vty *); extern unsigned long int attr_count(void);
extern unsigned long int attr_count (void); extern unsigned long int attr_unknown_count(void);
extern unsigned long int attr_unknown_count (void);
/* Cluster list prototypes. */ /* Cluster list prototypes. */
extern int cluster_loop_check (struct cluster_list *, struct in_addr); extern int cluster_loop_check(struct cluster_list *, struct in_addr);
extern void cluster_unintern (struct cluster_list *); extern void cluster_unintern(struct cluster_list *);
/* Transit attribute prototypes. */ /* Transit attribute prototypes. */
void transit_unintern (struct transit *); void transit_unintern(struct transit *);
/* Below exported for unit-test purposes only */ /* Below exported for unit-test purposes only */
struct bgp_attr_parser_args { struct bgp_attr_parser_args {
struct peer *peer; struct peer *peer;
bgp_size_t length; /* attribute data length; */ bgp_size_t length; /* attribute data length; */
bgp_size_t total; /* total length, inc header */ bgp_size_t total; /* total length, inc header */
struct attr *attr; struct attr *attr;
u_int8_t type; u_int8_t type;
u_int8_t flags; u_int8_t flags;
u_char *startp; u_char *startp;
}; };
extern int bgp_mp_reach_parse (struct bgp_attr_parser_args *args, extern int bgp_mp_reach_parse(struct bgp_attr_parser_args *args,
struct bgp_nlri *); struct bgp_nlri *);
extern int bgp_mp_unreach_parse (struct bgp_attr_parser_args *args, extern int bgp_mp_unreach_parse(struct bgp_attr_parser_args *args,
struct bgp_nlri *); struct bgp_nlri *);
extern struct bgp_attr_encap_subtlv * extern struct bgp_attr_encap_subtlv *
encap_tlv_dup(struct bgp_attr_encap_subtlv *orig); encap_tlv_dup(struct bgp_attr_encap_subtlv *orig);
extern void extern void bgp_attr_flush_encap(struct attr *attr);
bgp_attr_flush_encap(struct attr *attr);
/** /**
* Set of functions to encode MP_REACH_NLRI and MP_UNREACH_NLRI attributes. * 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. * finally the _end() function.
*/ */
extern size_t bgp_packet_mpattr_start(struct stream *s, struct peer *peer, extern size_t bgp_packet_mpattr_start(struct stream *s, struct peer *peer,
afi_t afi, safi_t safi, afi_t afi, safi_t safi,
struct bpacket_attr_vec_arr *vecarr, struct bpacket_attr_vec_arr *vecarr,
struct attr *attr); struct attr *attr);
extern void bgp_packet_mpattr_prefix(struct stream *s, afi_t afi, safi_t safi, extern void bgp_packet_mpattr_prefix(struct stream *s, afi_t afi, safi_t safi,
struct prefix *p, struct prefix_rd *prd, struct prefix *p, struct prefix_rd *prd,
u_char *tag, int addpath_encode, mpls_label_t *label, int addpath_encode,
u_int32_t addpath_tx_id, u_int32_t addpath_tx_id, struct attr *);
struct attr *);
extern size_t bgp_packet_mpattr_prefix_size(afi_t afi, safi_t safi, 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 void bgp_packet_mpattr_end(struct stream *s, size_t sizep);
extern size_t bgp_packet_mpunreach_start (struct stream *s, afi_t afi, extern size_t bgp_packet_mpunreach_start(struct stream *s, afi_t afi,
safi_t safi); safi_t safi);
extern void bgp_packet_mpunreach_prefix (struct stream *s, struct prefix *p, extern void bgp_packet_mpunreach_prefix(struct stream *s, struct prefix *p,
afi_t afi, safi_t safi, struct prefix_rd *prd, afi_t afi, safi_t safi,
u_char *tag, int, u_int32_t, struct attr *); struct prefix_rd *prd, mpls_label_t *,
extern void bgp_packet_mpunreach_end (struct stream *s, size_t attrlen_pnt); int, u_int32_t, struct attr *);
extern void bgp_packet_mpunreach_end(struct stream *s, size_t attrlen_pnt);
static inline int static inline int bgp_rmap_nhop_changed(u_int32_t out_rmap_flags,
bgp_rmap_nhop_changed(u_int32_t out_rmap_flags, u_int32_t in_rmap_flags) u_int32_t in_rmap_flags)
{ {
return ((CHECK_FLAG(out_rmap_flags, BATTR_RMAP_NEXTHOP_PEER_ADDRESS) || 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_NEXTHOP_UNCHANGED)
CHECK_FLAG(out_rmap_flags, BATTR_RMAP_IPV4_NHOP_CHANGED) || || 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,
CHECK_FLAG(out_rmap_flags, BATTR_RMAP_IPV6_PREFER_GLOBAL_CHANGED) || BATTR_RMAP_IPV6_GLOBAL_NHOP_CHANGED)
CHECK_FLAG(out_rmap_flags, BATTR_RMAP_IPV6_LL_NHOP_CHANGED) || || CHECK_FLAG(out_rmap_flags,
CHECK_FLAG(in_rmap_flags, BATTR_RMAP_NEXTHOP_UNCHANGED)) ? 1 : 0); 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 */ #endif /* _QUAGGA_BGP_ATTR_H */

View File

@ -33,21 +33,20 @@
#include "bgpd/bgp_attr_evpn.h" #include "bgpd/bgp_attr_evpn.h"
#include "bgpd/bgp_ecommunity.h" #include "bgpd/bgp_ecommunity.h"
#include "bgpd/bgp_evpn.h" #include "bgpd/bgp_evpn.h"
#include "bgpd/bgp_evpn_private.h"
void bgp_add_routermac_ecom(struct attr *attr, struct ethaddr *routermac) void bgp_add_routermac_ecom(struct attr *attr, struct ethaddr *routermac)
{ {
struct ecommunity_val routermac_ecom; struct ecommunity_val routermac_ecom;
if (attr->extra) { memset(&routermac_ecom, 0, sizeof(struct ecommunity_val));
memset(&routermac_ecom, 0, sizeof(struct ecommunity_val)); routermac_ecom.val[0] = ECOMMUNITY_ENCODE_EVPN;
routermac_ecom.val[0] = ECOMMUNITY_ENCODE_EVPN; routermac_ecom.val[1] = ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC;
routermac_ecom.val[1] = ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC; memcpy(&routermac_ecom.val[2], routermac->octet, ETHER_ADDR_LEN);
memcpy(&routermac_ecom.val[2], routermac->octet, ETHER_ADDR_LEN); if (!attr->ecommunity)
if (!attr->extra->ecommunity) attr->ecommunity = ecommunity_new();
attr->extra->ecommunity = ecommunity_new(); ecommunity_add_val(attr->ecommunity, &routermac_ecom);
ecommunity_add_val(attr->extra->ecommunity, &routermac_ecom); ecommunity_str(attr->ecommunity);
ecommunity_str (attr->extra->ecommunity);
}
} }
/* converts to an esi /* converts to an esi
@ -62,10 +61,9 @@ int str2esi(const char *str, struct eth_segment_id *id)
if (!str) if (!str)
return 0; return 0;
if (sscanf (str, "%2x:%2x:%2x:%2x:%2x:%2x:%2x:%2x:%2x:%2x", if (sscanf(str, "%2x:%2x:%2x:%2x:%2x:%2x:%2x:%2x:%2x:%2x", a + 0, a + 1,
a + 0, a + 1, a + 2, a + 3, a + 4, a + 5, a + 2, a + 3, a + 4, a + 5, a + 6, a + 7, a + 8, a + 9)
a + 6, a + 7, a + 8, a + 9) != ESI_LEN) != ESI_LEN) {
{
/* error in incoming str length */ /* error in incoming str length */
return 0; return 0;
} }
@ -86,12 +84,13 @@ char *esi2str(struct eth_segment_id *id)
return NULL; return NULL;
val = id->val; 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), snprintf(ptr, (ESI_LEN * 2 + ESI_LEN - 1 + 1),
"%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", val[0],
val[0], val[1], val[2], val[3], val[4], val[1], val[2], val[3], val[4], val[5], val[6], val[7], val[8],
val[5], val[6], val[7], val[8], val[9]); val[9]);
return ptr; return ptr;
} }
@ -102,12 +101,63 @@ char *ecom_mac2str(char *ecom_mac)
en = ecom_mac; en = ecom_mac;
en += 2; 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 */ /* dst prefix must be AF_INET or AF_INET6 prefix, to forge EVPN prefix */
extern int extern int bgp_build_evpn_prefix(int evpn_type, uint32_t eth_tag,
bgp_build_evpn_prefix(int evpn_type, uint32_t eth_tag, struct prefix *dst) struct prefix *dst)
{ {
struct evpn_addr *p_evpn_p; struct evpn_addr *p_evpn_p;
struct prefix p2; 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); p_evpn_p = &(dst->u.prefix_evpn);
dst->family = AF_ETHERNET; dst->family = AF_ETHERNET;
p_evpn_p->route_type = evpn_type; 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->eth_tag = eth_tag;
p_evpn_p->ip_prefix_length = p2.prefixlen; p_evpn_p->ip_prefix_length = p2.prefixlen;
if (src->family == AF_INET) { if (src->family == AF_INET) {
p_evpn_p->flags = IP_PREFIX_V4; SET_IPADDR_V4(&p_evpn_p->ip);
memcpy(&p_evpn_p->ip.v4_addr, &src->u.prefix4, memcpy(&p_evpn_p->ip.ipaddr_v4, &src->u.prefix4,
sizeof(struct in_addr)); 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 { } else {
p_evpn_p->flags = IP_PREFIX_V6; SET_IPADDR_V6(&p_evpn_p->ip);
memcpy(&p_evpn_p->ip.v6_addr, &src->u.prefix6, memcpy(&p_evpn_p->ip.ipaddr_v6, &src->u.prefix6,
sizeof(struct in6_addr)); 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 } else
return -1; return -1;

View File

@ -22,16 +22,18 @@
#define _QUAGGA_BGP_ATTR_EVPN_H #define _QUAGGA_BGP_ATTR_EVPN_H
/* value of first byte of ESI */ /* value of first byte of ESI */
#define ESI_TYPE_ARBITRARY 0 /* */ #define ESI_TYPE_ARBITRARY 0 /* */
#define ESI_TYPE_LACP 1 /* <> */ #define ESI_TYPE_LACP 1 /* <> */
#define ESI_TYPE_BRIDGE 2 /* <Root bridge Mac-6B>:<Root Br Priority-2B>:00 */ #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_MAC 3 /* <Syst Mac Add-6B>:<Local Discriminator Value-3B> */
#define ESI_TYPE_ROUTER 4 /* <RouterId-4B>:<Local Discriminator Value-4B> */ #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_AS 5 /* <AS-4B>:<Local Discriminator Value-4B> */
#define MAX_ESI {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff} #define MAX_ESI {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff}
#define ESI_LEN 10 #define ESI_LEN 10
#define MAX_ET 0xffffffff #define MAX_ET 0xffffffff
u_long eth_tag_id; u_long eth_tag_id;
struct attr; 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 *esi2str(struct eth_segment_id *id);
extern char *ecom_mac2str(char *ecom_mac); 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, extern int bgp_build_evpn_prefix(int type, uint32_t eth_tag,
struct prefix *dst); 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 #ifndef _QUAGGA_BGP_BFD_H
#define _QUAGGA_BGP_BFD_H #define _QUAGGA_BGP_BFD_H
extern void extern void bgp_bfd_init(void);
bgp_bfd_init(void);
extern void extern void bgp_bfd_peer_group2peer_copy(struct peer *conf, struct peer *peer);
bgp_bfd_peer_group2peer_copy(struct peer *conf, struct peer *peer);
extern void extern void bgp_bfd_register_peer(struct peer *peer);
bgp_bfd_register_peer (struct peer *peer);
extern void extern void bgp_bfd_deregister_peer(struct peer *peer);
bgp_bfd_deregister_peer (struct peer *peer);
extern void extern void bgp_bfd_peer_config_write(struct vty *vty, struct peer *peer,
bgp_bfd_peer_config_write(struct vty *vty, struct peer *peer, char *addr); char *addr);
extern void extern void bgp_bfd_show_info(struct vty *vty, struct peer *peer,
bgp_bfd_show_info(struct vty *vty, struct peer *peer, u_char use_json, json_object *json_neigh); u_char use_json, json_object *json_neigh);
extern int extern int bgp_bfd_is_peer_multihop(struct peer *peer);
bgp_bfd_is_peer_multihop(struct peer *peer);
#endif /* _QUAGGA_BGP_BFD_H */ #endif /* _QUAGGA_BGP_BFD_H */

View File

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

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. */ #define LARGE_COMMUNITY_LIST_EXPANDED 5 /* Expanded Large community-list. */
/* Community-list. */ /* Community-list. */
struct community_list struct community_list {
{ /* Name of the community-list. */
/* Name of the community-list. */ char *name;
char *name;
/* String or number. */ /* String or number. */
int sort; int sort;
/* Link to upper list. */ /* Link to upper list. */
struct community_list_list *parent; struct community_list_list *parent;
/* Linked list for other community-list. */ /* Linked list for other community-list. */
struct community_list *next; struct community_list *next;
struct community_list *prev; struct community_list *prev;
/* Community-list entry in this community-list. */ /* Community-list entry in this community-list. */
struct community_entry *head; struct community_entry *head;
struct community_entry *tail; struct community_entry *tail;
}; };
/* Each entry in community-list. */ /* Each entry in community-list. */
struct community_entry struct community_entry {
{ struct community_entry *next;
struct community_entry *next; struct community_entry *prev;
struct community_entry *prev;
/* Permit or deny. */ /* Permit or deny. */
u_char direct; u_char direct;
/* Standard or expanded. */ /* Standard or expanded. */
u_char style; u_char style;
/* Any match. */ /* Any match. */
u_char any; u_char any;
/* Community structure. */ /* Community structure. */
union union {
{ struct community *com;
struct community *com; struct ecommunity *ecom;
struct ecommunity *ecom; struct lcommunity *lcom;
struct lcommunity *lcom; } u;
} u;
/* Configuration string. */ /* Configuration string. */
char *config; char *config;
/* Expanded community-list regular expression. */ /* Expanded community-list regular expression. */
regex_t *reg; regex_t *reg;
}; };
/* Linked list of community-list. */ /* Linked list of community-list. */
struct community_list_list struct community_list_list {
{ struct community_list *head;
struct community_list *head; struct community_list *tail;
struct community_list *tail;
}; };
/* Master structure of community-list and extcommunity-list. */ /* Master structure of community-list and extcommunity-list. */
struct community_list_master struct community_list_master {
{ struct community_list_list num;
struct community_list_list num; struct community_list_list str;
struct community_list_list str;
}; };
/* Community-list handler. community_list_init() returns this /* Community-list handler. community_list_init() returns this
structure as handler. */ structure as handler. */
struct community_list_handler struct community_list_handler {
{ /* Community-list. */
/* Community-list. */ struct community_list_master community_list;
struct community_list_master community_list;
/* Exteded community-list. */ /* Exteded community-list. */
struct community_list_master extcommunity_list; struct community_list_master extcommunity_list;
/* Large community-list. */ /* Large community-list. */
struct community_list_master lcommunity_list; struct community_list_master lcommunity_list;
}; };
/* Error code of community-list. */ /* Error code of community-list. */
@ -131,42 +125,42 @@ struct community_list_handler
extern struct community_list_handler *bgp_clist; extern struct community_list_handler *bgp_clist;
/* Prototypes. */ /* Prototypes. */
extern struct community_list_handler *community_list_init (void); extern struct community_list_handler *community_list_init(void);
extern void community_list_terminate (struct community_list_handler *); 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, const char *name, const char *str, int direct,
int style); int style);
extern int community_list_unset (struct community_list_handler *ch, extern int lcommunity_list_unset(struct community_list_handler *ch,
const char *name, const char *str, const char *name, const char *str, int direct,
int direct, int style, int delete_all); int style);
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 struct community_list_master * 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 * 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 community_list_match(struct community *, struct community_list *);
extern int ecommunity_list_match (struct ecommunity *, 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 lcommunity_list_match(struct lcommunity *, struct community_list *);
extern int community_list_exact_match (struct community *, extern int community_list_exact_match(struct community *,
struct community_list *); struct community_list *);
extern struct community * extern struct community *community_list_match_delete(struct community *,
community_list_match_delete (struct community *, struct community_list *); struct community_list *);
extern struct lcommunity * extern struct lcommunity *
lcommunity_list_match_delete (struct lcommunity *lcom, lcommunity_list_match_delete(struct lcommunity *lcom,
struct community_list *list); struct community_list *list);
#endif /* _QUAGGA_BGP_CLIST_H */ #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" #include "lib/json.h"
/* Communities attribute. */ /* Communities attribute. */
struct community struct community {
{ /* Reference count of communities value. */
/* Reference count of communities value. */ unsigned long refcnt;
unsigned long refcnt;
/* Communities value size. */ /* Communities value size. */
int size; int size;
/* Communities value. */ /* Communities value. */
u_int32_t *val; u_int32_t *val;
/* Communities as a json object */ /* Communities as a json object */
json_object *json; json_object *json;
/* String of community attribute. This sring is used by vty output /* String of community attribute. This sring is used by vty output
and expanded community-list for regular expression match. */ and expanded community-list for regular expression match. */
char *str; char *str;
}; };
/* Well-known communities value. */ /* Well-known communities value. */
@ -56,25 +55,27 @@ struct community
#define com_nthval(X,n) ((X)->val + (n)) #define com_nthval(X,n) ((X)->val + (n))
/* Prototypes of communities attribute functions. */ /* Prototypes of communities attribute functions. */
extern void community_init (void); extern void community_init(void);
extern void community_finish (void); extern void community_finish(void);
extern void community_free (struct community *); extern void community_free(struct community *);
extern struct community *community_uniq_sort (struct community *); extern struct community *community_uniq_sort(struct community *);
extern struct community *community_parse (u_int32_t *, u_short); extern struct community *community_parse(u_int32_t *, u_short);
extern struct community *community_intern (struct community *); extern struct community *community_intern(struct community *);
extern void community_unintern (struct community **); extern void community_unintern(struct community **);
extern char *community_str (struct community *); extern char *community_str(struct community *);
extern unsigned int community_hash_make (struct community *); extern unsigned int community_hash_make(struct community *);
extern struct community *community_str2com (const char *); extern struct community *community_str2com(const char *);
extern int community_match (const struct community *, const struct community *); extern int community_match(const struct community *, const struct community *);
extern int community_cmp (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_merge(struct community *,
extern struct community *community_delete (struct community *, struct community *); struct community *);
extern struct community *community_dup (struct community *); extern struct community *community_delete(struct community *,
extern int community_include (struct community *, u_int32_t); struct community *);
extern void community_del_val (struct community *, u_int32_t *); extern struct community *community_dup(struct community *);
extern unsigned long community_count (void); extern int community_include(struct community *, u_int32_t);
extern struct hash *community_hash (void); extern void community_del_val(struct community *, u_int32_t *);
extern u_int32_t community_val_get (struct community *com, int i); 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 */ #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 #define _QUAGGA_BGP_DAMP_H
/* Structure maintained on a per-route basis. */ /* Structure maintained on a per-route basis. */
struct bgp_damp_info struct bgp_damp_info {
{ /* Doubly linked list. This information must be linked to
/* Doubly linked list. This information must be linked to reuse_list or no_reuse_list. */
reuse_list or no_reuse_list. */ struct bgp_damp_info *next;
struct bgp_damp_info *next; struct bgp_damp_info *prev;
struct bgp_damp_info *prev;
/* Figure-of-merit. */ /* Figure-of-merit. */
unsigned int penalty; unsigned int penalty;
/* Number of flapping. */ /* Number of flapping. */
unsigned int flap; unsigned int flap;
/* First flap time */ /* First flap time */
time_t start_time; time_t start_time;
/* Last time penalty was updated. */ /* Last time penalty was updated. */
time_t t_updated; time_t t_updated;
/* Time of route start to be suppressed. */ /* Time of route start to be suppressed. */
time_t suppress_time; time_t suppress_time;
/* Back reference to bgp_info. */ /* Back reference to bgp_info. */
struct bgp_info *binfo; struct bgp_info *binfo;
/* Back reference to bgp_node. */ /* Back reference to bgp_node. */
struct bgp_node *rn; struct bgp_node *rn;
/* Current index in the reuse_list. */ /* Current index in the reuse_list. */
int index; int index;
/* Last time message type. */ /* Last time message type. */
u_char lastrecord; u_char lastrecord;
#define BGP_RECORD_UPDATE 1U #define BGP_RECORD_UPDATE 1U
#define BGP_RECORD_WITHDRAW 2U #define BGP_RECORD_WITHDRAW 2U
afi_t afi; afi_t afi;
safi_t safi; safi_t safi;
}; };
/* Specified parameter set configuration. */ /* Specified parameter set configuration. */
struct bgp_damp_config struct bgp_damp_config {
{ /* Value over which routes suppressed. */
/* Value over which routes suppressed. */ unsigned int suppress_value;
unsigned int suppress_value;
/* Value below which suppressed routes reused. */ /* Value below which suppressed routes reused. */
unsigned int reuse_limit; unsigned int reuse_limit;
/* Max time a route can be suppressed. */ /* Max time a route can be suppressed. */
time_t max_suppress_time; time_t max_suppress_time;
/* Time during which accumulated penalty reduces by half. */ /* Time during which accumulated penalty reduces by half. */
time_t half_life; time_t half_life;
/* Non-configurable parameters but fixed at implementation time. /* Non-configurable parameters but fixed at implementation time.
* To change this values, init_bgp_damp() should be modified. * To change this values, init_bgp_damp() should be modified.
*/ */
time_t tmax; /* Max time previous instability retained */ time_t tmax; /* Max time previous instability retained */
unsigned int reuse_list_size; /* Number of reuse lists */ unsigned int reuse_list_size; /* Number of reuse lists */
unsigned int reuse_index_size; /* Size of reuse index array */ unsigned int reuse_index_size; /* Size of reuse index array */
/* Non-configurable parameters. Most of these are calculated from /* Non-configurable parameters. Most of these are calculated from
* the configurable parameters above. * the configurable parameters above.
*/ */
unsigned int ceiling; /* Max value a penalty can attain */ unsigned int ceiling; /* Max value a penalty can attain */
unsigned int decay_rate_per_tick; /* Calculated from half-life */ unsigned int decay_rate_per_tick; /* Calculated from half-life */
unsigned int decay_array_size; /* Calculated using config parameters */ unsigned int decay_array_size; /* Calculated using config parameters */
double scale_factor; double scale_factor;
unsigned int reuse_scale_factor; unsigned int reuse_scale_factor;
/* Decay array per-set based. */ /* Decay array per-set based. */
double *decay_array; double *decay_array;
/* Reuse index array per-set based. */ /* Reuse index array per-set based. */
int *reuse_index; int *reuse_index;
/* Reuse list array per-set based. */ /* Reuse list array per-set based. */
struct bgp_damp_info **reuse_list; struct bgp_damp_info **reuse_list;
int reuse_offset; int reuse_offset;
/* All dampening information which is not on reuse list. */ /* All dampening information which is not on reuse list. */
struct bgp_damp_info *no_reuse_list; struct bgp_damp_info *no_reuse_list;
/* Reuse timer thread per-set base. */ /* Reuse timer thread per-set base. */
struct thread* t_reuse; struct thread *t_reuse;
}; };
#define BGP_DAMP_NONE 0 #define BGP_DAMP_NONE 0
@ -129,20 +127,22 @@ struct bgp_damp_config
#define REUSE_LIST_SIZE 256 #define REUSE_LIST_SIZE 256
#define REUSE_ARRAY_SIZE 1024 #define REUSE_ARRAY_SIZE 1024
extern int bgp_damp_enable (struct bgp *, afi_t, safi_t, time_t, unsigned int, extern int bgp_damp_enable(struct bgp *, afi_t, safi_t, time_t, unsigned int,
unsigned int, time_t); unsigned int, time_t);
extern int bgp_damp_disable (struct bgp *, afi_t, safi_t); extern int bgp_damp_disable(struct bgp *, afi_t, safi_t);
extern int bgp_damp_withdraw (struct bgp_info *, struct bgp_node *, extern int bgp_damp_withdraw(struct bgp_info *, struct bgp_node *, afi_t,
afi_t, safi_t, int); safi_t, int);
extern int bgp_damp_update (struct bgp_info *, struct bgp_node *, afi_t, safi_t); 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 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_free(struct bgp_damp_info *, int);
extern void bgp_damp_info_clean (void); extern void bgp_damp_info_clean(void);
extern int bgp_damp_decay (time_t, int); extern int bgp_damp_decay(time_t, int);
extern void bgp_config_write_damp (struct vty *); extern void bgp_config_write_damp(struct vty *);
extern void bgp_damp_info_vty (struct vty *, struct bgp_info *, json_object *json_path); extern void bgp_damp_info_vty(struct vty *, struct bgp_info *,
extern const char * bgp_damp_reuse_time_vty (struct vty *, struct bgp_info *, json_object *json_path);
char *, size_t, u_char, json_object *); extern const char *bgp_damp_reuse_time_vty(struct vty *, struct bgp_info *,
extern int bgp_show_dampening_parameters (struct vty *vty, afi_t, safi_t); 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 */ #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 #define DETAIL 6
/* Prototypes. */ /* Prototypes. */
extern void bgp_debug_init (void); extern void bgp_debug_init(void);
extern void bgp_packet_dump (struct stream *); 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_as4;
extern unsigned long conf_bgp_debug_neighbor_events; 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_bestpath_prefixes;
extern struct list *bgp_debug_zebra_prefixes; extern struct list *bgp_debug_zebra_prefixes;
struct bgp_debug_filter struct bgp_debug_filter {
{ char *host;
char *host; struct prefix *p;
struct prefix *p;
}; };
#define BGP_DEBUG_AS4 0x01 #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_ON(a, b) (term_bgp_debug_ ## a |= (BGP_DEBUG_ ## b))
#define TERM_DEBUG_OFF(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) \ #define DEBUG_ON(a, b) \
do { \ do { \
CONF_DEBUG_ON(a, b); \ CONF_DEBUG_ON(a, b); \
TERM_DEBUG_ON(a, b); \ TERM_DEBUG_ON(a, b); \
} while (0) } while (0)
#define DEBUG_OFF(a, b) \ #define DEBUG_OFF(a, b) \
do { \ do { \
CONF_DEBUG_OFF(a, b); \ CONF_DEBUG_OFF(a, b); \
TERM_DEBUG_OFF(a, b); \ TERM_DEBUG_OFF(a, b); \
} while (0) } while (0)
#define BGP_DEBUG(a, b) (term_bgp_debug_ ## a & BGP_DEBUG_ ## b) #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) #define CONF_BGP_DEBUG(a, b) (conf_bgp_debug_ ## a & BGP_DEBUG_ ## b)
extern const char *bgp_type_str[]; 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 int bgp_debug_peer_updout_enabled(char *host);
extern const char *bgp_notify_code_str(char); extern const char *bgp_notify_code_str(char);
extern const char *bgp_notify_subcode_str(char, 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 const struct message bgp_status_msg[];
extern int bgp_debug_neighbor_events(struct peer *peer); extern int bgp_debug_neighbor_events(struct peer *peer);
extern int bgp_debug_keepalive(struct peer *peer); extern int bgp_debug_keepalive(struct peer *peer);
extern int bgp_debug_update(struct peer *peer, struct prefix *p, 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_bestpath(struct prefix *p);
extern int bgp_debug_zebra(struct prefix *p); extern int bgp_debug_zebra(struct prefix *p);
extern int bgp_debug_count(void); extern int bgp_debug_count(void);
extern const char *bgp_debug_rdpfxpath2str (struct prefix_rd *, union prefixconstptr, extern const char *bgp_debug_rdpfxpath2str(afi_t, safi_t, struct prefix_rd *,
int, u_int32_t, char *, int); union prefixconstptr, mpls_label_t *,
const char *bgp_notify_admin_message(char *buf, size_t bufsz, u_char *data, size_t datalen); 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 */ #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_AS2 0
#define TABLE_DUMP_V2_PEER_INDEX_TABLE_AS4 2 #define TABLE_DUMP_V2_PEER_INDEX_TABLE_AS4 2
extern void bgp_dump_init (void); extern void bgp_dump_init(void);
extern void bgp_dump_finish (void); extern void bgp_dump_finish(void);
extern void bgp_dump_state (struct peer *, int, int); extern void bgp_dump_state(struct peer *, int, int);
extern void bgp_dump_packet (struct peer *, int, struct stream *); extern void bgp_dump_packet(struct peer *, int, struct stream *);
#endif /* _QUAGGA_BGP_DUMP_H */ #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_ROUTE_TARGET 0x02
#define ECOMMUNITY_SITE_ORIGIN 0x03 #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_MACMOBILITY 0x00
#define ECOMMUNITY_EVPN_SUBTYPE_ESI_LABEL 0x01 #define ECOMMUNITY_EVPN_SUBTYPE_ESI_LABEL 0x01
#define ECOMMUNITY_EVPN_SUBTYPE_ES_IMPORT_RT 0x02 #define ECOMMUNITY_EVPN_SUBTYPE_ES_IMPORT_RT 0x02
#define ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC 0x03 #define ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC 0x03
#define ECOMMUNITY_EVPN_SUBTYPE_DEF_GW 0x0d #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 */ /* Low-order octet of the Extended Communities type field for OPAQUE types */
#define ECOMMUNITY_OPAQUE_SUBTYPE_ENCAP 0x0c #define ECOMMUNITY_OPAQUE_SUBTYPE_ENCAP 0x0c
@ -53,50 +56,98 @@
#define ECOMMUNITY_FLAG_NON_TRANSITIVE 0x40 #define ECOMMUNITY_FLAG_NON_TRANSITIVE 0x40
/* Extended Communities attribute. */ /* Extended Communities attribute. */
struct ecommunity struct ecommunity {
{ /* Reference counter. */
/* Reference counter. */ unsigned long refcnt;
unsigned long refcnt;
/* Size of Extended Communities attribute. */ /* Size of Extended Communities attribute. */
int size; int size;
/* Extended Communities value. */ /* Extended Communities value. */
u_int8_t *val; u_int8_t *val;
/* Human readable format string. */ /* Human readable format string. */
char *str; char *str;
}; };
/* Extended community value is eight octet. */ /* Extended community value is eight octet. */
struct ecommunity_val struct ecommunity_val {
{ char val[ECOMMUNITY_SIZE];
char val[ECOMMUNITY_SIZE];
}; };
#define ecom_length(X) ((X)->size * ECOMMUNITY_SIZE) #define ecom_length(X) ((X)->size * ECOMMUNITY_SIZE)
extern void ecommunity_init (void); /*
extern void ecommunity_finish (void); * Encode BGP Route Target AS:nn.
extern void ecommunity_free (struct ecommunity **); */
extern struct ecommunity *ecommunity_parse (u_int8_t *, u_short); static inline void encode_route_target_as(as_t as, u_int32_t val,
extern struct ecommunity *ecommunity_dup (struct ecommunity *); struct ecommunity_val *eval)
extern struct ecommunity *ecommunity_merge (struct ecommunity *, struct ecommunity *); {
extern struct ecommunity *ecommunity_uniq_sort (struct ecommunity *); eval->val[0] = ECOMMUNITY_ENCODE_AS;
extern struct ecommunity *ecommunity_intern (struct ecommunity *); eval->val[1] = ECOMMUNITY_ROUTE_TARGET;
extern int ecommunity_cmp (const void *, const void *); eval->val[2] = (as >> 8) & 0xff;
extern void ecommunity_unintern (struct ecommunity **); eval->val[3] = as & 0xff;
extern unsigned int ecommunity_hash_make (void *); eval->val[4] = (val >> 24) & 0xff;
extern struct ecommunity *ecommunity_str2com (const char *, int, int); eval->val[5] = (val >> 16) & 0xff;
extern char *ecommunity_ecom2str (struct ecommunity *, int, int); eval->val[6] = (val >> 8) & 0xff;
extern int ecommunity_match (const struct ecommunity *, const struct ecommunity *); eval->val[7] = val & 0xff;
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 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 */ /* for vpn */
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_add_val(struct ecommunity *, struct ecommunity_val *);
extern int ecommunity_strip (struct ecommunity *ecom, uint8_t type, uint8_t subtype); extern int ecommunity_strip(struct ecommunity *ecom, uint8_t type,
extern struct ecommunity *ecommunity_new (void); uint8_t subtype);
extern struct ecommunity *ecommunity_new(void);
#endif /* _QUAGGA_BGP_ECOMMUNITY_H */ #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 #ifndef _QUAGGA_BGP_ENCAP_TLV_H
#define _QUAGGA_BGP_ENCAP_TLV_H #define _QUAGGA_BGP_ENCAP_TLV_H
/*********************************************************************** /***********************************************************************
* TUNNEL TYPE-SPECIFIC TLV ENCODE * TUNNEL TYPE-SPECIFIC TLV ENCODE
***********************************************************************/ ***********************************************************************/
extern void extern void
bgp_encap_type_l2tpv3overip_to_tlv( bgp_encap_type_l2tpv3overip_to_tlv(struct bgp_encap_type_l2tpv3_over_ip *bet,
struct bgp_encap_type_l2tpv3_over_ip *bet, struct attr *attr);
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 extern void
bgp_encap_type_gre_to_tlv( bgp_encap_type_mpls_in_gre_to_tlv(struct bgp_encap_type_mpls_in_gre *bet,
struct bgp_encap_type_gre *bet, struct attr *attr);
struct attr *attr);
extern void extern void
bgp_encap_type_ip_in_ip_to_tlv( bgp_encap_type_vxlan_gpe_to_tlv(struct bgp_encap_type_vxlan_gpe *bet,
struct bgp_encap_type_ip_in_ip *bet, struct attr *attr);
struct attr *attr);
extern void extern void
bgp_encap_type_transmit_tunnel_endpoint( bgp_encap_type_mpls_in_udp_to_tlv(struct bgp_encap_type_mpls_in_udp *bet,
struct bgp_encap_type_transmit_tunnel_endpoint *bet, struct attr *attr);
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);
/*********************************************************************** /***********************************************************************
* TUNNEL TYPE-SPECIFIC TLV DECODE * TUNNEL TYPE-SPECIFIC TLV DECODE
***********************************************************************/ ***********************************************************************/
extern int extern int tlv_to_bgp_encap_type_l2tpv3overip(
tlv_to_bgp_encap_type_l2tpv3overip( struct bgp_attr_encap_subtlv *stlv, /* subtlv chain */
struct bgp_attr_encap_subtlv *stlv, /* subtlv chain */ struct bgp_encap_type_l2tpv3_over_ip *bet); /* caller-allocated */
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 extern int
tlv_to_bgp_encap_type_gre( tlv_to_bgp_encap_type_mpls_in_gre(struct bgp_attr_encap_subtlv *stlv,
struct bgp_attr_encap_subtlv *stlv, /* subtlv chain */ struct bgp_encap_type_mpls_in_gre *bet);
struct bgp_encap_type_gre *bet); /* caller-allocated */
extern int extern int
tlv_to_bgp_encap_type_ip_in_ip( tlv_to_bgp_encap_type_vxlan_gpe(struct bgp_attr_encap_subtlv *stlv,
struct bgp_attr_encap_subtlv *stlv, /* subtlv chain */ struct bgp_encap_type_vxlan_gpe *bet);
struct bgp_encap_type_ip_in_ip *bet); /* caller-allocated */
extern int extern int
tlv_to_bgp_encap_type_transmit_tunnel_endpoint( tlv_to_bgp_encap_type_mpls_in_udp(struct bgp_attr_encap_subtlv *stlv,
struct bgp_attr_encap_subtlv *stlv, struct bgp_encap_type_mpls_in_udp *bet);
struct bgp_encap_type_transmit_tunnel_endpoint *bet);
extern int extern int tlv_to_bgp_encap_type_pbb(
tlv_to_bgp_encap_type_ipsec_in_tunnel_mode( struct bgp_attr_encap_subtlv *stlv, /* subtlv chain */
struct bgp_attr_encap_subtlv *stlv, /* subtlv chain */ struct bgp_encap_type_pbb *bet); /* caller-allocated */
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 */
#endif /* _QUAGGA_BGP_ENCAP_TLV_H */ #endif /* _QUAGGA_BGP_ENCAP_TLV_H */

View File

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

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 #ifndef _FRR_BGP_EVPN_VTY_H
#define _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); extern void bgp_ethernetvpn_init(void);
#define L2VPN_HELP_STR "Layer 2 Virtual Private Network\n" #define L2VPN_HELP_STR "Layer 2 Virtual Private Network\n"
#define EVPN_HELP_STR "Ethernet 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 #ifndef _QUAGGA_BGP_FILTER_H
#define _QUAGGA_BGP_FILTER_H #define _QUAGGA_BGP_FILTER_H
enum as_filter_type enum as_filter_type { AS_FILTER_DENY, AS_FILTER_PERMIT };
{
AS_FILTER_DENY,
AS_FILTER_PERMIT
};
extern void bgp_filter_init (void); extern void bgp_filter_init(void);
extern void bgp_filter_reset (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 struct as_list *as_list_lookup(const char *);
extern void as_list_add_hook (void (*func) (char *)); extern void as_list_add_hook(void (*func)(char *));
extern void as_list_delete_hook (void (*func) (const char *)); extern void as_list_delete_hook(void (*func)(const char *));
#endif /* _QUAGGA_BGP_FILTER_H */ #endif /* _QUAGGA_BGP_FILTER_H */

File diff suppressed because it is too large Load Diff

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -29,88 +29,91 @@
* files they're used in */ * files they're used in */
DEFINE_MGROUP(BGPD, "bgpd") DEFINE_MGROUP(BGPD, "bgpd")
DEFINE_MTYPE(BGPD, BGP, "BGP instance") DEFINE_MTYPE(BGPD, BGP, "BGP instance")
DEFINE_MTYPE(BGPD, BGP_LISTENER, "BGP listen socket details") DEFINE_MTYPE(BGPD, BGP_LISTENER, "BGP listen socket details")
DEFINE_MTYPE(BGPD, BGP_PEER, "BGP peer") DEFINE_MTYPE(BGPD, BGP_PEER, "BGP peer")
DEFINE_MTYPE(BGPD, BGP_PEER_HOST, "BGP peer hostname") DEFINE_MTYPE(BGPD, BGP_PEER_HOST, "BGP peer hostname")
DEFINE_MTYPE(BGPD, BGP_PEER_IFNAME, "BGP peer ifname") DEFINE_MTYPE(BGPD, BGP_PEER_IFNAME, "BGP peer ifname")
DEFINE_MTYPE(BGPD, PEER_GROUP, "Peer group") DEFINE_MTYPE(BGPD, PEER_GROUP, "Peer group")
DEFINE_MTYPE(BGPD, PEER_GROUP_HOST, "BGP Peer group hostname") DEFINE_MTYPE(BGPD, PEER_GROUP_HOST, "BGP Peer group hostname")
DEFINE_MTYPE(BGPD, PEER_DESC, "Peer description") DEFINE_MTYPE(BGPD, PEER_DESC, "Peer description")
DEFINE_MTYPE(BGPD, PEER_PASSWORD, "Peer password string") DEFINE_MTYPE(BGPD, PEER_PASSWORD, "Peer password string")
DEFINE_MTYPE(BGPD, BGP_PEER_AF, "BGP peer af") DEFINE_MTYPE(BGPD, BGP_PEER_AF, "BGP peer af")
DEFINE_MTYPE(BGPD, BGP_UPDGRP, "BGP update group") DEFINE_MTYPE(BGPD, BGP_UPDGRP, "BGP update group")
DEFINE_MTYPE(BGPD, BGP_UPD_SUBGRP, "BGP update subgroup") DEFINE_MTYPE(BGPD, BGP_UPD_SUBGRP, "BGP update subgroup")
DEFINE_MTYPE(BGPD, BGP_PACKET, "BGP packet") DEFINE_MTYPE(BGPD, BGP_PACKET, "BGP packet")
DEFINE_MTYPE(BGPD, ATTR, "BGP attribute") 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_PATH, "BGP aspath") DEFINE_MTYPE(BGPD, AS_SEG, "BGP aspath seg")
DEFINE_MTYPE(BGPD, AS_SEG, "BGP aspath seg") DEFINE_MTYPE(BGPD, AS_SEG_DATA, "BGP aspath segment data")
DEFINE_MTYPE(BGPD, AS_SEG_DATA, "BGP aspath segment data") DEFINE_MTYPE(BGPD, AS_STR, "BGP aspath str")
DEFINE_MTYPE(BGPD, AS_STR, "BGP aspath str")
DEFINE_MTYPE(BGPD, BGP_TABLE, "BGP table") DEFINE_MTYPE(BGPD, BGP_TABLE, "BGP table")
DEFINE_MTYPE(BGPD, BGP_NODE, "BGP node") DEFINE_MTYPE(BGPD, BGP_NODE, "BGP node")
DEFINE_MTYPE(BGPD, BGP_ROUTE, "BGP route") DEFINE_MTYPE(BGPD, BGP_ROUTE, "BGP route")
DEFINE_MTYPE(BGPD, BGP_ROUTE_EXTRA, "BGP ancillary route info") DEFINE_MTYPE(BGPD, BGP_ROUTE_EXTRA, "BGP ancillary route info")
DEFINE_MTYPE(BGPD, BGP_CONN, "BGP connected") DEFINE_MTYPE(BGPD, BGP_CONN, "BGP connected")
DEFINE_MTYPE(BGPD, BGP_STATIC, "BGP static") DEFINE_MTYPE(BGPD, BGP_STATIC, "BGP static")
DEFINE_MTYPE(BGPD, BGP_ADVERTISE_ATTR, "BGP adv attr") DEFINE_MTYPE(BGPD, BGP_ADVERTISE_ATTR, "BGP adv attr")
DEFINE_MTYPE(BGPD, BGP_ADVERTISE, "BGP adv") DEFINE_MTYPE(BGPD, BGP_ADVERTISE, "BGP adv")
DEFINE_MTYPE(BGPD, BGP_SYNCHRONISE, "BGP synchronise") DEFINE_MTYPE(BGPD, BGP_SYNCHRONISE, "BGP synchronise")
DEFINE_MTYPE(BGPD, BGP_ADJ_IN, "BGP adj in") DEFINE_MTYPE(BGPD, BGP_ADJ_IN, "BGP adj in")
DEFINE_MTYPE(BGPD, BGP_ADJ_OUT, "BGP adj out") DEFINE_MTYPE(BGPD, BGP_ADJ_OUT, "BGP adj out")
DEFINE_MTYPE(BGPD, BGP_MPATH_INFO, "BGP multipath info") DEFINE_MTYPE(BGPD, BGP_MPATH_INFO, "BGP multipath info")
DEFINE_MTYPE(BGPD, AS_LIST, "BGP AS list") DEFINE_MTYPE(BGPD, AS_LIST, "BGP AS list")
DEFINE_MTYPE(BGPD, AS_FILTER, "BGP AS filter") DEFINE_MTYPE(BGPD, AS_FILTER, "BGP AS filter")
DEFINE_MTYPE(BGPD, AS_FILTER_STR, "BGP AS filter str") DEFINE_MTYPE(BGPD, AS_FILTER_STR, "BGP AS filter str")
DEFINE_MTYPE(BGPD, COMMUNITY, "community") DEFINE_MTYPE(BGPD, COMMUNITY, "community")
DEFINE_MTYPE(BGPD, COMMUNITY_VAL, "community val") DEFINE_MTYPE(BGPD, COMMUNITY_VAL, "community val")
DEFINE_MTYPE(BGPD, COMMUNITY_STR, "community str") DEFINE_MTYPE(BGPD, COMMUNITY_STR, "community str")
DEFINE_MTYPE(BGPD, ECOMMUNITY, "extcommunity") DEFINE_MTYPE(BGPD, ECOMMUNITY, "extcommunity")
DEFINE_MTYPE(BGPD, ECOMMUNITY_VAL, "extcommunity val") DEFINE_MTYPE(BGPD, ECOMMUNITY_VAL, "extcommunity val")
DEFINE_MTYPE(BGPD, ECOMMUNITY_STR, "extcommunity str") DEFINE_MTYPE(BGPD, ECOMMUNITY_STR, "extcommunity str")
DEFINE_MTYPE(BGPD, COMMUNITY_LIST, "community-list") DEFINE_MTYPE(BGPD, COMMUNITY_LIST, "community-list")
DEFINE_MTYPE(BGPD, COMMUNITY_LIST_NAME, "community-list name") DEFINE_MTYPE(BGPD, COMMUNITY_LIST_NAME, "community-list name")
DEFINE_MTYPE(BGPD, COMMUNITY_LIST_ENTRY, "community-list entry") DEFINE_MTYPE(BGPD, COMMUNITY_LIST_ENTRY, "community-list entry")
DEFINE_MTYPE(BGPD, COMMUNITY_LIST_CONFIG, "community-list config") DEFINE_MTYPE(BGPD, COMMUNITY_LIST_CONFIG, "community-list config")
DEFINE_MTYPE(BGPD, COMMUNITY_LIST_HANDLER, "community-list handler") DEFINE_MTYPE(BGPD, COMMUNITY_LIST_HANDLER, "community-list handler")
DEFINE_MTYPE(BGPD, CLUSTER, "Cluster list") DEFINE_MTYPE(BGPD, CLUSTER, "Cluster list")
DEFINE_MTYPE(BGPD, CLUSTER_VAL, "Cluster list val") DEFINE_MTYPE(BGPD, CLUSTER_VAL, "Cluster list val")
DEFINE_MTYPE(BGPD, BGP_PROCESS_QUEUE, "BGP Process queue") DEFINE_MTYPE(BGPD, BGP_PROCESS_QUEUE, "BGP Process queue")
DEFINE_MTYPE(BGPD, BGP_CLEAR_NODE_QUEUE, "BGP node clear queue") DEFINE_MTYPE(BGPD, BGP_CLEAR_NODE_QUEUE, "BGP node clear queue")
DEFINE_MTYPE(BGPD, TRANSIT, "BGP transit attr") DEFINE_MTYPE(BGPD, TRANSIT, "BGP transit attr")
DEFINE_MTYPE(BGPD, TRANSIT_VAL, "BGP transit val") DEFINE_MTYPE(BGPD, TRANSIT_VAL, "BGP transit val")
DEFINE_MTYPE(BGPD, BGP_DEBUG_FILTER, "BGP debug filter") DEFINE_MTYPE(BGPD, BGP_DEBUG_FILTER, "BGP debug filter")
DEFINE_MTYPE(BGPD, BGP_DEBUG_STR, "BGP debug filter string") DEFINE_MTYPE(BGPD, BGP_DEBUG_STR, "BGP debug filter string")
DEFINE_MTYPE(BGPD, BGP_DISTANCE, "BGP distance") DEFINE_MTYPE(BGPD, BGP_DISTANCE, "BGP distance")
DEFINE_MTYPE(BGPD, BGP_NEXTHOP_CACHE, "BGP nexthop") DEFINE_MTYPE(BGPD, BGP_NEXTHOP_CACHE, "BGP nexthop")
DEFINE_MTYPE(BGPD, BGP_CONFED_LIST, "BGP confed list") DEFINE_MTYPE(BGPD, BGP_CONFED_LIST, "BGP confed list")
DEFINE_MTYPE(BGPD, PEER_UPDATE_SOURCE, "BGP peer update interface") DEFINE_MTYPE(BGPD, PEER_UPDATE_SOURCE, "BGP peer update interface")
DEFINE_MTYPE(BGPD, PEER_CONF_IF, "BGP peer config interface") DEFINE_MTYPE(BGPD, PEER_CONF_IF, "BGP peer config interface")
DEFINE_MTYPE(BGPD, BGP_DAMP_INFO, "Dampening info") DEFINE_MTYPE(BGPD, BGP_DAMP_INFO, "Dampening info")
DEFINE_MTYPE(BGPD, BGP_DAMP_ARRAY, "BGP Dampening array") DEFINE_MTYPE(BGPD, BGP_DAMP_ARRAY, "BGP Dampening array")
DEFINE_MTYPE(BGPD, BGP_REGEXP, "BGP regexp") DEFINE_MTYPE(BGPD, BGP_REGEXP, "BGP regexp")
DEFINE_MTYPE(BGPD, BGP_AGGREGATE, "BGP aggregate") DEFINE_MTYPE(BGPD, BGP_AGGREGATE, "BGP aggregate")
DEFINE_MTYPE(BGPD, BGP_ADDR, "BGP own address") DEFINE_MTYPE(BGPD, BGP_ADDR, "BGP own address")
DEFINE_MTYPE(BGPD, BGP_REDIST, "BGP redistribution") DEFINE_MTYPE(BGPD, BGP_REDIST, "BGP redistribution")
DEFINE_MTYPE(BGPD, BGP_FILTER_NAME, "BGP Filter Information") DEFINE_MTYPE(BGPD, BGP_FILTER_NAME, "BGP Filter Information")
DEFINE_MTYPE(BGPD, BGP_DUMP_STR, "BGP Dump String Information") DEFINE_MTYPE(BGPD, BGP_DUMP_STR, "BGP Dump String Information")
DEFINE_MTYPE(BGPD, ENCAP_TLV, "ENCAP TLV") 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, BGP_TEA_OPTIONS_VALUE, "BGP TEA Options Value")
DEFINE_MTYPE(BGPD, LCOMMUNITY, "Large Community") DEFINE_MTYPE(BGPD, LCOMMUNITY, "Large Community")
DEFINE_MTYPE(BGPD, LCOMMUNITY_STR, "Large Community display string") DEFINE_MTYPE(BGPD, LCOMMUNITY_STR, "Large Community display string")
DEFINE_MTYPE(BGPD, LCOMMUNITY_VAL, "Large Community value") 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_UPD_SUBGRP)
DECLARE_MTYPE(BGP_PACKET) DECLARE_MTYPE(BGP_PACKET)
DECLARE_MTYPE(ATTR) DECLARE_MTYPE(ATTR)
DECLARE_MTYPE(ATTR_EXTRA)
DECLARE_MTYPE(AS_PATH) DECLARE_MTYPE(AS_PATH)
DECLARE_MTYPE(AS_SEG) DECLARE_MTYPE(AS_SEG)
DECLARE_MTYPE(AS_SEG_DATA) DECLARE_MTYPE(AS_SEG_DATA)
@ -110,4 +109,8 @@ DECLARE_MTYPE(BGP_TEA_OPTIONS_VALUE)
DECLARE_MTYPE(LCOMMUNITY) DECLARE_MTYPE(LCOMMUNITY)
DECLARE_MTYPE(LCOMMUNITY_STR) DECLARE_MTYPE(LCOMMUNITY_STR)
DECLARE_MTYPE(LCOMMUNITY_VAL) DECLARE_MTYPE(LCOMMUNITY_VAL)
DECLARE_MTYPE(BGP_EVPN)
DECLARE_MTYPE(BGP_EVPN_IMPORT_RT)
DECLARE_MTYPE(BGP_EVPN_MACIP)
#endif /* _QUAGGA_BGP_MEMORY_H */ #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 /* Supplemental information linked to bgp_info for keeping track of
* multipath selections, lazily allocated to save memory * multipath selections, lazily allocated to save memory
*/ */
struct bgp_info_mpath struct bgp_info_mpath {
{ /* Points to the first multipath (on bestpath) or the next multipath */
/* Points to the first multipath (on bestpath) or the next multipath */ struct bgp_info_mpath *mp_next;
struct bgp_info_mpath *mp_next;
/* Points to the previous multipath or NULL on bestpath */ /* Points to the previous multipath or NULL on bestpath */
struct bgp_info_mpath *mp_prev; struct bgp_info_mpath *mp_prev;
/* Points to bgp_info associated with this multipath info */ /* Points to bgp_info associated with this multipath info */
struct bgp_info *mp_info; struct bgp_info *mp_info;
/* When attached to best path, the number of selected multipaths */ /* When attached to best path, the number of selected multipaths */
u_int32_t mp_count; u_int32_t mp_count;
/* Aggregated attribute for advertising multipath route */ /* Aggregated attribute for advertising multipath route */
struct attr *mp_attr; struct attr *mp_attr;
}; };
/* Functions to support maximum-paths configuration */ /* Functions to support maximum-paths configuration */
extern int bgp_maximum_paths_set (struct bgp *, afi_t, safi_t, int, u_int16_t, extern int bgp_maximum_paths_set(struct bgp *, afi_t, safi_t, int, u_int16_t,
u_int16_t); u_int16_t);
extern int bgp_maximum_paths_unset (struct bgp *, afi_t, safi_t, int); extern int bgp_maximum_paths_unset(struct bgp *, afi_t, safi_t, int);
/* Functions used by bgp_best_selection to record current /* Functions used by bgp_best_selection to record current
* multipath selections * multipath selections
*/ */
extern int bgp_info_nexthop_cmp (struct bgp_info *bi1, struct bgp_info *bi2); 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_init(struct list *);
extern void bgp_mp_list_clear (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_list_add(struct list *, struct bgp_info *);
extern void bgp_mp_dmed_deselect (struct bgp_info *); extern void bgp_mp_dmed_deselect(struct bgp_info *);
extern void bgp_info_mpath_update (struct bgp_node *, struct bgp_info *, extern void bgp_info_mpath_update(struct bgp_node *, struct bgp_info *,
struct bgp_info *, struct list *, struct bgp_info *, struct list *,
struct bgp_maxpaths_cfg *); struct bgp_maxpaths_cfg *);
extern void bgp_info_mpath_aggregate_update (struct bgp_info *, extern void bgp_info_mpath_aggregate_update(struct bgp_info *,
struct bgp_info *); struct bgp_info *);
/* Unlink and free multipath information associated with a 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_dequeue(struct bgp_info *);
extern void bgp_info_mpath_free (struct bgp_info_mpath **); extern void bgp_info_mpath_free(struct bgp_info_mpath **);
/* Walk list of multipaths associated with a best path */ /* 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_first(struct bgp_info *);
extern struct bgp_info *bgp_info_mpath_next (struct bgp_info *); extern struct bgp_info *bgp_info_mpath_next(struct bgp_info *);
/* Accessors for multipath information */ /* Accessors for multipath information */
extern u_int32_t bgp_info_mpath_count (struct bgp_info *); extern u_int32_t bgp_info_mpath_count(struct bgp_info *);
extern struct attr *bgp_info_mpath_attr (struct bgp_info *); extern struct attr *bgp_info_mpath_attr(struct bgp_info *);
#endif /* _QUAGGA_BGP_MPATH_H */ #endif /* _QUAGGA_BGP_MPATH_H */

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,7 @@
/* MPLS-VPN /* MPLS-VPN
* Copyright (C) 2000 Kunihiro Ishiguro <kunihiro@zebra.org> * 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 * 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 * under the terms of the GNU General Public License as published by the
@ -22,100 +22,57 @@
#define _QUAGGA_BGP_MPLSVPN_H #define _QUAGGA_BGP_MPLSVPN_H
#include "bgpd/bgp_route.h" #include "bgpd/bgp_route.h"
#include "bgpd/bgp_rd.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
#ifdef MPLS_LABEL_MAX #ifdef MPLS_LABEL_MAX
# undef MPLS_LABEL_MAX #undef MPLS_LABEL_MAX
#endif #endif
typedef enum { typedef enum {
MPLS_LABEL_IPV4_EXPLICIT_NULL = 0, /* [RFC3032] */ MPLS_LABEL_IPV4_EXPLICIT_NULL = 0, /* [RFC3032] */
MPLS_LABEL_ROUTER_ALERT = 1, /* [RFC3032] */ MPLS_LABEL_ROUTER_ALERT = 1, /* [RFC3032] */
MPLS_LABEL_IPV6_EXPLICIT_NULL = 2, /* [RFC3032] */ MPLS_LABEL_IPV6_EXPLICIT_NULL = 2, /* [RFC3032] */
MPLS_LABEL_IMPLICIT_NULL = 3, /* [RFC3032] */ MPLS_LABEL_IMPLICIT_NULL = 3, /* [RFC3032] */
MPLS_LABEL_UNASSIGNED4 = 4, MPLS_LABEL_UNASSIGNED4 = 4,
MPLS_LABEL_UNASSIGNED5 = 5, MPLS_LABEL_UNASSIGNED5 = 5,
MPLS_LABEL_UNASSIGNED6 = 6, MPLS_LABEL_UNASSIGNED6 = 6,
MPLS_LABEL_ELI = 7, /* Entropy Indicator [RFC6790] */ MPLS_LABEL_ELI = 7, /* Entropy Indicator [RFC6790] */
MPLS_LABEL_UNASSIGNED8 = 8, MPLS_LABEL_UNASSIGNED8 = 8,
MPLS_LABEL_UNASSIGNED9 = 9, MPLS_LABEL_UNASSIGNED9 = 9,
MPLS_LABEL_UNASSIGNED10 = 10, MPLS_LABEL_UNASSIGNED10 = 10,
MPLS_LABEL_UNASSIGNED11 = 11, MPLS_LABEL_UNASSIGNED11 = 11,
MPLS_LABEL_GAL = 13, /* [RFC5586] */ MPLS_LABEL_GAL = 13, /* [RFC5586] */
MPLS_LABEL_OAM_ALERT = 14, /* [RFC3429] */ MPLS_LABEL_OAM_ALERT = 14, /* [RFC3429] */
MPLS_LABEL_EXTENSION = 15, /* [RFC7274] */ MPLS_LABEL_EXTENSION = 15, /* [RFC7274] */
MPLS_LABEL_MAX = 1048575, MPLS_LABEL_MAX = 1048575,
MPLS_LABEL_ILLEGAL = 0xFFFFFFFF /* for internal use only */ MPLS_LABEL_ILLEGAL = 0xFFFFFFFF /* for internal use only */
} mpls_special_label_t; } mpls_special_label_t;
#define MPLS_LABEL_IS_SPECIAL(label) \ #define MPLS_LABEL_IS_SPECIAL(label) ((label) <= MPLS_LABEL_EXTENSION)
((label) <= MPLS_LABEL_EXTENSION) #define MPLS_LABEL_IS_NULL(label) \
#define MPLS_LABEL_IS_NULL(label) \ ((label) == MPLS_LABEL_IPV4_EXPLICIT_NULL \
((label) == MPLS_LABEL_IPV4_EXPLICIT_NULL || \ || (label) == MPLS_LABEL_IPV6_EXPLICIT_NULL \
(label) == MPLS_LABEL_IPV6_EXPLICIT_NULL || \ || (label) == MPLS_LABEL_IMPLICIT_NULL)
(label) == MPLS_LABEL_IMPLICIT_NULL)
#define BGP_VPNVX_HELP_STR \ #define BGP_VPNVX_HELP_STR \
"Address Family\n" \ "Address Family\n" \
"Address Family\n" "Address Family\n"
#define V4_HEADER \ #define V4_HEADER \
" Network Next Hop Metric LocPrf Weight Path" " Network Next Hop Metric LocPrf Weight Path\n"
#define V4_HEADER_TAG \ #define V4_HEADER_TAG " Network Next Hop In tag/Out tag\n"
" Network Next Hop In tag/Out tag" #define V4_HEADER_OVERLAY \
#define V4_HEADER_OVERLAY \ " Network Next Hop EthTag Overlay Index RouterMac\n"
" Network Next Hop EthTag Overlay Index RouterMac"
struct rd_as extern void bgp_mplsvpn_init(void);
{ extern int bgp_nlri_parse_vpn(struct peer *, struct attr *, struct bgp_nlri *);
u_int16_t type; extern u_int32_t decode_label(mpls_label_t *);
as_t as; extern void encode_label(mpls_label_t, mpls_label_t *);
u_int32_t val;
};
struct rd_ip extern int argv_find_and_parse_vpnvx(struct cmd_token **argv, int argc,
{ int *index, afi_t *afi);
u_int16_t type; extern int bgp_show_mpls_vpn(struct vty *vty, afi_t afi, struct prefix_rd *prd,
struct in_addr ip; enum bgp_show_type type, void *output_arg,
u_int16_t val; int tags, u_char use_json);
};
#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);
#endif /* _QUAGGA_BGP_MPLSVPN_H */ #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 #define BGP_SOCKET_SNDBUF_SIZE 65536
extern int bgp_socket (unsigned short, const char *); extern int bgp_socket(unsigned short, const char *);
extern void bgp_close (void); extern void bgp_close(void);
extern int bgp_connect (struct peer *); extern int bgp_connect(struct peer *);
extern int bgp_getsockname (struct peer *); extern int bgp_getsockname(struct peer *);
extern int bgp_md5_set (struct peer *); extern int bgp_md5_set(struct peer *);
extern int bgp_md5_unset (struct peer *); extern int bgp_md5_unset(struct peer *);
extern int bgp_set_socket_ttl(struct peer *, int fd); extern int bgp_set_socket_ttl(struct peer *, int fd);
#endif /* _QUAGGA_BGP_NETWORK_H */ #endif /* _QUAGGA_BGP_NETWORK_H */

View File

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

View File

@ -25,28 +25,26 @@
#include "queue.h" #include "queue.h"
#include "prefix.h" #include "prefix.h"
#define NEXTHOP_FAMILY(nexthop_len) ( \ #define NEXTHOP_FAMILY(nexthop_len) \
((nexthop_len) == 4 || \ (((nexthop_len) == 4 || (nexthop_len) == 12 \
(nexthop_len) == 12 ? AF_INET : \ ? AF_INET \
((nexthop_len) == 16 || \ : ((nexthop_len) == 16 || (nexthop_len) == 24 \
(nexthop_len) == 24 || \ || (nexthop_len) == 48 \
(nexthop_len) == 48 ? AF_INET6 : \ ? AF_INET6 \
AF_UNSPEC)) \ : AF_UNSPEC)))
)
#define BGP_MP_NEXTHOP_FAMILY NEXTHOP_FAMILY #define BGP_MP_NEXTHOP_FAMILY NEXTHOP_FAMILY
/* BGP nexthop cache value structure. */ /* BGP nexthop cache value structure. */
struct bgp_nexthop_cache struct bgp_nexthop_cache {
{ /* IGP route's metric. */
/* IGP route's metric. */ u_int32_t metric;
u_int32_t metric;
/* Nexthop number and nexthop linked list.*/ /* Nexthop number and nexthop linked list.*/
u_char nexthop_num; u_char nexthop_num;
struct nexthop *nexthop; struct nexthop *nexthop;
time_t last_update; time_t last_update;
u_int16_t flags; u_int16_t flags;
#define BGP_NEXTHOP_VALID (1 << 0) #define BGP_NEXTHOP_VALID (1 << 0)
#define BGP_NEXTHOP_REGISTERED (1 << 1) #define BGP_NEXTHOP_REGISTERED (1 << 1)
@ -55,26 +53,26 @@ struct bgp_nexthop_cache
#define BGP_STATIC_ROUTE (1 << 4) #define BGP_STATIC_ROUTE (1 << 4)
#define BGP_STATIC_ROUTE_EXACT_MATCH (1 << 5) #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_CHANGED (1 << 0)
#define BGP_NEXTHOP_METRIC_CHANGED (1 << 1) #define BGP_NEXTHOP_METRIC_CHANGED (1 << 1)
#define BGP_NEXTHOP_CONNECTED_CHANGED (1 << 2) #define BGP_NEXTHOP_CONNECTED_CHANGED (1 << 2)
struct bgp_node *node; struct bgp_node *node;
void *nht_info; /* In BGP, peer session */ void *nht_info; /* In BGP, peer session */
LIST_HEAD(path_list, bgp_info) paths; LIST_HEAD(path_list, bgp_info) paths;
unsigned int path_count; unsigned int path_count;
struct bgp *bgp; struct bgp *bgp;
}; };
extern int bgp_nexthop_lookup (afi_t, struct peer *peer, struct bgp_info *, extern int bgp_nexthop_lookup(afi_t, struct peer *peer, struct bgp_info *,
int *, int *); int *, int *);
extern void bgp_connected_add (struct bgp *bgp, struct connected *c); extern void bgp_connected_add(struct bgp *bgp, struct connected *c);
extern void bgp_connected_delete (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_multiaccess_check_v4(struct in_addr, struct peer *);
extern int bgp_config_write_scan_time (struct vty *); extern int bgp_config_write_scan_time(struct vty *);
extern int bgp_nexthop_self (struct bgp *, struct attr *); extern int bgp_nexthop_self(struct bgp *, struct in_addr);
extern struct bgp_nexthop_cache *bnc_new(void); extern struct bgp_nexthop_cache *bnc_new(void);
extern void bnc_free(struct bgp_nexthop_cache *bnc); extern void bnc_free(struct bgp_nexthop_cache *bnc);
extern void bnc_nexthop_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_init(struct bgp *bgp);
extern void bgp_scan_finish(struct bgp *bgp); extern void bgp_scan_finish(struct bgp *bgp);
extern void bgp_scan_vty_init(void); extern void bgp_scan_vty_init(void);
extern void bgp_address_init (struct bgp *bgp); extern void bgp_address_init(struct bgp *bgp);
extern void bgp_address_destroy (struct bgp *bgp); extern void bgp_address_destroy(struct bgp *bgp);
#endif /* _QUAGGA_BGP_NEXTHOP_H */ #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 * peer - The BGP peer associated with this NHT
* connected - True if NH MUST be a connected route * connected - True if NH MUST be a connected route
*/ */
extern int bgp_find_or_add_nexthop(struct bgp *bgp, afi_t a, extern int bgp_find_or_add_nexthop(struct bgp *bgp, afi_t a, struct bgp_info *p,
struct bgp_info *p, struct peer *peer, int connected); struct peer *peer, int connected);
/** /**
* bgp_unlink_nexthop() - Unlink the nexthop object from the path structure. * 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. * p - path structure.
*/ */
extern void bgp_unlink_nexthop(struct bgp_info *p); 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 * 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 * afi - afi: AFI_IP or AF_IP6
* peer - Ptr to peer * 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 */ #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 #define _QUAGGA_BGP_OPEN_H
/* Standard header for capability TLV */ /* Standard header for capability TLV */
struct capability_header struct capability_header {
{ u_char code;
u_char code; u_char length;
u_char length;
}; };
/* Generic MP capability data */ /* Generic MP capability data */
struct capability_mp_data struct capability_mp_data {
{ iana_afi_t afi;
iana_afi_t afi; u_char reserved;
u_char reserved; safi_t safi;
safi_t safi;
}; };
struct capability_as4 struct capability_as4 {
{ uint32_t as4;
uint32_t as4;
}; };
struct graceful_restart_af struct graceful_restart_af {
{ afi_t afi;
afi_t afi; safi_t safi;
safi_t safi; u_char flag;
u_char flag;
}; };
struct capability_gr struct capability_gr {
{ u_int16_t restart_flag_time;
u_int16_t restart_flag_time; struct graceful_restart_af gr[];
struct graceful_restart_af gr[];
}; };
/* Capability Code */ /* Capability Code */
@ -68,7 +63,6 @@ struct capability_gr
#define CAPABILITY_CODE_REFRESH_OLD 128 /* Route Refresh Capability(cisco) */ #define CAPABILITY_CODE_REFRESH_OLD 128 /* Route Refresh Capability(cisco) */
#define CAPABILITY_CODE_ORF_OLD 130 /* Cooperative Route Filtering Capability(cisco) */ #define CAPABILITY_CODE_ORF_OLD 130 /* Cooperative Route Filtering Capability(cisco) */
/* Capability Length */ /* Capability Length */
#define CAPABILITY_CODE_MP_LEN 4 #define CAPABILITY_CODE_MP_LEN 4
#define CAPABILITY_CODE_REFRESH_LEN 0 #define CAPABILITY_CODE_REFRESH_LEN 0
@ -99,9 +93,10 @@ struct capability_gr
#define RESTART_R_BIT 0x8000 #define RESTART_R_BIT 0x8000
#define RESTART_F_BIT 0x80 #define RESTART_F_BIT 0x80
extern int bgp_open_option_parse (struct peer *, u_char, int *); extern int bgp_open_option_parse(struct peer *, u_char, int *);
extern void bgp_open_capability (struct stream *, struct peer *); extern void bgp_open_capability(struct stream *, struct peer *);
extern void bgp_capability_vty_out (struct vty *, struct peer *, u_char, json_object *); extern void bgp_capability_vty_out(struct vty *, struct peer *, u_char,
extern as_t peek_for_as4_capability (struct peer *, u_char); json_object *);
extern as_t peek_for_as4_capability(struct peer *, u_char);
#endif /* _QUAGGA_BGP_OPEN_H */ #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 #define ORF_COMMON_PART_DENY 0x20
/* Packet send and receive function prototypes. */ /* Packet send and receive function prototypes. */
extern int bgp_read (struct thread *); extern int bgp_read(struct thread *);
extern int bgp_write (struct thread *); extern int bgp_write(struct thread *);
extern int bgp_connect_check (struct peer *, int change_state); extern int bgp_connect_check(struct peer *, int change_state);
extern void bgp_keepalive_send (struct peer *); extern void bgp_keepalive_send(struct peer *);
extern void bgp_open_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(struct peer *, u_int8_t, u_int8_t);
extern void bgp_notify_send_with_data (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); 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_route_refresh_send(struct peer *, afi_t, safi_t, u_char, u_char,
extern void bgp_capability_send (struct peer *, afi_t, safi_t, int, int); int);
extern void bgp_default_update_send (struct peer *, struct attr *, extern void bgp_capability_send(struct peer *, afi_t, safi_t, int, int);
afi_t, safi_t, struct peer *); extern void bgp_default_update_send(struct peer *, struct attr *, afi_t, safi_t,
extern void bgp_default_withdraw_send (struct peer *, 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_restarted_peers(struct peer *);
extern void bgp_update_implicit_eors (struct peer *); extern void bgp_update_implicit_eors(struct peer *);
extern void bgp_check_update_delay (struct bgp *); 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_marker(struct stream *s, u_char type);
extern int bgp_packet_set_size (struct stream *s); extern int bgp_packet_set_size(struct stream *s);
extern void bgp_packet_add (struct peer *peer, struct stream *s); extern void bgp_packet_add(struct peer *peer, struct stream *s);
#endif /* _QUAGGA_BGP_PACKET_H */ #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

@ -35,61 +35,55 @@
(^|[,{}() ]|$) */ (^|[,{}() ]|$) */
regex_t * regex_t *bgp_regcomp(const char *regstr)
bgp_regcomp (const char *regstr)
{ {
/* Convert _ character to generic regular expression. */ /* Convert _ character to generic regular expression. */
int i, j; int i, j;
int len; int len;
int magic = 0; int magic = 0;
char *magic_str; char *magic_str;
char magic_regexp[] = "(^|[,{}() ]|$)"; char magic_regexp[] = "(^|[,{}() ]|$)";
int ret; int ret;
regex_t *regex; regex_t *regex;
len = strlen (regstr); len = strlen(regstr);
for (i = 0; i < len; i++) for (i = 0; i < len; i++)
if (regstr[i] == '_') if (regstr[i] == '_')
magic++; magic++;
magic_str = XMALLOC (MTYPE_TMP, len + (14 * magic) + 1); magic_str = XMALLOC(MTYPE_TMP, len + (14 * magic) + 1);
for (i = 0, j = 0; i < len; i++) for (i = 0, j = 0; i < len; i++) {
{ if (regstr[i] == '_') {
if (regstr[i] == '_') memcpy(magic_str + j, magic_regexp,
{ strlen(magic_regexp));
memcpy (magic_str + j, magic_regexp, strlen (magic_regexp)); j += strlen(magic_regexp);
j += strlen (magic_regexp); } else
magic_str[j++] = regstr[i];
} }
else magic_str[j] = '\0';
magic_str[j++] = regstr[i];
}
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) if (ret != 0) {
{ XFREE(MTYPE_BGP_REGEXP, regex);
XFREE (MTYPE_BGP_REGEXP, regex); return NULL;
return NULL; }
}
return regex; return regex;
} }
int int bgp_regexec(regex_t *regex, struct aspath *aspath)
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 void bgp_regex_free(regex_t *regex)
bgp_regex_free (regex_t *regex)
{ {
regfree (regex); regfree(regex);
XFREE (MTYPE_BGP_REGEXP, regex); XFREE(MTYPE_BGP_REGEXP, regex);
} }

View File

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

View File

@ -21,42 +21,41 @@
#ifndef _QUAGGA_BGP_TABLE_H #ifndef _QUAGGA_BGP_TABLE_H
#define _QUAGGA_BGP_TABLE_H #define _QUAGGA_BGP_TABLE_H
#include "mpls.h"
#include "table.h" #include "table.h"
struct bgp_table struct bgp_table {
{ /* afi/safi of this table */
/* afi/safi of this table */ afi_t afi;
afi_t afi; safi_t safi;
safi_t safi;
int lock; int lock;
struct route_table *route_table; struct route_table *route_table;
uint64_t version; uint64_t version;
}; };
struct bgp_node struct bgp_node {
{ /*
/* * CAUTION
* CAUTION *
* * These fields must be the very first fields in this structure.
* These fields must be the very first fields in this structure. *
* * @see bgp_node_to_rnode
* @see bgp_node_to_rnode * @see bgp_node_from_rnode
* @see bgp_node_from_rnode */
*/ ROUTE_NODE_FIELDS
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; uint64_t version;
u_char flags; u_char flags;
#define BGP_NODE_PROCESS_SCHEDULED (1 << 0) #define BGP_NODE_PROCESS_SCHEDULED (1 << 0)
#define BGP_NODE_USER_CLEAR (1 << 1) #define BGP_NODE_USER_CLEAR (1 << 1)
#define BGP_NODE_LABEL_CHANGED (1 << 2) #define BGP_NODE_LABEL_CHANGED (1 << 2)
@ -68,16 +67,15 @@ struct bgp_node
* *
* Structure that holds state for iterating over a bgp table. * Structure that holds state for iterating over a bgp table.
*/ */
typedef struct bgp_table_iter_t_ typedef struct bgp_table_iter_t_ {
{ struct bgp_table *table;
struct bgp_table *table; route_table_iter_t rt_iter;
route_table_iter_t rt_iter;
} bgp_table_iter_t; } bgp_table_iter_t;
extern struct bgp_table *bgp_table_init (afi_t, safi_t); extern struct bgp_table *bgp_table_init(afi_t, safi_t);
extern void bgp_table_lock (struct bgp_table *); extern void bgp_table_lock(struct bgp_table *);
extern void bgp_table_unlock (struct bgp_table *); extern void bgp_table_unlock(struct bgp_table *);
extern void bgp_table_finish (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. * Returns the bgp_node structure corresponding to a route_node.
*/ */
static inline struct bgp_node * static inline struct bgp_node *bgp_node_from_rnode(struct route_node *rnode)
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. * Returns the route_node structure corresponding to a bgp_node.
*/ */
static inline struct route_node * static inline struct route_node *bgp_node_to_rnode(struct bgp_node *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. * Returns the bgp_table that the given node is in.
*/ */
static inline struct bgp_table * static inline struct bgp_table *bgp_node_table(struct bgp_node *node)
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. * Gets the parent node of the given node without locking it.
*/ */
static inline struct bgp_node * static inline struct bgp_node *bgp_node_parent_nolock(struct bgp_node *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 * bgp_unlock_node
*/ */
static inline void static inline void bgp_unlock_node(struct bgp_node *node)
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 * @see bgp_table_top
*/ */
static inline struct bgp_node * 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 * bgp_table_top
*/ */
static inline struct bgp_node * 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 * bgp_route_next
*/ */
static inline struct bgp_node * static inline struct bgp_node *bgp_route_next(struct bgp_node *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 * bgp_route_next_until
*/ */
static inline struct bgp_node * static inline struct bgp_node *bgp_route_next_until(struct bgp_node *node,
bgp_route_next_until (struct bgp_node *node, struct bgp_node *limit) struct bgp_node *limit)
{ {
struct route_node *rnode; struct route_node *rnode;
rnode = route_next_until (bgp_node_to_rnode (node), rnode = route_next_until(bgp_node_to_rnode(node),
bgp_node_to_rnode (limit)); bgp_node_to_rnode(limit));
return bgp_node_from_rnode (rnode); return bgp_node_from_rnode(rnode);
} }
/* /*
* bgp_node_get * bgp_node_get
*/ */
static inline struct bgp_node * static inline struct bgp_node *bgp_node_get(struct bgp_table *const table,
bgp_node_get (struct bgp_table *const table, struct prefix *p) 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 * bgp_node_lookup
*/ */
static inline struct bgp_node * 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 * bgp_lock_node
*/ */
static inline struct bgp_node * static inline struct bgp_node *bgp_lock_node(struct bgp_node *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 * bgp_node_match
*/ */
static inline struct bgp_node * static inline struct bgp_node *bgp_node_match(const struct bgp_table *table,
bgp_node_match (const struct bgp_table *table, struct prefix *p) 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 * bgp_node_match_ipv4
*/ */
static inline struct bgp_node * 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, return bgp_node_from_rnode(
addr)); route_node_match_ipv4(table->route_table, addr));
} }
/* /*
* bgp_node_match_ipv6 * bgp_node_match_ipv6
*/ */
static inline struct bgp_node * 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, return bgp_node_from_rnode(
addr)); route_node_match_ipv6(table->route_table, addr));
} }
static inline unsigned long static inline unsigned long bgp_table_count(const struct bgp_table *const table)
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 * bgp_table_get_next
*/ */
static inline struct bgp_node * static inline struct bgp_node *bgp_table_get_next(const struct bgp_table *table,
bgp_table_get_next (const struct bgp_table *table, struct prefix *p) 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 * bgp_table_iter_init
*/ */
static inline void static inline void bgp_table_iter_init(bgp_table_iter_t *iter,
bgp_table_iter_init (bgp_table_iter_t * iter, struct bgp_table *table) struct bgp_table *table)
{ {
bgp_table_lock (table); bgp_table_lock(table);
iter->table = table; iter->table = table;
route_table_iter_init (&iter->rt_iter, table->route_table); route_table_iter_init(&iter->rt_iter, table->route_table);
} }
/* /*
* bgp_table_iter_next * bgp_table_iter_next
*/ */
static inline struct bgp_node * static inline struct bgp_node *bgp_table_iter_next(bgp_table_iter_t *iter)
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 * bgp_table_iter_cleanup
*/ */
static inline void static inline void bgp_table_iter_cleanup(bgp_table_iter_t *iter)
bgp_table_iter_cleanup (bgp_table_iter_t * iter)
{ {
route_table_iter_cleanup (&iter->rt_iter); route_table_iter_cleanup(&iter->rt_iter);
bgp_table_unlock (iter->table); bgp_table_unlock(iter->table);
iter->table = NULL; iter->table = NULL;
} }
/* /*
* bgp_table_iter_pause * bgp_table_iter_pause
*/ */
static inline void static inline void bgp_table_iter_pause(bgp_table_iter_t *iter)
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 * bgp_table_iter_is_done
*/ */
static inline int static inline int bgp_table_iter_is_done(bgp_table_iter_t *iter)
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 * bgp_table_iter_started
*/ */
static inline int static inline int bgp_table_iter_started(bgp_table_iter_t *iter)
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... /* This would benefit from a real atomic operation...
* until then. */ * until then. */
static inline uint64_t static inline uint64_t bgp_table_next_version(struct bgp_table *table)
bgp_table_next_version (struct bgp_table *table)
{ {
return ++table->version; return ++table->version;
} }
static inline uint64_t static inline uint64_t bgp_table_version(struct bgp_table *table)
bgp_table_version (struct bgp_table *table)
{ {
return table->version; return table->version;
} }
#endif /* _QUAGGA_BGP_TABLE_H */ #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 BGP_DEFAULT_SUBGROUP_COALESCE_TIME 200
#define PEER_UPDGRP_FLAGS (PEER_FLAG_LOCAL_AS_NO_PREPEND | \ #define PEER_UPDGRP_FLAGS \
PEER_FLAG_LOCAL_AS_REPLACE_AS) (PEER_FLAG_LOCAL_AS_NO_PREPEND | PEER_FLAG_LOCAL_AS_REPLACE_AS)
#define PEER_UPDGRP_AF_FLAGS (PEER_FLAG_SEND_COMMUNITY | \ #define PEER_UPDGRP_AF_FLAGS \
PEER_FLAG_SEND_EXT_COMMUNITY | \ (PEER_FLAG_SEND_COMMUNITY | PEER_FLAG_SEND_EXT_COMMUNITY \
PEER_FLAG_DEFAULT_ORIGINATE | \ | PEER_FLAG_DEFAULT_ORIGINATE | PEER_FLAG_REFLECTOR_CLIENT \
PEER_FLAG_REFLECTOR_CLIENT | \ | PEER_FLAG_RSERVER_CLIENT | PEER_FLAG_NEXTHOP_SELF \
PEER_FLAG_RSERVER_CLIENT | \ | PEER_FLAG_NEXTHOP_UNCHANGED | PEER_FLAG_FORCE_NEXTHOP_SELF \
PEER_FLAG_NEXTHOP_SELF | \ | PEER_FLAG_AS_PATH_UNCHANGED | PEER_FLAG_MED_UNCHANGED \
PEER_FLAG_NEXTHOP_UNCHANGED | \ | PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED | PEER_FLAG_REMOVE_PRIVATE_AS \
PEER_FLAG_FORCE_NEXTHOP_SELF | \ | PEER_FLAG_REMOVE_PRIVATE_AS_ALL \
PEER_FLAG_AS_PATH_UNCHANGED | \ | PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE \
PEER_FLAG_MED_UNCHANGED | \ | PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE \
PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED | \ | PEER_FLAG_ADDPATH_TX_ALL_PATHS \
PEER_FLAG_REMOVE_PRIVATE_AS | \ | PEER_FLAG_ADDPATH_TX_BESTPATH_PER_AS | PEER_FLAG_AS_OVERRIDE)
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_CAP_FLAGS (PEER_CAP_AS4_RCV)
#define PEER_UPDGRP_AF_CAP_FLAGS (PEER_CAP_ORF_PREFIX_SM_RCV | \ #define PEER_UPDGRP_AF_CAP_FLAGS \
PEER_CAP_ORF_PREFIX_SM_OLD_RCV |\ (PEER_CAP_ORF_PREFIX_SM_RCV | PEER_CAP_ORF_PREFIX_SM_OLD_RCV \
PEER_CAP_ADDPATH_AF_TX_ADV |\ | PEER_CAP_ADDPATH_AF_TX_ADV | PEER_CAP_ADDPATH_AF_RX_RCV \
PEER_CAP_ADDPATH_AF_RX_RCV |\ | PEER_CAP_ENHE_AF_NEGO)
PEER_CAP_ENHE_AF_NEGO)
typedef enum typedef enum { BGP_ATTR_VEC_NH = 0, BGP_ATTR_VEC_MAX } bpacket_attr_vec_type;
{
BGP_ATTR_VEC_NH = 0,
BGP_ATTR_VEC_MAX
} bpacket_attr_vec_type;
typedef struct typedef struct {
{ u_int32_t flags;
u_int32_t flags; unsigned long offset;
unsigned long offset;
} bpacket_attr_vec; } bpacket_attr_vec;
#define BPKT_ATTRVEC_FLAGS_UPDATED (1 << 0) #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_GNH_CHANGED (1 << 5)
#define BPKT_ATTRVEC_FLAGS_RMAP_IPV6_LNH_CHANGED (1 << 6) #define BPKT_ATTRVEC_FLAGS_RMAP_IPV6_LNH_CHANGED (1 << 6)
typedef struct bpacket_attr_vec_arr typedef struct bpacket_attr_vec_arr {
{ bpacket_attr_vec entries[BGP_ATTR_VEC_MAX];
bpacket_attr_vec entries[BGP_ATTR_VEC_MAX];
} bpacket_attr_vec_arr; } bpacket_attr_vec_arr;
struct bpacket struct bpacket {
{ /* for being part of an update subgroup's message list */
/* for being part of an update subgroup's message list */ TAILQ_ENTRY(bpacket) pkt_train;
TAILQ_ENTRY (bpacket) pkt_train;
/* list of peers (well, peer_afs) that the packet needs to be sent to */ /* list of peers (well, peer_afs) that the packet needs to be sent to */
LIST_HEAD (pkt_peer_list, peer_af) peers; LIST_HEAD(pkt_peer_list, peer_af) peers;
struct stream *buffer; struct stream *buffer;
bpacket_attr_vec_arr arr; bpacket_attr_vec_arr arr;
unsigned int ver; unsigned int ver;
}; };
struct bpacket_queue struct bpacket_queue {
{ TAILQ_HEAD(pkt_queue, bpacket) pkts;
TAILQ_HEAD (pkt_queue, bpacket) pkts;
#if 0 #if 0
/* A dummy packet that is used to thread all peers that have /* A dummy packet that is used to thread all peers that have
@ -110,149 +95,146 @@ struct bpacket_queue
struct bpacket sentinel; struct bpacket sentinel;
#endif #endif
unsigned int conf_max_count; unsigned int conf_max_count;
unsigned int curr_count; unsigned int curr_count;
unsigned int hwm_count; unsigned int hwm_count;
unsigned int max_count_reached_count; unsigned int max_count_reached_count;
}; };
struct update_group struct update_group {
{ /* back pointer to the BGP instance */
/* back pointer to the BGP instance */ struct bgp *bgp;
struct bgp *bgp;
/* list of subgroups that belong to the update group */ /* list of subgroups that belong to the update group */
LIST_HEAD (subgrp_list, update_subgroup) subgrps; LIST_HEAD(subgrp_list, update_subgroup) subgrps;
/* lazy way to store configuration common to all peers /* lazy way to store configuration common to all peers
hash function will compute from this data */ hash function will compute from this data */
struct peer *conf; struct peer *conf;
afi_t afi; afi_t afi;
safi_t safi; safi_t safi;
int afid; int afid;
uint64_t id; uint64_t id;
time_t uptime; time_t uptime;
u_int32_t join_events; u_int32_t join_events;
u_int32_t prune_events; u_int32_t prune_events;
u_int32_t merge_events; u_int32_t merge_events;
u_int32_t updgrp_switch_events; u_int32_t updgrp_switch_events;
u_int32_t peer_refreshes_combined; u_int32_t peer_refreshes_combined;
u_int32_t adj_count; u_int32_t adj_count;
u_int32_t split_events; u_int32_t split_events;
u_int32_t merge_checks_triggered; u_int32_t merge_checks_triggered;
u_int32_t subgrps_created; u_int32_t subgrps_created;
u_int32_t subgrps_deleted; 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. * Shorthand for a global statistics counter.
*/ */
#define UPDGRP_GLOBAL_STAT(updgrp, stat) \ #define UPDGRP_GLOBAL_STAT(updgrp, stat) \
((updgrp)->bgp->update_group_stats.stat) ((updgrp)->bgp->update_group_stats.stat)
/* /*
* Add the given value to a counter on an update group and the bgp * Add the given value to a counter on an update group and the bgp
* instance. * instance.
*/ */
#define UPDGRP_INCR_STAT_BY(updgrp, stat, value) \ #define UPDGRP_INCR_STAT_BY(updgrp, stat, value) \
do { \ do { \
(updgrp)->stat += (value); \ (updgrp)->stat += (value); \
UPDGRP_GLOBAL_STAT(updgrp, stat) += (value); \ UPDGRP_GLOBAL_STAT(updgrp, stat) += (value); \
} while (0) } while (0)
/* /*
* Increment a counter on a update group and its parent structures. * Increment a counter on a update group and its parent structures.
*/ */
#define UPDGRP_INCR_STAT(subgrp, stat) \ #define UPDGRP_INCR_STAT(subgrp, stat) UPDGRP_INCR_STAT_BY(subgrp, stat, 1)
UPDGRP_INCR_STAT_BY(subgrp, stat, 1)
struct update_subgroup struct update_subgroup {
{ /* back pointer to the parent update group */
/* back pointer to the parent update group */ struct update_group *update_group;
struct update_group *update_group;
/* list of peers that belong to the subgroup */ /* list of peers that belong to the subgroup */
LIST_HEAD (peer_list, peer_af) peers; LIST_HEAD(peer_list, peer_af) peers;
int peer_count; int peer_count;
/* for being part of an update group's subgroup list */ /* for being part of an update group's subgroup list */
LIST_ENTRY (update_subgroup) updgrp_train; LIST_ENTRY(update_subgroup) updgrp_train;
struct bpacket_queue pkt_queue; struct bpacket_queue pkt_queue;
/* /*
* List of adj-out structures for this subgroup. * List of adj-out structures for this subgroup.
* It essentially represents the snapshot of every prefix that * It essentially represents the snapshot of every prefix that
* has been advertised to the members of the subgroup * has been advertised to the members of the subgroup
*/ */
TAILQ_HEAD (adjout_queue, bgp_adj_out) adjq; TAILQ_HEAD(adjout_queue, bgp_adj_out) adjq;
/* packet buffer for update generation */ /* packet buffer for update generation */
struct stream *work; struct stream *work;
/* We use a separate stream to encode MP_REACH_NLRI for efficient /* We use a separate stream to encode MP_REACH_NLRI for efficient
* NLRI packing. peer->work stores all the other attributes. The * NLRI packing. peer->work stores all the other attributes. The
* actual packet is then constructed by concatenating the two. * actual packet is then constructed by concatenating the two.
*/ */
struct stream *scratch; struct stream *scratch;
/* synchronization list and time */ /* synchronization list and time */
struct bgp_synchronize *sync; struct bgp_synchronize *sync;
/* send prefix count */ /* send prefix count */
unsigned long scount; unsigned long scount;
/* announcement attribute hash */ /* announcement attribute hash */
struct hash *hash; struct hash *hash;
struct thread *t_coalesce; struct thread *t_coalesce;
u_int32_t v_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. */ /* table version that the subgroup has caught up to. */
uint64_t version; uint64_t version;
/* version maintained to record adj changes */ /* version maintained to record adj changes */
uint64_t adj_version; uint64_t adj_version;
time_t uptime; time_t uptime;
/* /*
* Identifying information about the subgroup that this subgroup was split * Identifying information about the subgroup that this subgroup was
* from, if any. * split
*/ * from, if any.
struct */
{ struct {
uint64_t update_group_id; uint64_t update_group_id;
uint64_t subgroup_id; uint64_t subgroup_id;
} split_from; } split_from;
u_int32_t join_events; u_int32_t join_events;
u_int32_t prune_events; u_int32_t prune_events;
/* /*
* This is bumped up when another subgroup merges into this one. * This is bumped up when another subgroup merges into this one.
*/ */
u_int32_t merge_events; u_int32_t merge_events;
u_int32_t updgrp_switch_events; u_int32_t updgrp_switch_events;
u_int32_t peer_refreshes_combined; u_int32_t peer_refreshes_combined;
u_int32_t adj_count; u_int32_t adj_count;
u_int32_t split_events; u_int32_t split_events;
u_int32_t merge_checks_triggered; u_int32_t merge_checks_triggered;
uint64_t id; uint64_t id;
u_int16_t sflags; u_int16_t sflags;
/* Subgroup flags, see below */ /* Subgroup flags, see below */
u_int16_t flags; u_int16_t flags;
}; };
/* /*
@ -267,43 +249,41 @@ struct update_subgroup
* Add the given value to the specified counter on a subgroup and its * Add the given value to the specified counter on a subgroup and its
* parent structures. * parent structures.
*/ */
#define SUBGRP_INCR_STAT_BY(subgrp, stat, value) \ #define SUBGRP_INCR_STAT_BY(subgrp, stat, value) \
do { \ do { \
(subgrp)->stat += (value); \ (subgrp)->stat += (value); \
if ((subgrp)->update_group) \ if ((subgrp)->update_group) \
UPDGRP_INCR_STAT_BY((subgrp)->update_group, stat, value); \ UPDGRP_INCR_STAT_BY((subgrp)->update_group, stat, \
} while (0) value); \
} while (0)
/* /*
* Increment a counter on a subgroup and its parent structures. * Increment a counter on a subgroup and its parent structures.
*/ */
#define SUBGRP_INCR_STAT(subgrp, stat) \ #define SUBGRP_INCR_STAT(subgrp, stat) SUBGRP_INCR_STAT_BY(subgrp, stat, 1)
SUBGRP_INCR_STAT_BY(subgrp, stat, 1)
/* /*
* Decrement a counter on a subgroup and its parent structures. * Decrement a counter on a subgroup and its parent structures.
*/ */
#define SUBGRP_DECR_STAT(subgrp, stat) \ #define SUBGRP_DECR_STAT(subgrp, stat) SUBGRP_INCR_STAT_BY(subgrp, stat, -1)
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 */ /* really a private structure */
struct updwalk_context struct updwalk_context {
{ struct vty *vty;
struct vty *vty; struct bgp_node *rn;
struct bgp_node *rn; struct bgp_info *ri;
struct bgp_info *ri; uint64_t updgrp_id;
uint64_t updgrp_id; uint64_t subgrp_id;
uint64_t subgrp_id; bgp_policy_type_e policy_type;
bgp_policy_type_e policy_type; const char *policy_name;
const char *policy_name; int policy_event_start_flag;
int policy_event_start_flag; int policy_route_update;
int policy_route_update; updgrp_walkcb cb;
updgrp_walkcb cb; void *context;
void *context; u_int8_t flags;
u_int8_t flags;
#define UPDWALK_FLAGS_ADVQUEUE (1 << 0) #define UPDWALK_FLAGS_ADVQUEUE (1 << 0)
#define UPDWALK_FLAGS_ADVERTISED (1 << 1) #define UPDWALK_FLAGS_ADVERTISED (1 << 1)
@ -321,8 +301,7 @@ struct updwalk_context
#define UPDGRP_AFI(u) ((u)->afi) #define UPDGRP_AFI(u) ((u)->afi)
#define UPDGRP_SAFI(u) ((u)->safi) #define UPDGRP_SAFI(u) ((u)->safi)
#define UPDGRP_INST(u) ((u)->bgp) #define UPDGRP_INST(u) ((u)->bgp)
#define UPDGRP_AFFLAGS(u) \ #define UPDGRP_AFFLAGS(u) ((u)->conf->af_flags[UPDGRP_AFI(u)][UPDGRP_SAFI(u)])
((u)->conf->af_flags[UPDGRP_AFI(u)][UPDGRP_SAFI(u)])
#define UPDGRP_DBG_ON(u) ((u)->num_dbg_en_peers) #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_EN(u) (((u)->num_dbg_en_peers)++)
#define UPDGRP_PEER_DBG_DIS(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. * Walk all subgroups in an update group.
*/ */
#define UPDGRP_FOREACH_SUBGRP(updgrp, subgrp) \ #define UPDGRP_FOREACH_SUBGRP(updgrp, subgrp) \
LIST_FOREACH(subgrp, &((updgrp)->subgrps), updgrp_train) LIST_FOREACH(subgrp, &((updgrp)->subgrps), updgrp_train)
#define UPDGRP_FOREACH_SUBGRP_SAFE(updgrp, subgrp, tmp_subgrp) \ #define UPDGRP_FOREACH_SUBGRP_SAFE(updgrp, subgrp, tmp_subgrp) \
LIST_FOREACH_SAFE(subgrp, &((updgrp)->subgrps), updgrp_train, tmp_subgrp) LIST_FOREACH_SAFE(subgrp, &((updgrp)->subgrps), updgrp_train, \
tmp_subgrp)
#define SUBGRP_FOREACH_PEER(subgrp, paf) \ #define SUBGRP_FOREACH_PEER(subgrp, paf) \
LIST_FOREACH(paf, &(subgrp->peers), subgrp_train) LIST_FOREACH(paf, &(subgrp->peers), subgrp_train)
#define SUBGRP_FOREACH_PEER_SAFE(subgrp, paf, temp_paf) \ #define SUBGRP_FOREACH_PEER_SAFE(subgrp, paf, temp_paf) \
LIST_FOREACH_SAFE(paf, &(subgrp->peers), subgrp_train, temp_paf) LIST_FOREACH_SAFE(paf, &(subgrp->peers), subgrp_train, temp_paf)
#define SUBGRP_FOREACH_ADJ(subgrp, adj) \ #define SUBGRP_FOREACH_ADJ(subgrp, adj) \
TAILQ_FOREACH(adj, &(subgrp->adjq), subgrp_adj_train) TAILQ_FOREACH(adj, &(subgrp->adjq), subgrp_adj_train)
#define SUBGRP_FOREACH_ADJ_SAFE(subgrp, adj, adj_temp) \ #define SUBGRP_FOREACH_ADJ_SAFE(subgrp, adj, adj_temp) \
TAILQ_FOREACH_SAFE(adj, &(subgrp->adjq), subgrp_adj_train, adj_temp) TAILQ_FOREACH_SAFE(adj, &(subgrp->adjq), subgrp_adj_train, adj_temp)
/* Prototypes. */ /* Prototypes. */
/* bgp_updgrp.c */ /* bgp_updgrp.c */
extern void update_bgp_group_init (struct bgp *); extern void update_bgp_group_init(struct bgp *);
extern void udpate_bgp_group_free (struct bgp *); extern void udpate_bgp_group_free(struct bgp *);
extern void extern void update_group_show(struct bgp *bgp, afi_t afi, safi_t safi,
update_group_show (struct bgp *bgp, afi_t afi, safi_t safi, struct vty *vty, uint64_t subgrp_id); struct vty *vty, uint64_t subgrp_id);
extern void update_group_show_stats (struct bgp *bgp, struct vty *vty); extern void update_group_show_stats(struct bgp *bgp, struct vty *vty);
extern void update_group_adjust_peer (struct peer_af *paf); extern void update_group_adjust_peer(struct peer_af *paf);
extern int update_group_adjust_soloness (struct peer *peer, int set); extern int update_group_adjust_soloness(struct peer *peer, int set);
extern void extern void update_subgroup_remove_peer(struct update_subgroup *,
update_subgroup_remove_peer (struct update_subgroup *, struct peer_af *); struct peer_af *);
extern struct bgp_table *update_subgroup_rib (struct update_subgroup *); extern struct bgp_table *update_subgroup_rib(struct update_subgroup *);
extern void extern void update_subgroup_split_peer(struct peer_af *, struct update_group *);
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 extern int
update_subgroup_check_merge (struct update_subgroup *, const char *); update_group_refresh_default_originate_route_map(struct thread *thread);
extern int extern void update_group_start_advtimer(struct bgp *bgp);
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);
extern void update_subgroup_inherit_info (struct update_subgroup *to, extern void update_subgroup_inherit_info(struct update_subgroup *to,
struct update_subgroup *from); struct update_subgroup *from);
/* bgp_updgrp_packet.c */ /* bgp_updgrp_packet.c */
extern struct bpacket *bpacket_alloc (void); extern struct bpacket *bpacket_alloc(void);
extern void bpacket_free (struct bpacket *pkt); extern void bpacket_free(struct bpacket *pkt);
extern void bpacket_queue_init (struct bpacket_queue *q); extern void bpacket_queue_init(struct bpacket_queue *q);
extern void bpacket_queue_cleanup (struct bpacket_queue *q); extern void bpacket_queue_cleanup(struct bpacket_queue *q);
extern void bpacket_queue_sanity_check (struct bpacket_queue *q); extern void bpacket_queue_sanity_check(struct bpacket_queue *q);
extern struct bpacket *bpacket_queue_add (struct bpacket_queue *q, extern struct bpacket *bpacket_queue_add(struct bpacket_queue *q,
struct stream *s, struct stream *s,
struct bpacket_attr_vec_arr struct bpacket_attr_vec_arr *vecarr);
*vecarr); struct bpacket *bpacket_queue_remove(struct bpacket_queue *q);
struct bpacket *bpacket_queue_remove (struct bpacket_queue *q); extern struct bpacket *bpacket_queue_first(struct bpacket_queue *q);
extern struct bpacket *bpacket_queue_first (struct bpacket_queue *q); struct bpacket *bpacket_queue_last(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_length (struct bpacket_queue *q); unsigned int bpacket_queue_hwm_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);
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_advance_peer (struct peer_af *paf); extern void bpacket_queue_remove_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);
extern void bpacket_add_peer (struct bpacket *pkt, struct peer_af *paf); unsigned int bpacket_queue_virtual_length(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);
extern void bpacket_queue_show_vty (struct bpacket_queue *q, struct vty *vty); int subgroup_packets_to_build(struct update_subgroup *subgrp);
int subgroup_packets_to_build (struct update_subgroup *subgrp); extern struct bpacket *subgroup_update_packet(struct update_subgroup *s);
extern struct bpacket *subgroup_update_packet (struct update_subgroup *s); extern struct bpacket *subgroup_withdraw_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,
extern struct stream *bpacket_reformat_for_peer (struct bpacket *pkt, struct peer_af *paf);
struct peer_af *paf); extern void bpacket_attr_vec_arr_reset(struct bpacket_attr_vec_arr *vecarr);
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,
extern void bpacket_attr_vec_arr_set_vec (struct bpacket_attr_vec_arr *vecarr, bpacket_attr_vec_type type,
bpacket_attr_vec_type type, struct stream *s, struct attr *attr);
struct stream *s, extern void subgroup_default_update_packet(struct update_subgroup *subgrp,
struct attr *attr); struct attr *attr,
extern void struct peer *from);
subgroup_default_update_packet (struct update_subgroup *subgrp, extern void subgroup_default_withdraw_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 */ /* bgp_updgrp_adv.c */
extern struct bgp_advertise *bgp_advertise_clean_subgroup (struct extern struct bgp_advertise *
update_subgroup bgp_advertise_clean_subgroup(struct update_subgroup *subgrp,
*subgrp, struct bgp_adj_out *adj);
struct bgp_adj_out extern void update_group_show_adj_queue(struct bgp *bgp, afi_t afi, safi_t safi,
*adj); struct vty *vty, uint64_t id);
extern void update_group_show_adj_queue (struct bgp *bgp, afi_t afi, extern void update_group_show_advertised(struct bgp *bgp, afi_t afi,
safi_t safi, struct vty *vty, safi_t safi, struct vty *vty,
uint64_t id); uint64_t id);
extern void update_group_show_advertised (struct bgp *bgp, afi_t afi, extern void update_group_show_packet_queue(struct bgp *bgp, afi_t afi,
safi_t safi, struct vty *vty, safi_t safi, struct vty *vty,
uint64_t id); uint64_t id);
extern void update_group_show_packet_queue (struct bgp *bgp, afi_t afi, extern void subgroup_announce_route(struct update_subgroup *subgrp);
safi_t safi, struct vty *vty, extern void subgroup_announce_all(struct update_subgroup *subgrp);
uint64_t id);
extern void subgroup_announce_route (struct update_subgroup *subgrp);
extern void subgroup_announce_all (struct update_subgroup *subgrp);
extern void extern void subgroup_default_originate(struct update_subgroup *subgrp,
subgroup_default_originate (struct update_subgroup *subgrp, int withdraw); int withdraw);
extern void extern void group_announce_route(struct bgp *bgp, afi_t afi, safi_t safi,
group_announce_route (struct bgp *bgp, afi_t afi, safi_t safi, struct bgp_node *rn, struct bgp_info *ri);
struct bgp_node *rn, struct bgp_info *ri); extern void subgroup_clear_table(struct update_subgroup *subgrp);
extern void subgroup_clear_table (struct update_subgroup *subgrp); extern void update_group_announce(struct bgp *bgp);
extern void update_group_announce (struct bgp *bgp); extern void update_group_announce_rrclients(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 void peer_af_announce_route (struct peer_af *paf, int combine); extern struct bgp_adj_out *bgp_adj_out_alloc(struct update_subgroup *subgrp,
extern struct bgp_adj_out *bgp_adj_out_alloc (struct update_subgroup *subgrp, struct bgp_node *rn,
struct bgp_node *rn, u_int32_t addpath_tx_id);
u_int32_t addpath_tx_id); extern void bgp_adj_out_remove_subgroup(struct bgp_node *rn,
extern void bgp_adj_out_remove_subgroup (struct bgp_node *rn, struct bgp_adj_out *adj,
struct bgp_adj_out *adj, struct update_subgroup *subgrp);
struct update_subgroup *subgrp); extern void bgp_adj_out_set_subgroup(struct bgp_node *rn,
extern void struct update_subgroup *subgrp,
bgp_adj_out_set_subgroup (struct bgp_node *rn, struct attr *attr, struct bgp_info *binfo);
struct update_subgroup *subgrp, extern void bgp_adj_out_unset_subgroup(struct bgp_node *rn,
struct attr *attr, struct bgp_info *binfo); struct update_subgroup *subgrp,
extern void char withdraw, u_int32_t addpath_tx_id);
bgp_adj_out_unset_subgroup (struct bgp_node *rn, void subgroup_announce_table(struct update_subgroup *subgrp,
struct update_subgroup *subgrp, struct bgp_table *table);
char withdraw, extern void subgroup_trigger_write(struct update_subgroup *subgrp);
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 extern int update_group_clear_update_dbg(struct update_group *updgrp,
update_group_clear_update_dbg (struct update_group *updgrp, void *arg); void *arg);
extern void update_bgp_group_free(struct bgp *bgp); 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_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, extern int bgp_addpath_tx_path(struct peer *peer, afi_t afi, safi_t safi,
struct bgp_info *ri); struct bgp_info *ri);
/* /*
* Inline functions * 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 * bpacket_queue_is_empty
*/ */
static inline int static inline int bpacket_queue_is_empty(struct bpacket_queue *queue)
bpacket_queue_is_empty (struct bpacket_queue *queue)
{ {
/* /*
* The packet queue is empty if it only contains a sentinel. * The packet queue is empty if it only contains a sentinel.
*/ */
if (queue->curr_count != 1) if (queue->curr_count != 1)
return 0; return 0;
assert (bpacket_queue_first (queue)->buffer == NULL); assert(bpacket_queue_first(queue)->buffer == NULL);
return 1; 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. * Returns the packet after the given packet in a bpacket queue.
*/ */
static inline struct bpacket * static inline struct bpacket *bpacket_next(struct bpacket *pkt)
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. * Adjust all peer_af structures for the given peer.
*/ */
static inline void static inline void update_group_adjust_peer_afs(struct peer *peer)
update_group_adjust_peer_afs (struct peer *peer)
{ {
struct peer_af *paf; struct peer_af *paf;
int afidx; int afidx;
for (afidx = BGP_AF_START; afidx < BGP_AF_MAX; afidx++) for (afidx = BGP_AF_START; afidx < BGP_AF_MAX; afidx++) {
{ paf = peer->peer_af_array[afidx];
paf = peer->peer_af_array[afidx]; if (paf != NULL)
if (paf != NULL) update_group_adjust_peer(paf);
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. * Remove all peer_af structures for the given peer from their subgroups.
*/ */
static inline void static inline void update_group_remove_peer_afs(struct peer *peer)
update_group_remove_peer_afs (struct peer *peer)
{ {
struct peer_af *paf; struct peer_af *paf;
int afidx; int afidx;
for (afidx = BGP_AF_START; afidx < BGP_AF_MAX; afidx++) for (afidx = BGP_AF_START; afidx < BGP_AF_MAX; afidx++) {
{ paf = peer->peer_af_array[afidx];
paf = peer->peer_af_array[afidx]; if (paf != NULL)
if (paf != NULL) update_subgroup_remove_peer(PAF_SUBGRP(paf), paf);
update_subgroup_remove_peer (PAF_SUBGRP (paf), paf); }
}
} }
/* /*
* update_subgroup_needs_refresh * update_subgroup_needs_refresh
*/ */
static inline int 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)) if (CHECK_FLAG(subgrp->flags, SUBGRP_FLAG_NEEDS_REFRESH))
return 1; return 1;
else else
return 0; return 0;
} }
/* /*
* update_subgroup_set_needs_refresh * update_subgroup_set_needs_refresh
*/ */
static inline void 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) if (value)
SET_FLAG (subgrp->flags, SUBGRP_FLAG_NEEDS_REFRESH); SET_FLAG(subgrp->flags, SUBGRP_FLAG_NEEDS_REFRESH);
else else
UNSET_FLAG (subgrp->flags, SUBGRP_FLAG_NEEDS_REFRESH); UNSET_FLAG(subgrp->flags, SUBGRP_FLAG_NEEDS_REFRESH);
} }
static inline struct update_subgroup * static inline struct update_subgroup *peer_subgroup(struct peer *peer,
peer_subgroup (struct peer *peer, afi_t afi, safi_t safi) afi_t afi, safi_t safi)
{ {
struct peer_af *paf; struct peer_af *paf;
paf = peer_af_find (peer, afi, safi); paf = peer_af_find(peer, afi, safi);
if (paf) if (paf)
return PAF_SUBGRP (paf); return PAF_SUBGRP(paf);
return NULL; 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. * Adjust all peer_af structures for the given peer.
*/ */
static inline void static inline void bgp_announce_peer(struct peer *peer)
bgp_announce_peer (struct peer *peer)
{ {
struct peer_af *paf; struct peer_af *paf;
int afidx; int afidx;
for (afidx = BGP_AF_START; afidx < BGP_AF_MAX; afidx++) for (afidx = BGP_AF_START; afidx < BGP_AF_MAX; afidx++) {
{ paf = peer->peer_af_array[afidx];
paf = peer->peer_af_array[afidx]; if (paf != NULL)
if (paf != NULL) subgroup_announce_all(PAF_SUBGRP(paf));
subgroup_announce_all (PAF_SUBGRP (paf)); }
}
} }
/** /**
* advertise_list_is_empty * advertise_list_is_empty
*/ */
static inline int static inline int advertise_list_is_empty(struct update_subgroup *subgrp)
advertise_list_is_empty (struct update_subgroup *subgrp)
{ {
if (!BGP_ADV_FIFO_EMPTY (&subgrp->sync->update) || if (!BGP_ADV_FIFO_EMPTY(&subgrp->sync->update)
!BGP_ADV_FIFO_EMPTY (&subgrp->sync->withdraw) || || !BGP_ADV_FIFO_EMPTY(&subgrp->sync->withdraw)
!BGP_ADV_FIFO_EMPTY (&subgrp->sync->withdraw_low)) || !BGP_ADV_FIFO_EMPTY(&subgrp->sync->withdraw_low)) {
{ return 0;
return 0; }
}
return 1; return 1;
} }
#endif /* _QUAGGA_BGP_UPDGRP_H */ #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

@ -21,20 +21,20 @@
#if ENABLE_BGP_VNC #if ENABLE_BGP_VNC
typedef enum { typedef enum {
BGP_VNC_SUBTLV_TYPE_LIFETIME=1, BGP_VNC_SUBTLV_TYPE_LIFETIME = 1,
BGP_VNC_SUBTLV_TYPE_RFPOPTION=2, /* deprecated */ BGP_VNC_SUBTLV_TYPE_RFPOPTION = 2, /* deprecated */
} bgp_vnc_subtlv_types; } bgp_vnc_subtlv_types;
/* /*
* VNC Attribute subtlvs * VNC Attribute subtlvs
*/ */
struct bgp_vnc_subtlv_lifetime { struct bgp_vnc_subtlv_lifetime {
uint32_t lifetime; uint32_t lifetime;
}; };
struct bgp_vnc_subtlv_unaddr { 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 */ #endif /* _QUAGGA_BGP_VNC_TYPES_H */

View File

@ -30,171 +30,221 @@
#include "bgpd/bgp_mplsvpn.h" #include "bgpd/bgp_mplsvpn.h"
#include "bgpd/bgp_vpn.h" #include "bgpd/bgp_vpn.h"
int int show_adj_route_vpn(struct vty *vty, struct peer *peer,
show_adj_route_vpn (struct vty *vty, struct peer *peer, struct prefix_rd *prd, struct prefix_rd *prd, afi_t afi, safi_t safi,
afi_t afi, safi_t safi, u_char use_json) u_char use_json)
{ {
struct bgp *bgp; struct bgp *bgp;
struct bgp_table *table; struct bgp_table *table;
struct bgp_node *rn; struct bgp_node *rn;
struct bgp_node *rm; struct bgp_node *rm;
struct attr *attr; struct attr *attr;
int rd_header; int rd_header;
int header = 1; int header = 1;
json_object *json = NULL; json_object *json = NULL;
json_object *json_scode = NULL; json_object *json_scode = NULL;
json_object *json_ocode = NULL; json_object *json_ocode = NULL;
json_object *json_routes = NULL; json_object *json_routes = NULL;
json_object *json_array = NULL; json_object *json_array = NULL;
bgp = bgp_get_default (); bgp = bgp_get_default();
if (bgp == NULL) if (bgp == NULL) {
{ if (!use_json)
if (!use_json) vty_out(vty, "No BGP process is configured\n");
vty_outln (vty, "No BGP process is configured"); return CMD_WARNING;
return CMD_WARNING; }
}
if (use_json) if (use_json) {
{ json_scode = json_object_new_object();
json_scode = json_object_new_object(); json_ocode = json_object_new_object();
json_ocode = json_object_new_object(); json_routes = json_object_new_object();
json_routes = json_object_new_object(); json = json_object_new_object();
json = json_object_new_object();
json_object_string_add(json_scode, "suppressed", "s"); json_object_string_add(json_scode, "suppressed", "s");
json_object_string_add(json_scode, "damped", "d"); json_object_string_add(json_scode, "damped", "d");
json_object_string_add(json_scode, "history", "h"); json_object_string_add(json_scode, "history", "h");
json_object_string_add(json_scode, "valid", "*"); json_object_string_add(json_scode, "valid", "*");
json_object_string_add(json_scode, "best", ">"); json_object_string_add(json_scode, "best", ">");
json_object_string_add(json_scode, "internal", "i"); json_object_string_add(json_scode, "internal", "i");
json_object_string_add(json_ocode, "igp", "i"); json_object_string_add(json_ocode, "igp", "i");
json_object_string_add(json_ocode, "egp", "e"); json_object_string_add(json_ocode, "egp", "e");
json_object_string_add(json_ocode, "incomplete", "?"); json_object_string_add(json_ocode, "incomplete", "?");
} }
for (rn = bgp_table_top (bgp->rib[afi][SAFI_MPLS_VPN]); rn; for (rn = bgp_table_top(bgp->rib[afi][SAFI_MPLS_VPN]); rn;
rn = bgp_route_next (rn)) rn = bgp_route_next(rn)) {
{ if (prd && memcmp(rn->p.u.val, prd->val, 8) != 0)
if (prd && memcmp (rn->p.u.val, prd->val, 8) != 0) continue;
continue;
if ((table = rn->info) != NULL) if ((table = rn->info) != NULL) {
{ if (use_json)
if (use_json) json_array = json_object_new_array();
json_array = json_object_new_array(); else
else json_array = NULL;
json_array = NULL;
rd_header = 1; rd_header = 1;
for (rm = bgp_table_top (table); rm; rm = bgp_route_next (rm)) for (rm = bgp_table_top(table); rm;
{ rm = bgp_route_next(rm)) {
if ((attr = rm->info) != NULL) if ((attr = rm->info) != NULL) {
{ if (header) {
if (header) if (use_json) {
{ json_object_int_add(
if (use_json) json,
{ "bgpTableVersion",
json_object_int_add(json, "bgpTableVersion", 0); 0);
json_object_string_add(json, "bgpLocalRouterId", inet_ntoa (bgp->router_id)); json_object_string_add(
json_object_object_add(json, "bgpStatusCodes", json_scode); json,
json_object_object_add(json, "bgpOriginCodes", json_ocode); "bgpLocalRouterId",
} inet_ntoa(
else bgp->router_id));
{ json_object_object_add(
vty_outln (vty, "BGP table version is 0, local router ID is %s", json,
inet_ntoa(bgp->router_id)); "bgpStatusCodes",
vty_outln (vty, json_scode);
"Status codes: s suppressed, d damped, h history, * valid, > best, i - internal"); json_object_object_add(
vty_outln (vty, "Origin codes: i - IGP, e - EGP, ? - incomplete%s", json,
VTYNL); "bgpOriginCodes",
vty_outln (vty, V4_HEADER); json_ocode);
} } else {
header = 0; 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) if (rd_header) {
{ u_int16_t type;
u_int16_t type; struct rd_as rd_as;
struct rd_as rd_as; struct rd_ip rd_ip = {0};
struct rd_ip rd_ip = {0};
#if ENABLE_BGP_VNC #if ENABLE_BGP_VNC
struct rd_vnc_eth rd_vnc_eth = {0}; struct rd_vnc_eth rd_vnc_eth = {
0};
#endif #endif
u_char *pnt; u_char *pnt;
pnt = rn->p.u.val; pnt = rn->p.u.val;
/* Decode RD type. */ /* Decode RD type. */
type = decode_rd_type (pnt); type = decode_rd_type(pnt);
/* Decode RD value. */ /* Decode RD value. */
if (type == RD_TYPE_AS) if (type == RD_TYPE_AS)
decode_rd_as (pnt + 2, &rd_as); decode_rd_as(pnt + 2,
else if (type == RD_TYPE_AS4) &rd_as);
decode_rd_as4 (pnt + 2, &rd_as); else if (type == RD_TYPE_AS4)
else if (type == RD_TYPE_IP) decode_rd_as4(pnt + 2,
decode_rd_ip (pnt + 2, &rd_ip); &rd_as);
else if (type == RD_TYPE_IP)
decode_rd_ip(pnt + 2,
&rd_ip);
#if ENABLE_BGP_VNC #if ENABLE_BGP_VNC
else if (type == RD_TYPE_VNC_ETH) else if (type
decode_rd_vnc_eth (pnt, &rd_vnc_eth); == RD_TYPE_VNC_ETH)
decode_rd_vnc_eth(
pnt,
&rd_vnc_eth);
#endif #endif
if (use_json) if (use_json) {
{ char buffer[BUFSIZ];
char buffer[BUFSIZ]; if (type == RD_TYPE_AS
if (type == RD_TYPE_AS || type == RD_TYPE_AS4) || type == RD_TYPE_AS4)
sprintf (buffer, "%u:%d", rd_as.as, rd_as.val); sprintf(buffer,
else if (type == RD_TYPE_IP) "%u:%d",
sprintf (buffer, "%s:%d", inet_ntoa (rd_ip.ip), rd_ip.val); rd_as.as,
json_object_string_add(json_routes, "routeDistinguisher", buffer); rd_as.val);
} else if (type
else == RD_TYPE_IP)
{ sprintf(buffer,
vty_out (vty, "Route Distinguisher: "); "%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) if (type == RD_TYPE_AS
vty_out (vty, "%u:%d", rd_as.as, rd_as.val); || type == RD_TYPE_AS4)
else if (type == RD_TYPE_IP) vty_out(vty,
vty_out (vty, "%s:%d", inet_ntoa (rd_ip.ip), rd_ip.val); "%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 #if ENABLE_BGP_VNC
else if (type == RD_TYPE_VNC_ETH) else if (
vty_out (vty, "%u:%02x:%02x:%02x:%02x:%02x:%02x", type
rd_vnc_eth.local_nve_id, == RD_TYPE_VNC_ETH)
rd_vnc_eth.macaddr.octet[0], vty_out(vty,
rd_vnc_eth.macaddr.octet[1], "%u:%02x:%02x:%02x:%02x:%02x:%02x",
rd_vnc_eth.macaddr.octet[2], rd_vnc_eth
rd_vnc_eth.macaddr.octet[3], .local_nve_id,
rd_vnc_eth.macaddr.octet[4], rd_vnc_eth
rd_vnc_eth.macaddr.octet[5]); .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 #endif
vty_out (vty, VTYNL); vty_out(vty, "\n");
} }
rd_header = 0; rd_header = 0;
} }
route_vty_out_tmp (vty, &rm->p, attr, SAFI_MPLS_VPN, use_json, json_array); route_vty_out_tmp(vty, &rm->p, attr,
} SAFI_MPLS_VPN,
} use_json, json_array);
if (use_json) }
{ }
struct prefix *p; if (use_json) {
char buf_a[BUFSIZ]; struct prefix *p;
char buf_b[BUFSIZ]; char buf_a[BUFSIZ];
p = &rm->p; char buf_b[BUFSIZ];
sprintf(buf_a, "%s/%d", inet_ntop (p->family, &p->u.prefix, buf_b, BUFSIZ), p->prefixlen); p = &rm->p;
json_object_object_add(json_routes, buf_a, json_array); sprintf(buf_a, "%s/%d",
} inet_ntop(p->family, &p->u.prefix,
} buf_b, BUFSIZ),
} p->prefixlen);
if (use_json) json_object_object_add(json_routes, buf_a,
{ json_array);
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); if (use_json) {
} json_object_object_add(json, "routes", json_routes);
return CMD_SUCCESS; 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> #include <zebra.h>
extern int extern int show_adj_route_vpn(struct vty *vty, struct peer *peer,
show_adj_route_vpn (struct vty *vty, struct peer *peer, struct prefix_rd *prd, struct prefix_rd *prd, afi_t afi, safi_t safi,
afi_t afi, safi_t safi, u_char use_json); u_char use_json);
#endif /* _QUAGGA_BGP_VPN_H */ #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_CMD_STR "<ipv4|ipv6>"
#define BGP_AFI_HELP_STR "Address Family\nAddress Family\n" #define BGP_AFI_HELP_STR "Address Family\nAddress Family\n"
#define BGP_SAFI_CMD_STR "<unicast|multicast|vpn|labeled-unicast>" #define BGP_SAFI_CMD_STR "<unicast|multicast|vpn>"
#define BGP_SAFI_HELP_STR \ #define BGP_SAFI_HELP_STR \
"Address Family modifier\n" \ "Address Family modifier\n" \
"Address Family modifier\n" \ "Address Family modifier\n" \
"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_CMD_STR BGP_AFI_CMD_STR" "BGP_SAFI_CMD_STR
#define BGP_AFI_SAFI_HELP_STR BGP_AFI_HELP_STR BGP_SAFI_HELP_STR #define BGP_AFI_SAFI_HELP_STR BGP_AFI_HELP_STR BGP_SAFI_HELP_STR
extern void bgp_vty_init (void); #define BGP_SAFI_WITH_LABEL_CMD_STR "<unicast|multicast|vpn|labeled-unicast>"
extern const char *afi_safi_print (afi_t, safi_t); #define BGP_SAFI_WITH_LABEL_HELP_STR \
extern const char *afi_safi_json (afi_t, safi_t); "Address Family modifier\n" \
extern int bgp_config_write_update_delay (struct vty *, struct bgp *); "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_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_listen(struct vty *vty, struct bgp *bgp);
extern int bgp_config_write_coalesce_time(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 int bgp_vty_return(struct vty *vty, int ret);
extern struct peer * extern struct peer *peer_and_group_lookup_vty(struct vty *vty,
peer_and_group_lookup_vty (struct vty *vty, const char *peer_str); const char *peer_str);
extern afi_t extern afi_t bgp_vty_afi_from_str(const char *afi_str);
bgp_vty_afi_from_str(const char *afi_str);
extern safi_t extern safi_t bgp_vty_safi_from_str(const char *safi_str);
bgp_vty_safi_from_str(const char *safi_str);
extern int extern int argv_find_and_parse_afi(struct cmd_token **argv, int argc,
argv_find_and_parse_afi(struct cmd_token **argv, int argc, int *index, afi_t *afi); int *index, afi_t *afi);
extern int extern int argv_find_and_parse_safi(struct cmd_token **argv, int argc,
argv_find_and_parse_safi(struct cmd_token **argv, int argc, int *index, safi_t *safi); int *index, safi_t *safi);
extern int extern int bgp_vty_find_and_parse_afi_safi_bgp(struct vty *vty,
bgp_vty_find_and_parse_afi_safi_bgp (struct vty *vty, struct cmd_token **argv, int argc, int *idx, struct cmd_token **argv,
afi_t *afi, safi_t *safi, struct bgp **bgp); 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 */ #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 #ifndef _QUAGGA_BGP_ZEBRA_H
#define _QUAGGA_BGP_ZEBRA_H #define _QUAGGA_BGP_ZEBRA_H
#define BGP_NEXTHOP_BUF_SIZE (8 * sizeof (struct in_addr *)) extern void bgp_zebra_init(struct thread_master *master);
#define BGP_IFINDICES_BUF_SIZE (8 * sizeof (unsigned int)) extern void bgp_zebra_destroy(void);
#define BGP_LABEL_BUF_SIZE (8 * sizeof (unsigned int)) 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 void bgp_zebra_initiate_radv(struct bgp *bgp, struct peer *peer);
extern struct stream *bgp_ifindices_buf; extern void bgp_zebra_terminate_radv(struct bgp *bgp, struct peer *peer);
extern struct stream *bgp_label_buf;
extern void bgp_zebra_init (struct thread_master *master); extern void bgp_zebra_instance_register(struct bgp *);
extern void bgp_zebra_destroy (void); extern void bgp_zebra_instance_deregister(struct bgp *);
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_initiate_radv (struct bgp *bgp, struct peer *peer); extern struct bgp_redist *bgp_redist_lookup(struct bgp *, afi_t, u_char,
extern void bgp_zebra_terminate_radv (struct bgp *bgp, struct peer *peer); 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 struct interface *if_lookup_by_ipv4(struct in_addr *, vrf_id_t);
extern void bgp_zebra_instance_deregister (struct bgp *); 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 int bgp_zebra_advertise_all_vni(struct bgp *, int);
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_num_connects(void); extern int bgp_zebra_num_connects(void);

12194
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

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

File diff suppressed because it is too large Load Diff

View File

@ -32,138 +32,127 @@
#include "bgpd/bgp_encap_types.h" #include "bgpd/bgp_encap_types.h"
/* probably ought to have a field-specific define in config.h */ /* probably ought to have a field-specific define in config.h */
# ifndef s6_addr32 /* for solaris/bsd */ #ifndef s6_addr32 /* for solaris/bsd */
# ifdef SOLARIS_IPV6 #ifdef SOLARIS_IPV6
# define s6_addr32 _S6_un._S6_u32 # define s6_addr32 _S6_un._S6_u32
# else #else
# define s6_addr32 __u6_addr.__u6_addr32 # define s6_addr32 __u6_addr.__u6_addr32
# endif #endif
# endif #endif
#define RFAPI_V4_ADDR 0x04 #define RFAPI_V4_ADDR 0x04
#define RFAPI_V6_ADDR 0x06 #define RFAPI_V6_ADDR 0x06
#define RFAPI_SHOW_STR "VNC information\n" #define RFAPI_SHOW_STR "VNC information\n"
struct rfapi_ip_addr struct rfapi_ip_addr {
{ uint8_t addr_family; /* AF_INET | AF_INET6 */
uint8_t addr_family; /* AF_INET | AF_INET6 */ union {
union struct in_addr v4; /* in network order */
{ struct in6_addr v6; /* in network order */
struct in_addr v4; /* in network order */ } addr;
struct in6_addr v6; /* in network order */
} addr;
}; };
struct rfapi_ip_prefix struct rfapi_ip_prefix {
{ uint8_t length;
uint8_t length; uint8_t cost; /* bgp local pref = 255 - cost */
uint8_t cost; /* bgp local pref = 255 - cost */ struct rfapi_ip_addr prefix;
struct rfapi_ip_addr prefix;
}; };
struct rfapi_nexthop struct rfapi_nexthop {
{ struct prefix addr;
struct prefix addr; uint8_t cost;
uint8_t cost;
}; };
struct rfapi_next_hop_entry struct rfapi_next_hop_entry {
{ struct rfapi_next_hop_entry *next;
struct rfapi_next_hop_entry *next; struct rfapi_ip_prefix prefix;
struct rfapi_ip_prefix prefix; uint32_t lifetime;
uint32_t lifetime; struct rfapi_ip_addr un_address;
struct rfapi_ip_addr un_address; struct rfapi_ip_addr vn_address;
struct rfapi_ip_addr vn_address; struct rfapi_vn_option *vn_options;
struct rfapi_vn_option *vn_options; struct rfapi_un_option *un_options;
struct rfapi_un_option *un_options;
}; };
#define RFAPI_REMOVE_RESPONSE_LIFETIME 0 #define RFAPI_REMOVE_RESPONSE_LIFETIME 0
#define RFAPI_INFINITE_LIFETIME 0xFFFFFFFF #define RFAPI_INFINITE_LIFETIME 0xFFFFFFFF
struct rfapi_l2address_option struct rfapi_l2address_option {
{ struct ethaddr macaddr; /* use 0 to assign label to IP prefix */
struct ethaddr macaddr; /* use 0 to assign label to IP prefix */ uint32_t label; /* 20bit label in low bits, no TC, S, or TTL */
uint32_t label; /* 20bit label in low bits, no TC, S, or TTL */ uint32_t logical_net_id; /* ~= EVPN Ethernet Segment Id,
uint32_t logical_net_id; /* ~= EVPN Ethernet Segment Id, must not be zero for mac regis. */
must not be zero for mac regis. */ uint8_t local_nve_id;
uint8_t local_nve_id; uint16_t tag_id; /* EVPN Ethernet Tag ID, 0 = none */
uint16_t tag_id; /* EVPN Ethernet Tag ID, 0 = none */
}; };
typedef enum typedef enum {
{ RFAPI_UN_OPTION_TYPE_PROVISIONAL, /* internal use only */
RFAPI_UN_OPTION_TYPE_PROVISIONAL, /* internal use only */ RFAPI_UN_OPTION_TYPE_TUNNELTYPE,
RFAPI_UN_OPTION_TYPE_TUNNELTYPE,
} rfapi_un_option_type; } rfapi_un_option_type;
struct rfapi_tunneltype_option struct rfapi_tunneltype_option {
{ bgp_encap_types type;
bgp_encap_types type; union {
union struct bgp_encap_type_reserved reserved;
{ struct bgp_encap_type_l2tpv3_over_ip l2tpv3_ip;
struct bgp_encap_type_reserved reserved; struct bgp_encap_type_gre gre;
struct bgp_encap_type_l2tpv3_over_ip l2tpv3_ip; struct bgp_encap_type_transmit_tunnel_endpoint
struct bgp_encap_type_gre gre; transmit_tunnel_endpoint;
struct bgp_encap_type_transmit_tunnel_endpoint transmit_tunnel_endpoint; struct bgp_encap_type_ipsec_in_tunnel_mode ipsec_tunnel;
struct bgp_encap_type_ipsec_in_tunnel_mode ipsec_tunnel; struct bgp_encap_type_ip_in_ip_tunnel_with_ipsec_transport_mode
struct bgp_encap_type_ip_in_ip_tunnel_with_ipsec_transport_mode ip_ipsec; ip_ipsec;
struct bgp_encap_type_mpls_in_ip_tunnel_with_ipsec_transport_mode mpls_ipsec; struct bgp_encap_type_mpls_in_ip_tunnel_with_ipsec_transport_mode
struct bgp_encap_type_ip_in_ip ip_ip; mpls_ipsec;
struct bgp_encap_type_vxlan vxlan; struct bgp_encap_type_ip_in_ip ip_ip;
struct bgp_encap_type_nvgre nvgre; struct bgp_encap_type_vxlan vxlan;
struct bgp_encap_type_mpls mpls; struct bgp_encap_type_nvgre nvgre;
struct bgp_encap_type_mpls_in_gre mpls_gre; struct bgp_encap_type_mpls mpls;
struct bgp_encap_type_vxlan_gpe vxlan_gpe; struct bgp_encap_type_mpls_in_gre mpls_gre;
struct bgp_encap_type_mpls_in_udp mpls_udp; struct bgp_encap_type_vxlan_gpe vxlan_gpe;
struct bgp_encap_type_pbb pbb; struct bgp_encap_type_mpls_in_udp mpls_udp;
} bgpinfo; struct bgp_encap_type_pbb pbb;
} bgpinfo;
}; };
struct rfapi_un_option struct rfapi_un_option {
{ struct rfapi_un_option *next;
struct rfapi_un_option *next; rfapi_un_option_type type;
rfapi_un_option_type type; union {
union struct rfapi_tunneltype_option tunnel;
{ } v;
struct rfapi_tunneltype_option tunnel;
} v;
}; };
typedef enum typedef enum {
{ RFAPI_VN_OPTION_TYPE_L2ADDR =
RFAPI_VN_OPTION_TYPE_L2ADDR = 3, /* Layer 2 address, 3 for legacy compatibility */ 3, /* Layer 2 address, 3 for legacy compatibility */
RFAPI_VN_OPTION_TYPE_LOCAL_NEXTHOP, /* for static routes */ RFAPI_VN_OPTION_TYPE_LOCAL_NEXTHOP, /* for static routes */
RFAPI_VN_OPTION_TYPE_INTERNAL_RD, /* internal use only */ RFAPI_VN_OPTION_TYPE_INTERNAL_RD, /* internal use only */
} rfapi_vn_option_type; } rfapi_vn_option_type;
struct rfapi_vn_option struct rfapi_vn_option {
{ struct rfapi_vn_option *next;
struct rfapi_vn_option *next;
rfapi_vn_option_type type; rfapi_vn_option_type type;
union union {
{ struct rfapi_l2address_option l2addr;
struct rfapi_l2address_option l2addr;
/* /*
* If this option is present, the next hop is local to the * If this option is present, the next hop is local to the
* client NVE (i.e., not via a tunnel). * client NVE (i.e., not via a tunnel).
*/ */
struct rfapi_nexthop local_nexthop; struct rfapi_nexthop local_nexthop;
/* /*
* For rfapi internal use only * For rfapi internal use only
*/ */
struct prefix_rd internal_rd; struct prefix_rd internal_rd;
} v; } v;
}; };
struct rfapi_l2address_option_match struct rfapi_l2address_option_match {
{ struct rfapi_l2address_option o;
struct rfapi_l2address_option o; uint32_t flags;
uint32_t flags;
#define RFAPI_L2O_MACADDR 0x00000001 #define RFAPI_L2O_MACADDR 0x00000001
#define RFAPI_L2O_LABEL 0x00000002 #define RFAPI_L2O_LABEL 0x00000002
@ -211,8 +200,8 @@ typedef void *rfapi_handle;
* rfapi_open() * rfapi_open()
* *
*------------------------------------------*/ *------------------------------------------*/
typedef void (rfapi_response_cb_t) (struct rfapi_next_hop_entry * next_hops, typedef void(rfapi_response_cb_t)(struct rfapi_next_hop_entry *next_hops,
void *userdata); void *userdata);
/*------------------------------------------ /*------------------------------------------
* rfapi_nve_close_cb_t (callback typedef) * rfapi_nve_close_cb_t (callback typedef)
@ -228,7 +217,7 @@ typedef void (rfapi_response_cb_t) (struct rfapi_next_hop_entry * next_hops,
* ESTALE handle invalidated by configuration change * ESTALE handle invalidated by configuration change
* *
*------------------------------------------*/ *------------------------------------------*/
typedef void (rfapi_nve_close_cb_t) (rfapi_handle pHandle, int reason); typedef void(rfapi_nve_close_cb_t)(rfapi_handle pHandle, int reason);
/*------------------------------------------ /*------------------------------------------
* rfp_cfg_write_cb_t (callback typedef) * rfp_cfg_write_cb_t (callback typedef)
@ -247,7 +236,7 @@ typedef void (rfapi_nve_close_cb_t) (rfapi_handle pHandle, int reason);
* return value: * return value:
* lines written * lines written
--------------------------------------------*/ --------------------------------------------*/
typedef int (rfp_cfg_write_cb_t) (struct vty * vty, void *rfp_start_val); typedef int(rfp_cfg_write_cb_t)(struct vty *vty, void *rfp_start_val);
/*------------------------------------------ /*------------------------------------------
* rfp_cfg_group_write_cb_t (callback typedef) * rfp_cfg_group_write_cb_t (callback typedef)
@ -269,31 +258,26 @@ typedef int (rfp_cfg_write_cb_t) (struct vty * vty, void *rfp_start_val);
* return value: * return value:
* lines written * lines written
--------------------------------------------*/ --------------------------------------------*/
typedef enum typedef enum {
{ RFAPI_RFP_CFG_GROUP_DEFAULT,
RFAPI_RFP_CFG_GROUP_DEFAULT, RFAPI_RFP_CFG_GROUP_NVE,
RFAPI_RFP_CFG_GROUP_NVE, RFAPI_RFP_CFG_GROUP_L2
RFAPI_RFP_CFG_GROUP_L2
} rfapi_rfp_cfg_group_type; } rfapi_rfp_cfg_group_type;
typedef int (rfp_cfg_group_write_cb_t) (struct vty * vty, typedef int(rfp_cfg_group_write_cb_t)(struct vty *vty, void *rfp_start_val,
void *rfp_start_val, rfapi_rfp_cfg_group_type type,
rfapi_rfp_cfg_group_type type, const char *name, void *rfp_cfg_group);
const char *name,
void *rfp_cfg_group);
/*********************************************************************** /***********************************************************************
* Configuration related defines and structures * Configuration related defines and structures
***********************************************************************/ ***********************************************************************/
struct rfapi_rfp_cb_methods struct rfapi_rfp_cb_methods {
{ rfp_cfg_write_cb_t *cfg_cb; /* show top level config */
rfp_cfg_write_cb_t *cfg_cb; /* show top level config */ rfp_cfg_group_write_cb_t *cfg_group_cb; /* show group level config */
rfp_cfg_group_write_cb_t *cfg_group_cb; /* show group level config */ rfapi_response_cb_t *response_cb; /* unsolicited responses */
rfapi_response_cb_t *response_cb; /* unsolicited responses */ rfapi_response_cb_t *local_cb; /* local route add/delete */
rfapi_response_cb_t *local_cb; /* local route add/delete */ rfapi_nve_close_cb_t *close_cb; /* handle closed */
rfapi_nve_close_cb_t *close_cb; /* handle closed */
}; };
/* /*
@ -319,35 +303,33 @@ struct rfapi_rfp_cb_methods
* rfapi_query. When partial table download is used, only * rfapi_query. When partial table download is used, only
* information matching a query is passed. * information matching a query is passed.
*/ */
typedef enum typedef enum {
{ RFAPI_RFP_DOWNLOAD_PARTIAL = 0,
RFAPI_RFP_DOWNLOAD_PARTIAL = 0, RFAPI_RFP_DOWNLOAD_FULL
RFAPI_RFP_DOWNLOAD_FULL
} rfapi_rfp_download_type; } rfapi_rfp_download_type;
#define RFAPI_RFP_CFG_DEFAULT_FTD_ADVERTISEMENT_INTERVAL 1 #define RFAPI_RFP_CFG_DEFAULT_FTD_ADVERTISEMENT_INTERVAL 1
struct rfapi_rfp_cfg struct rfapi_rfp_cfg {
{ /* partial or full table download */
/* partial or full table download */ rfapi_rfp_download_type download_type; /* default=partial */
rfapi_rfp_download_type download_type; /* default=partial */ /*
/* * When full-table-download is enabled, this is the minimum
* When full-table-download is enabled, this is the minimum * number of seconds between times a non-queried prefix will
* number of seconds between times a non-queried prefix will * be updated to a particular NVE.
* be updated to a particular NVE. * default: RFAPI_RFP_CFG_DEFAULT_FTD_ADVERTISEMENT_INTERVAL
* default: RFAPI_RFP_CFG_DEFAULT_FTD_ADVERTISEMENT_INTERVAL */
*/ uint32_t ftd_advertisement_interval;
uint32_t ftd_advertisement_interval; /*
/* * percentage of registration lifetime to continue to use information
* percentage of registration lifetime to continue to use information * post soft-state refresh timeout
* post soft-state refresh timeout default: RFAPI_RFP_CFG_DEFAULT_HOLDDOWN_FACTOR
default: RFAPI_RFP_CFG_DEFAULT_HOLDDOWN_FACTOR */
*/ uint32_t holddown_factor;
uint32_t holddown_factor; /* Control generation of updated RFP responses */
/* Control generation of updated RFP responses */ uint8_t use_updated_response; /* default=0/no */
uint8_t use_updated_response; /* default=0/no */ /* when use_updated_response, also generate remove responses */
/* when use_updated_response, also generate remove responses */ uint8_t use_removes; /* default=0/no */
uint8_t use_removes; /* default=0/no */
}; };
/*********************************************************************** /***********************************************************************
@ -370,11 +352,9 @@ struct rfapi_rfp_cfg
* return value: * return value:
* rfp_start_val rfp returned value passed on rfp_stop and other rfapi calls * rfp_start_val rfp returned value passed on rfp_stop and other rfapi calls
--------------------------------------------*/ --------------------------------------------*/
extern void * extern void *rfp_start(struct thread_master *master,
rfp_start ( struct rfapi_rfp_cfg **cfgp,
struct thread_master *master, struct rfapi_rfp_cb_methods **cbmp);
struct rfapi_rfp_cfg **cfgp,
struct rfapi_rfp_cb_methods **cbmp);
/*------------------------------------------ /*------------------------------------------
* rfp_stop * rfp_stop
@ -389,8 +369,7 @@ rfp_start (
* *
* return value: * return value:
--------------------------------------------*/ --------------------------------------------*/
extern void extern void rfp_stop(void *rfp_start_val);
rfp_stop (void *rfp_start_val);
/*********************************************************************** /***********************************************************************
* RFP processing behavior configuration * RFP processing behavior configuration
@ -413,10 +392,8 @@ rfp_stop (void *rfp_start_val);
* 0 Success * 0 Success
* ENXIO Unabled to locate configured BGP/VNC * ENXIO Unabled to locate configured BGP/VNC
--------------------------------------------*/ --------------------------------------------*/
extern int extern int rfapi_rfp_set_configuration(void *rfp_start_val,
rfapi_rfp_set_configuration ( struct rfapi_rfp_cfg *rfp_cfg);
void *rfp_start_val,
struct rfapi_rfp_cfg *rfp_cfg);
/*------------------------------------------ /*------------------------------------------
* rfapi_rfp_set_cb_methods * rfapi_rfp_set_cb_methods
@ -433,10 +410,8 @@ rfapi_rfp_set_configuration (
* 0 Success * 0 Success
* ENXIO BGP or VNC not configured * ENXIO BGP or VNC not configured
*------------------------------------------*/ *------------------------------------------*/
extern int extern int rfapi_rfp_set_cb_methods(void *rfp_start_val,
rfapi_rfp_set_cb_methods ( struct rfapi_rfp_cb_methods *methods);
void *rfp_start_val,
struct rfapi_rfp_cb_methods *methods);
/*********************************************************************** /***********************************************************************
* RFP group specific configuration * RFP group specific configuration
@ -463,12 +438,10 @@ rfapi_rfp_set_cb_methods (
* return value: * return value:
* rfp_cfg_group NULL or Pointer to configuration structure * rfp_cfg_group NULL or Pointer to configuration structure
--------------------------------------------*/ --------------------------------------------*/
extern void * extern void *rfapi_rfp_init_group_config_ptr_vty(void *rfp_start_val,
rfapi_rfp_init_group_config_ptr_vty ( rfapi_rfp_cfg_group_type type,
void *rfp_start_val, struct vty *vty,
rfapi_rfp_cfg_group_type type, uint32_t size);
struct vty *vty,
uint32_t size);
/*------------------------------------------ /*------------------------------------------
* rfapi_rfp_get_group_config_ptr_vty * rfapi_rfp_get_group_config_ptr_vty
@ -489,11 +462,9 @@ rfapi_rfp_init_group_config_ptr_vty (
* return value: * return value:
* rfp_cfg_group Pointer to configuration structure * rfp_cfg_group Pointer to configuration structure
--------------------------------------------*/ --------------------------------------------*/
extern void * extern void *rfapi_rfp_get_group_config_ptr_vty(void *rfp_start_val,
rfapi_rfp_get_group_config_ptr_vty ( rfapi_rfp_cfg_group_type type,
void *rfp_start_val, struct vty *vty);
rfapi_rfp_cfg_group_type type,
struct vty *vty);
/*------------------------------------------ /*------------------------------------------
* rfp_group_config_search_cb_t (callback typedef) * rfp_group_config_search_cb_t (callback typedef)
@ -512,8 +483,7 @@ rfapi_rfp_get_group_config_ptr_vty (
* 0 Match/Success * 0 Match/Success
* ENOENT No matching * ENOENT No matching
--------------------------------------------*/ --------------------------------------------*/
typedef int (rfp_group_config_search_cb_t) (void *criteria, typedef int(rfp_group_config_search_cb_t)(void *criteria, void *rfp_cfg_group);
void *rfp_cfg_group);
/*------------------------------------------ /*------------------------------------------
* rfapi_rfp_get_group_config_ptr_name * rfapi_rfp_get_group_config_ptr_name
@ -536,13 +506,9 @@ typedef int (rfp_group_config_search_cb_t) (void *criteria,
* return value: * return value:
* rfp_cfg_group Pointer to configuration structure * rfp_cfg_group Pointer to configuration structure
--------------------------------------------*/ --------------------------------------------*/
extern void * extern void *rfapi_rfp_get_group_config_ptr_name(
rfapi_rfp_get_group_config_ptr_name ( void *rfp_start_val, rfapi_rfp_cfg_group_type type, const char *name,
void *rfp_start_val, void *criteria, rfp_group_config_search_cb_t *search_cb);
rfapi_rfp_cfg_group_type type,
const char *name,
void *criteria,
rfp_group_config_search_cb_t *search_cb);
/*------------------------------------------ /*------------------------------------------
* rfapi_rfp_get_l2_group_config_ptr_lni * rfapi_rfp_get_l2_group_config_ptr_lni
@ -565,11 +531,9 @@ rfapi_rfp_get_group_config_ptr_name (
* rfp_cfg_group Pointer to configuration structure * rfp_cfg_group Pointer to configuration structure
--------------------------------------------*/ --------------------------------------------*/
extern void * extern void *
rfapi_rfp_get_l2_group_config_ptr_lni ( rfapi_rfp_get_l2_group_config_ptr_lni(void *rfp_start_val,
void *rfp_start_val, uint32_t logical_net_id, void *criteria,
uint32_t logical_net_id, rfp_group_config_search_cb_t *search_cb);
void *criteria,
rfp_group_config_search_cb_t *search_cb);
/*********************************************************************** /***********************************************************************
* NVE Sessions * NVE Sessions
@ -615,15 +579,11 @@ rfapi_rfp_get_l2_group_config_ptr_lni (
* but underlay network address is not IPv4 * but underlay network address is not IPv4
* EDEADLK Called from within a callback procedure * EDEADLK Called from within a callback procedure
*------------------------------------------*/ *------------------------------------------*/
extern int extern int rfapi_open(void *rfp_start_val, struct rfapi_ip_addr *vn,
rfapi_open ( struct rfapi_ip_addr *un,
void *rfp_start_val, struct rfapi_un_option *default_options,
struct rfapi_ip_addr *vn, uint32_t *response_lifetime, void *userdata,
struct rfapi_ip_addr *un, rfapi_handle *pHandle);
struct rfapi_un_option *default_options,
uint32_t *response_lifetime,
void *userdata,
rfapi_handle *pHandle);
/*------------------------------------------ /*------------------------------------------
@ -643,8 +603,7 @@ rfapi_open (
* EBADF invalid handle * EBADF invalid handle
* ENXIO BGP or VNC not configured * ENXIO BGP or VNC not configured
*------------------------------------------*/ *------------------------------------------*/
extern int extern int rfapi_close(rfapi_handle rfd);
rfapi_close (rfapi_handle rfd);
/*------------------------------------------ /*------------------------------------------
* rfapi_check * rfapi_check
@ -664,8 +623,7 @@ rfapi_close (rfapi_handle rfd);
* ENXIO BGP or VNC not configured * ENXIO BGP or VNC not configured
* EAFNOSUPPORT Internal addressing error * EAFNOSUPPORT Internal addressing error
*------------------------------------------*/ *------------------------------------------*/
extern int extern int rfapi_check(rfapi_handle rfd);
rfapi_check (rfapi_handle rfd);
/*********************************************************************** /***********************************************************************
* NVE Routes * NVE Routes
@ -701,12 +659,9 @@ rfapi_check (rfapi_handle rfd);
* ESTALE descriptor is no longer usable; should be closed * ESTALE descriptor is no longer usable; should be closed
* EDEADLK Called from within a callback procedure * EDEADLK Called from within a callback procedure
--------------------------------------------*/ --------------------------------------------*/
extern int extern int rfapi_query(rfapi_handle rfd, struct rfapi_ip_addr *target,
rfapi_query ( struct rfapi_l2address_option *l2o,
rfapi_handle rfd, struct rfapi_next_hop_entry **ppNextHopEntry);
struct rfapi_ip_addr *target,
struct rfapi_l2address_option *l2o,
struct rfapi_next_hop_entry **ppNextHopEntry);
/*------------------------------------------ /*------------------------------------------
* rfapi_query_done * rfapi_query_done
@ -728,8 +683,7 @@ rfapi_query (
* ESTALE descriptor is no longer usable; should be closed * ESTALE descriptor is no longer usable; should be closed
* EDEADLK Called from within a callback procedure * EDEADLK Called from within a callback procedure
--------------------------------------------*/ --------------------------------------------*/
extern int extern int rfapi_query_done(rfapi_handle rfd, struct rfapi_ip_addr *target);
rfapi_query_done (rfapi_handle rfd, struct rfapi_ip_addr *target);
/*------------------------------------------ /*------------------------------------------
* rfapi_query_done_all * rfapi_query_done_all
@ -750,8 +704,7 @@ rfapi_query_done (rfapi_handle rfd, struct rfapi_ip_addr *target);
* ESTALE descriptor is no longer usable; should be closed * ESTALE descriptor is no longer usable; should be closed
* EDEADLK Called from within a callback procedure * EDEADLK Called from within a callback procedure
--------------------------------------------*/ --------------------------------------------*/
extern int extern int rfapi_query_done_all(rfapi_handle rfd, int *count);
rfapi_query_done_all (rfapi_handle rfd, int *count);
/*------------------------------------------ /*------------------------------------------
* rfapi_register * rfapi_register
@ -785,21 +738,16 @@ rfapi_query_done_all (rfapi_handle rfd, int *count);
* EDEADLK Called from within a callback procedure * EDEADLK Called from within a callback procedure
--------------------------------------------*/ --------------------------------------------*/
typedef enum typedef enum {
{ RFAPI_REGISTER_ADD,
RFAPI_REGISTER_ADD, RFAPI_REGISTER_WITHDRAW,
RFAPI_REGISTER_WITHDRAW, RFAPI_REGISTER_KILL
RFAPI_REGISTER_KILL
} rfapi_register_action; } rfapi_register_action;
extern int extern int rfapi_register(rfapi_handle rfd, struct rfapi_ip_prefix *prefix,
rfapi_register ( uint32_t lifetime, struct rfapi_un_option *options_un,
rfapi_handle rfd, struct rfapi_vn_option *options_vn,
struct rfapi_ip_prefix *prefix, rfapi_register_action action);
uint32_t lifetime,
struct rfapi_un_option *options_un,
struct rfapi_vn_option *options_vn,
rfapi_register_action action);
/*********************************************************************** /***********************************************************************
* Helper / Utility functions * Helper / Utility functions
@ -818,8 +766,7 @@ rfapi_register (
* return value: * return value:
* vn NVE virtual network address * vn NVE virtual network address
*------------------------------------------*/ *------------------------------------------*/
extern struct rfapi_ip_addr * extern struct rfapi_ip_addr *rfapi_get_vn_addr(void *);
rfapi_get_vn_addr (void *);
/*------------------------------------------ /*------------------------------------------
* rfapi_get_un_addr * rfapi_get_un_addr
@ -834,8 +781,7 @@ rfapi_get_vn_addr (void *);
* return value: * return value:
* un NVE underlay network address * un NVE underlay network address
*------------------------------------------*/ *------------------------------------------*/
extern struct rfapi_ip_addr * extern struct rfapi_ip_addr *rfapi_get_un_addr(void *);
rfapi_get_un_addr (void *);
/*------------------------------------------ /*------------------------------------------
* rfapi_error_str * rfapi_error_str
@ -850,8 +796,7 @@ rfapi_get_un_addr (void *);
* *
* const char * String * const char * String
*------------------------------------------*/ *------------------------------------------*/
extern const char * extern const char *rfapi_error_str(int code);
rfapi_error_str (int code);
/*------------------------------------------ /*------------------------------------------
* rfapi_get_rfp_start_val * rfapi_get_rfp_start_val
@ -864,8 +809,7 @@ rfapi_error_str (int code);
* returns: * returns:
* void * * void *
*------------------------------------------*/ *------------------------------------------*/
extern void * extern void *rfapi_get_rfp_start_val(void *bgpv);
rfapi_get_rfp_start_val (void *bgpv);
/*------------------------------------------ /*------------------------------------------
* rfapi_compare_rfds * rfapi_compare_rfds
@ -882,8 +826,7 @@ rfapi_get_rfp_start_val (void *bgpv);
* 0 Mismatch * 0 Mismatch
* 1 Match * 1 Match
*------------------------------------------*/ *------------------------------------------*/
extern int extern int rfapi_compare_rfds(void *rfd1, void *rfd2);
rfapi_compare_rfds (void *rfd1, void *rfd2);
/*------------------------------------------ /*------------------------------------------
* rfapi_free_next_hop_list * rfapi_free_next_hop_list
@ -898,8 +841,7 @@ rfapi_compare_rfds (void *rfd1, void *rfd2);
* *
* return value: None * return value: None
--------------------------------------------*/ --------------------------------------------*/
extern void extern void rfapi_free_next_hop_list(struct rfapi_next_hop_entry *list);
rfapi_free_next_hop_list (struct rfapi_next_hop_entry *list);
/*------------------------------------------ /*------------------------------------------
* rfapi_get_response_lifetime_default * rfapi_get_response_lifetime_default
@ -915,8 +857,7 @@ rfapi_free_next_hop_list (struct rfapi_next_hop_entry *list);
* *
* return value: The bgp instance default lifetime for a response. * return value: The bgp instance default lifetime for a response.
--------------------------------------------*/ --------------------------------------------*/
extern int extern int rfapi_get_response_lifetime_default(void *rfp_start_val);
rfapi_get_response_lifetime_default (void *rfp_start_val);
/*------------------------------------------ /*------------------------------------------
* rfapi_is_vnc_configured * rfapi_is_vnc_configured
@ -933,8 +874,7 @@ rfapi_get_response_lifetime_default (void *rfp_start_val);
* 0 Success * 0 Success
* ENXIO VNC not configured * ENXIO VNC not configured
--------------------------------------------*/ --------------------------------------------*/
extern int extern int rfapi_is_vnc_configured(void *rfp_start_val);
rfapi_is_vnc_configured (void *rfp_start_val);
/*------------------------------------------ /*------------------------------------------
* rfapi_bgp_lookup_by_rfp * rfapi_bgp_lookup_by_rfp
@ -953,8 +893,7 @@ rfapi_is_vnc_configured (void *rfp_start_val);
* NULL = not found * NULL = not found
* *
--------------------------------------------*/ --------------------------------------------*/
extern struct bgp * extern struct bgp *rfapi_bgp_lookup_by_rfp(void *rfp_start_val);
rfapi_bgp_lookup_by_rfp (void *rfp_start_val);
/*------------------------------------------ /*------------------------------------------
* rfapi_get_rfp_start_val_by_bgp * rfapi_get_rfp_start_val_by_bgp
@ -972,8 +911,7 @@ rfapi_bgp_lookup_by_rfp (void *rfp_start_val);
* NULL = not found * NULL = not found
* *
--------------------------------------------*/ --------------------------------------------*/
extern void * extern void *rfapi_get_rfp_start_val_by_bgp(struct bgp *bgp);
rfapi_get_rfp_start_val_by_bgp (struct bgp *bgp);
#endif /* ENABLE_BGP_VNC */ #endif /* ENABLE_BGP_VNC */

View File

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

View File

@ -56,44 +56,30 @@
#include "rfapi_rib.h" #include "rfapi_rib.h"
extern void extern void rfapiApInit(struct rfapi_advertised_prefixes *ap);
rfapiApInit (struct rfapi_advertised_prefixes *ap);
extern void extern void rfapiApRelease(struct rfapi_advertised_prefixes *ap);
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 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 rfapiApDelete(struct bgp *bgp, struct rfapi_descriptor *rfd,
extern int struct prefix *pfx_ip, struct prefix *pfx_eth,
rfapiApCountAll (struct bgp *bgp); struct prefix_rd *prd,
int *advertise_tunnel); /* out */
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 */
#endif /* _QUAGGA_BGP_RFAPI_AP_H */ #endif /* _QUAGGA_BGP_RFAPI_AP_H */

View File

@ -26,56 +26,44 @@
#include "bgpd/bgp_route.h" #include "bgpd/bgp_route.h"
#include "bgpd/bgp_nexthop.h" #include "bgpd/bgp_nexthop.h"
extern void rfapi_init (void); extern void rfapi_init(void);
extern void vnc_zebra_init (struct thread_master *master); extern void vnc_zebra_init(struct thread_master *master);
extern void vnc_zebra_destroy (void); 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); struct rfapi *bgp_rfapi_new(struct bgp *bgp);
void bgp_rfapi_destroy (struct bgp *bgp, struct rfapi *h); void bgp_rfapi_destroy(struct bgp *bgp, struct rfapi *h);
extern void extern void rfapiProcessUpdate(struct peer *peer, void *rfd, struct prefix *p,
rfapiProcessUpdate (struct peer *peer, struct prefix_rd *prd, struct attr *attr,
void *rfd, afi_t afi, safi_t safi, u_char type,
struct prefix *p, u_char sub_type, uint32_t *label);
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 extern void rfapiProcessWithdraw(struct peer *peer, void *rfd, struct prefix *p,
rfapiProcessWithdraw (struct peer *peer, struct prefix_rd *prd, struct attr *attr,
void *rfd, afi_t afi, safi_t safi, u_char type, int kill);
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 extern void vnc_zebra_announce(struct prefix *p, struct bgp_info *new_select,
vnc_zebra_announce (struct prefix *p, struct bgp *bgp);
struct bgp_info *new_select, struct bgp *bgp);
extern void extern void vnc_zebra_withdraw(struct prefix *p, struct bgp_info *old_select);
vnc_zebra_withdraw (struct prefix *p, struct bgp_info *old_select);
extern void extern void rfapi_vty_out_vncinfo(struct vty *vty, struct prefix *p,
rfapi_vty_out_vncinfo (struct vty *vty, struct bgp_info *bi, safi_t safi);
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 */ #endif /* ENABLE_BGP_VNC */

View File

@ -36,15 +36,14 @@
#include "bgpd/rfapi/vnc_debug.h" #include "bgpd/rfapi/vnc_debug.h"
void * void *rfapi_create_generic(struct rfapi_ip_addr *vn, struct rfapi_ip_addr *un)
rfapi_create_generic (struct rfapi_ip_addr *vn, struct rfapi_ip_addr *un)
{ {
struct rfapi_descriptor *rfd; struct rfapi_descriptor *rfd;
rfd = XCALLOC (MTYPE_RFAPI_DESC, sizeof (struct rfapi_descriptor)); rfd = XCALLOC(MTYPE_RFAPI_DESC, sizeof(struct rfapi_descriptor));
vnc_zlog_debug_verbose ("%s: rfd=%p", __func__, rfd); vnc_zlog_debug_verbose("%s: rfd=%p", __func__, rfd);
rfd->vn_addr = *vn; rfd->vn_addr = *vn;
rfd->un_addr = *un; rfd->un_addr = *un;
return (void *) rfd; return (void *)rfd;
} }
/*------------------------------------------ /*------------------------------------------
@ -60,12 +59,11 @@ rfapi_create_generic (struct rfapi_ip_addr *vn, struct rfapi_ip_addr *un)
* return value: * return value:
* *
*------------------------------------------*/ *------------------------------------------*/
void void rfapi_free_generic(void *grfd)
rfapi_free_generic (void *grfd)
{ {
struct rfapi_descriptor *rfd; struct rfapi_descriptor *rfd;
rfd = (struct rfapi_descriptor *) grfd; rfd = (struct rfapi_descriptor *)grfd;
XFREE (MTYPE_RFAPI_DESC, rfd); XFREE(MTYPE_RFAPI_DESC, rfd);
} }
@ -84,48 +82,45 @@ rfapi_free_generic (void *grfd)
* 0 Mismatch * 0 Mismatch
* 1 Match * 1 Match
*------------------------------------------*/ *------------------------------------------*/
int int rfapi_compare_rfds(void *rfd1, void *rfd2)
rfapi_compare_rfds (void *rfd1, void *rfd2)
{ {
struct rfapi_descriptor *rrfd1, *rrfd2; struct rfapi_descriptor *rrfd1, *rrfd2;
int match = 0; int match = 0;
rrfd1 = (struct rfapi_descriptor *) rfd1; rrfd1 = (struct rfapi_descriptor *)rfd1;
rrfd2 = (struct rfapi_descriptor *) rfd2; rrfd2 = (struct rfapi_descriptor *)rfd2;
if (rrfd1->vn_addr.addr_family == rrfd2->vn_addr.addr_family) if (rrfd1->vn_addr.addr_family == rrfd2->vn_addr.addr_family) {
{ if (rrfd1->vn_addr.addr_family == AF_INET)
if (rrfd1->vn_addr.addr_family == AF_INET) match = IPV4_ADDR_SAME(&(rrfd1->vn_addr.addr.v4),
match = IPV4_ADDR_SAME (&(rrfd1->vn_addr.addr.v4), &(rrfd2->vn_addr.addr.v4));
&(rrfd2->vn_addr.addr.v4)); else
else match = IPV6_ADDR_SAME(&(rrfd1->vn_addr.addr.v6),
match = IPV6_ADDR_SAME (&(rrfd1->vn_addr.addr.v6), &(rrfd2->vn_addr.addr.v6));
&(rrfd2->vn_addr.addr.v6)); }
}
/* /*
* If the VN addresses don't match in all forms, * If the VN addresses don't match in all forms,
* give up. * give up.
*/ */
if (!match) if (!match)
return 0; return 0;
/* /*
* do the process again for the UN addresses. * do the process again for the UN addresses.
*/ */
match = 0; match = 0;
if (rrfd1->un_addr.addr_family == rrfd2->un_addr.addr_family) if (rrfd1->un_addr.addr_family == rrfd2->un_addr.addr_family) {
{ /* VN addresses match
/* VN addresses match * UN address families match
* UN address families match * now check the actual UN addresses
* now check the actual UN addresses */
*/ if (rrfd1->un_addr.addr_family == AF_INET)
if (rrfd1->un_addr.addr_family == AF_INET) match = IPV4_ADDR_SAME(&(rrfd1->un_addr.addr.v4),
match = IPV4_ADDR_SAME (&(rrfd1->un_addr.addr.v4), &(rrfd2->un_addr.addr.v4));
&(rrfd2->un_addr.addr.v4)); else
else match = IPV6_ADDR_SAME(&(rrfd1->un_addr.addr.v6),
match = IPV6_ADDR_SAME (&(rrfd1->un_addr.addr.v6), &(rrfd2->un_addr.addr.v6));
&(rrfd2->un_addr.addr.v6)); }
} return match;
return match;
} }

View File

@ -19,8 +19,8 @@
*/ */
extern void *rfapi_create_generic (struct rfapi_ip_addr *vn, extern void *rfapi_create_generic(struct rfapi_ip_addr *vn,
struct rfapi_ip_addr *un); struct rfapi_ip_addr *un);
/*------------------------------------------ /*------------------------------------------
* rfapi_free_generic * rfapi_free_generic
@ -35,4 +35,4 @@ extern void *rfapi_create_generic (struct rfapi_ip_addr *vn,
* 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