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,21 +43,18 @@
/* 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;
@ -67,16 +64,14 @@ baa_hash_alloc (void *p)
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;
@ -87,23 +82,21 @@ baa_hash_cmp (const void *p1, const void *p2)
/* 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(
adv->binfo); /* bgp_advertise bgp_info reference */
XFREE(MTYPE_BGP_ADVERTISE, adv); 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;
@ -112,8 +105,7 @@ bgp_advertise_add (struct bgp_advertise_attr *baa,
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)
@ -124,8 +116,8 @@ bgp_advertise_delete (struct bgp_advertise_attr *baa,
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;
@ -137,18 +129,15 @@ bgp_advertise_intern (struct hash *hash, struct attr *attr)
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); hash_release(hash, baa);
bgp_attr_unintern(&baa->attr); bgp_attr_unintern(&baa->attr);
} }
@ -156,8 +145,7 @@ bgp_advertise_unintern (struct hash *hash, struct bgp_advertise_attr *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;
@ -168,19 +156,19 @@ bgp_adj_out_lookup (struct peer *peer, struct bgp_node *rn,
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
* this
* peer and if an addpath_tx_id was specified */ * peer and if an addpath_tx_id was specified */
if (addpath_capable && addpath_tx_id && adj->addpath_tx_id != addpath_tx_id) if (addpath_capable && addpath_tx_id
&& adj->addpath_tx_id != addpath_tx_id)
continue; 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));
} }
@ -188,18 +176,14 @@ bgp_adj_out_lookup (struct peer *peer, struct bgp_node *rn,
} }
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) {
{
if (adj->attr != attr)
{
bgp_attr_unintern(&adj->attr); bgp_attr_unintern(&adj->attr);
adj->attr = bgp_attr_intern(attr); adj->attr = bgp_attr_intern(attr);
} }
@ -214,8 +198,7 @@ bgp_adj_in_set (struct bgp_node *rn, struct peer *peer, struct attr *attr,
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);
@ -223,8 +206,7 @@ bgp_adj_in_remove (struct bgp_node *rn, struct bgp_adj_in *bai)
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;
@ -235,12 +217,10 @@ bgp_adj_in_unset (struct bgp_node *rn, struct peer *peer,
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);
} }
@ -251,37 +231,35 @@ bgp_adj_in_unset (struct bgp_node *rn, struct peer *peer,
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] = hash_create (baa_hash_key, baa_hash_cmp, NULL); peer->hash[afi][safi] =
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, peer->sync[afi][safi]); XFREE(MTYPE_BGP_SYNCHRONISE,
peer->sync[afi][safi]);
peer->sync[afi][safi] = NULL; peer->sync[afi][safi] = NULL;
if (peer->hash[afi][safi]) if (peer->hash[afi][safi])

View File

@ -26,16 +26,14 @@
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;
@ -46,8 +44,7 @@ struct bgp_advertise_attr
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;
@ -69,8 +66,7 @@ struct bgp_advertise
}; };
/* 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;
@ -94,8 +90,7 @@ struct bgp_adj_out
}; };
/* 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;
@ -111,8 +106,7 @@ struct bgp_adj_in
}; };
/* 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;
@ -161,19 +155,22 @@ struct bgp_synchronize
(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 *,
u_int32_t);
extern int bgp_adj_in_unset(struct bgp_node *, struct peer *, u_int32_t); extern int bgp_adj_in_unset(struct bgp_node *, struct peer *, u_int32_t);
extern void bgp_adj_in_remove(struct bgp_node *, struct bgp_adj_in *); extern void bgp_adj_in_remove(struct bgp_node *, struct bgp_adj_in *);
@ -185,13 +182,12 @@ 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 extern void bgp_advertise_unintern(struct hash *hash,
bgp_advertise_unintern (struct hash *hash, struct bgp_advertise_attr *baa); 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

@ -44,12 +44,11 @@
#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;
@ -57,8 +56,7 @@ struct assegment
}; };
/* 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;
@ -98,7 +96,8 @@ 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 *,
const char *);
extern void aspath_print_all_vty(struct vty *); extern void aspath_print_all_vty(struct vty *);
extern unsigned int aspath_key_make(void *); extern unsigned int aspath_key_make(void *);
extern unsigned int aspath_get_first_as(struct aspath *); extern unsigned int aspath_get_first_as(struct aspath *);
@ -106,8 +105,11 @@ extern unsigned int aspath_get_last_as (struct aspath *);
extern int aspath_loop_check(struct aspath *, as_t); extern int aspath_loop_check(struct aspath *, as_t);
extern int aspath_private_as_check(struct aspath *); extern int aspath_private_as_check(struct aspath *);
extern int aspath_single_asn_check(struct aspath *, as_t asn); extern int aspath_single_asn_check(struct aspath *, as_t asn);
extern struct aspath *aspath_replace_specific_asn (struct aspath *aspath, as_t target_asn, as_t our_asn); extern struct aspath *aspath_replace_specific_asn(struct aspath *aspath,
extern struct aspath *aspath_replace_private_asns(struct aspath *aspath, as_t asn); as_t target_asn,
as_t our_asn);
extern struct aspath *aspath_replace_private_asns(struct aspath *aspath,
as_t asn);
extern struct aspath *aspath_remove_private_asns(struct aspath *aspath); extern struct aspath *aspath_remove_private_asns(struct aspath *aspath);
extern int aspath_firstas_check(struct aspath *, as_t); extern int aspath_firstas_check(struct aspath *, as_t);
extern int aspath_confed_check(struct aspath *); extern int aspath_confed_check(struct aspath *);

File diff suppressed because it is too large Load Diff

View File

@ -21,6 +21,7 @@
#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. */
@ -34,7 +35,6 @@
#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)
@ -91,18 +91,38 @@ struct bgp_tea_options {
#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. /* BGP core attribute structure. */
* lazily allocated as and when a struct attr struct attr {
* requires it. /* AS Path structure */
*/ struct aspath *aspath;
struct attr_extra
{ /* Community structure */
struct community *community;
/* Reference count of this attribute. */
unsigned long refcnt;
/* Flag of attribute is set or not. */
uint64_t flag;
/* Apart from in6_addr, the remaining static attributes */
struct in_addr nexthop;
u_int32_t med;
u_int32_t local_pref;
ifindex_t nh_ifindex;
/* Path origin attribute */
u_char origin;
/* has the route-map changed any attribute?
Used on the peer outbound side. */
u_int32_t rmap_change_flags;
/* Multi-Protocol Nexthop, AFI IPv6 */ /* Multi-Protocol Nexthop, AFI IPv6 */
struct in6_addr mp_nexthop_global; struct in6_addr mp_nexthop_global;
struct in6_addr mp_nexthop_local; struct in6_addr mp_nexthop_local;
@ -139,12 +159,18 @@ struct attr_extra
/* MP Nexthop preference */ /* MP Nexthop preference */
u_char mp_nexthop_prefer_global; u_char mp_nexthop_prefer_global;
/* Static MAC for EVPN */
u_char sticky;
/* route tag */ /* route tag */
route_tag_t tag; route_tag_t tag;
/* Label index */ /* Label index */
u_int32_t label_index; u_int32_t label_index;
/* MPLS label */
mpls_label_t label;
uint16_t encap_tunneltype; /* grr */ uint16_t encap_tunneltype; /* grr */
struct bgp_attr_encap_subtlv *encap_subtlvs; /* rfc5512 */ struct bgp_attr_encap_subtlv *encap_subtlvs; /* rfc5512 */
@ -153,38 +179,9 @@ struct attr_extra
#endif #endif
/* EVPN */ /* EVPN */
struct overlay_index evpn_overlay; struct overlay_index evpn_overlay;
};
/* BGP core attribute structure. */ /* EVPN MAC Mobility sequence number, if any. */
struct attr u_int32_t mm_seqnum;
{
/* AS Path structure */
struct aspath *aspath;
/* Community structure */
struct community *community;
/* Lazily allocated pointer to extra attributes */
struct attr_extra *extra;
/* Reference count of this attribute. */
unsigned long refcnt;
/* Flag of attribute is set or not. */
uint64_t flag;
/* Apart from in6_addr, the remaining static attributes */
struct in_addr nexthop;
u_int32_t med;
u_int32_t local_pref;
ifindex_t nh_ifindex;
/* Path origin attribute */
u_char origin;
/* has the route-map changed any attribute?
Used on the peer outbound side. */
u_int32_t rmap_change_flags;
}; };
/* rmap_change_flags definition */ /* rmap_change_flags definition */
@ -197,16 +194,14 @@ 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;
@ -215,15 +210,17 @@ struct transit
#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;
@ -235,8 +232,6 @@ 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_extra_free (struct attr *);
extern void bgp_attr_dup(struct attr *, struct attr *); extern void bgp_attr_dup(struct attr *, struct attr *);
extern void bgp_attr_deep_dup(struct attr *, struct attr *); extern void bgp_attr_deep_dup(struct attr *, struct attr *);
extern void bgp_attr_deep_free(struct attr *); extern void bgp_attr_deep_free(struct attr *);
@ -248,13 +243,14 @@ extern void bgp_attr_flush (struct attr *);
extern struct attr *bgp_attr_default_set(struct attr *attr, u_char); extern struct attr *bgp_attr_default_set(struct attr *attr, u_char);
extern struct attr *bgp_attr_aggregate_intern(struct bgp *, u_char, extern struct attr *bgp_attr_aggregate_intern(struct bgp *, u_char,
struct aspath *, struct aspath *,
struct community *, int as_set, 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 *,
u_char *, int, u_int32_t); mpls_label_t *, 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 *);
@ -288,8 +284,7 @@ extern int bgp_mp_unreach_parse (struct bgp_attr_parser_args *args,
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.
@ -303,9 +298,8 @@ extern size_t bgp_packet_mpattr_start(struct stream *s, struct peer *peer,
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);
@ -313,20 +307,30 @@ 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 *,
int, u_int32_t, struct attr *);
extern void bgp_packet_mpunreach_end(struct stream *s, size_t attrlen_pnt); 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->extra->ecommunity) if (!attr->ecommunity)
attr->extra->ecommunity = ecommunity_new(); attr->ecommunity = ecommunity_new();
ecommunity_add_val(attr->extra->ecommunity, &routermac_ecom); ecommunity_add_val(attr->ecommunity, &routermac_ecom);
ecommunity_str (attr->extra->ecommunity); ecommunity_str(attr->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,17 +171,17 @@ 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;
} }

View File

@ -28,10 +28,12 @@
#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);
extern u_int32_t bgp_attr_mac_mobility_seqnum(struct attr *attr,
u_char *sticky);
#endif /* _QUAGGA_BGP_ATTR_EVPN_H */ #endif /* _QUAGGA_BGP_ATTR_EVPN_H */

View File

@ -43,11 +43,11 @@
extern struct zclient *zclient; extern struct zclient *zclient;
/* /*
* bgp_bfd_peer_group2peer_copy - Copy the BFD information from peer group template * bgp_bfd_peer_group2peer_copy - Copy the BFD information from peer group
* template
* to peer. * to peer.
*/ */
void void bgp_bfd_peer_group2peer_copy(struct peer *conf, struct peer *peer)
bgp_bfd_peer_group2peer_copy(struct peer *conf, struct peer *peer)
{ {
struct bfd_info *bfd_info; struct bfd_info *bfd_info;
struct bfd_info *conf_bfd_info; struct bfd_info *conf_bfd_info;
@ -69,10 +69,10 @@ bgp_bfd_peer_group2peer_copy(struct peer *conf, struct peer *peer)
} }
/* /*
* bgp_bfd_is_peer_multihop - returns whether BFD peer is multi-hop or single hop. * bgp_bfd_is_peer_multihop - returns whether BFD peer is multi-hop or single
* hop.
*/ */
int int bgp_bfd_is_peer_multihop(struct peer *peer)
bgp_bfd_is_peer_multihop(struct peer *peer)
{ {
struct bfd_info *bfd_info; struct bfd_info *bfd_info;
@ -81,9 +81,9 @@ bgp_bfd_is_peer_multihop(struct peer *peer)
if (!bfd_info) if (!bfd_info)
return 0; return 0;
if((bfd_info->type == BFD_TYPE_MULTIHOP) || if ((bfd_info->type == BFD_TYPE_MULTIHOP)
((peer->sort == BGP_PEER_IBGP) && !peer->shared_network) || || ((peer->sort == BGP_PEER_IBGP) && !peer->shared_network)
is_ebgp_multihop_configured(peer)) || is_ebgp_multihop_configured(peer))
return 1; return 1;
else else
return 0; return 0;
@ -93,8 +93,7 @@ bgp_bfd_is_peer_multihop(struct peer *peer)
* bgp_bfd_peer_sendmsg - Format and send a Peer register/Unregister * bgp_bfd_peer_sendmsg - Format and send a Peer register/Unregister
* command to Zebra to be forwarded to BFD * command to Zebra to be forwarded to BFD
*/ */
static void static void bgp_bfd_peer_sendmsg(struct peer *peer, int command)
bgp_bfd_peer_sendmsg (struct peer *peer, int command)
{ {
struct bfd_info *bfd_info; struct bfd_info *bfd_info;
vrf_id_t vrf_id = VRF_DEFAULT; vrf_id_t vrf_id = VRF_DEFAULT;
@ -105,28 +104,27 @@ bgp_bfd_peer_sendmsg (struct peer *peer, int command)
if (peer->bgp && (peer->bgp->inst_type == BGP_INSTANCE_TYPE_VRF)) if (peer->bgp && (peer->bgp->inst_type == BGP_INSTANCE_TYPE_VRF))
vrf_id = peer->bgp->vrf_id; vrf_id = peer->bgp->vrf_id;
if (command == ZEBRA_BFD_DEST_DEREGISTER) if (command == ZEBRA_BFD_DEST_DEREGISTER) {
{ multihop =
multihop = CHECK_FLAG(bfd_info->flags, BFD_FLAG_BFD_TYPE_MULTIHOP); CHECK_FLAG(bfd_info->flags, BFD_FLAG_BFD_TYPE_MULTIHOP);
UNSET_FLAG(bfd_info->flags, BFD_FLAG_BFD_TYPE_MULTIHOP); UNSET_FLAG(bfd_info->flags, BFD_FLAG_BFD_TYPE_MULTIHOP);
} } else {
else
{
multihop = bgp_bfd_is_peer_multihop(peer); multihop = bgp_bfd_is_peer_multihop(peer);
if ((command == ZEBRA_BFD_DEST_REGISTER) && multihop) if ((command == ZEBRA_BFD_DEST_REGISTER) && multihop)
SET_FLAG(bfd_info->flags, BFD_FLAG_BFD_TYPE_MULTIHOP); SET_FLAG(bfd_info->flags, BFD_FLAG_BFD_TYPE_MULTIHOP);
} }
if (peer->su.sa.sa_family == AF_INET) if (peer->su.sa.sa_family == AF_INET)
bfd_peer_sendmsg (zclient, bfd_info, AF_INET, bfd_peer_sendmsg(
&peer->su.sin.sin_addr, zclient, bfd_info, AF_INET, &peer->su.sin.sin_addr,
(peer->su_local) ? &peer->su_local->sin.sin_addr : NULL, (peer->su_local) ? &peer->su_local->sin.sin_addr : NULL,
(peer->nexthop.ifp) ? peer->nexthop.ifp->name : NULL, (peer->nexthop.ifp) ? peer->nexthop.ifp->name : NULL,
peer->ttl, multihop, command, 1, vrf_id); peer->ttl, multihop, command, 1, vrf_id);
else if (peer->su.sa.sa_family == AF_INET6) else if (peer->su.sa.sa_family == AF_INET6)
bfd_peer_sendmsg (zclient, bfd_info, AF_INET6, bfd_peer_sendmsg(
&peer->su.sin6.sin6_addr, zclient, bfd_info, AF_INET6, &peer->su.sin6.sin6_addr,
(peer->su_local) ? &peer->su_local->sin6.sin6_addr : NULL, (peer->su_local) ? &peer->su_local->sin6.sin6_addr
: NULL,
(peer->nexthop.ifp) ? peer->nexthop.ifp->name : NULL, (peer->nexthop.ifp) ? peer->nexthop.ifp->name : NULL,
peer->ttl, multihop, command, 1, vrf_id); peer->ttl, multihop, command, 1, vrf_id);
} }
@ -135,8 +133,7 @@ bgp_bfd_peer_sendmsg (struct peer *peer, int command)
* bgp_bfd_register_peer - register a peer with BFD through zebra * bgp_bfd_register_peer - register a peer with BFD through zebra
* for monitoring the peer rechahability. * for monitoring the peer rechahability.
*/ */
void void bgp_bfd_register_peer(struct peer *peer)
bgp_bfd_register_peer (struct peer *peer)
{ {
struct bfd_info *bfd_info; struct bfd_info *bfd_info;
@ -144,7 +141,8 @@ bgp_bfd_register_peer (struct peer *peer)
return; return;
bfd_info = (struct bfd_info *)peer->bfd_info; bfd_info = (struct bfd_info *)peer->bfd_info;
/* Check if BFD is enabled and peer has already been registered with BFD */ /* Check if BFD is enabled and peer has already been registered with BFD
*/
if (CHECK_FLAG(bfd_info->flags, BFD_FLAG_BFD_REG)) if (CHECK_FLAG(bfd_info->flags, BFD_FLAG_BFD_REG))
return; return;
@ -156,8 +154,7 @@ bgp_bfd_register_peer (struct peer *peer)
* for stopping the monitoring of the peer * for stopping the monitoring of the peer
* rechahability. * rechahability.
*/ */
void void bgp_bfd_deregister_peer(struct peer *peer)
bgp_bfd_deregister_peer (struct peer *peer)
{ {
struct bfd_info *bfd_info; struct bfd_info *bfd_info;
@ -179,8 +176,7 @@ bgp_bfd_deregister_peer (struct peer *peer)
* bgp_bfd_update_peer - update peer with BFD with new BFD paramters * bgp_bfd_update_peer - update peer with BFD with new BFD paramters
* through zebra. * through zebra.
*/ */
static void static void bgp_bfd_update_peer(struct peer *peer)
bgp_bfd_update_peer (struct peer *peer)
{ {
struct bfd_info *bfd_info; struct bfd_info *bfd_info;
@ -198,8 +194,7 @@ bgp_bfd_update_peer (struct peer *peer)
/* /*
* bgp_bfd_update_type - update session type with BFD through zebra. * bgp_bfd_update_type - update session type with BFD through zebra.
*/ */
static void static void bgp_bfd_update_type(struct peer *peer)
bgp_bfd_update_type (struct peer *peer)
{ {
struct bfd_info *bfd_info; struct bfd_info *bfd_info;
int multihop; int multihop;
@ -212,23 +207,23 @@ bgp_bfd_update_type (struct peer *peer)
if (!CHECK_FLAG(bfd_info->flags, BFD_FLAG_BFD_REG)) if (!CHECK_FLAG(bfd_info->flags, BFD_FLAG_BFD_REG))
return; return;
if (bfd_info->type == BFD_TYPE_NOT_CONFIGURED) if (bfd_info->type == BFD_TYPE_NOT_CONFIGURED) {
{
multihop = bgp_bfd_is_peer_multihop(peer); multihop = bgp_bfd_is_peer_multihop(peer);
if ((multihop && !CHECK_FLAG(bfd_info->flags, BFD_FLAG_BFD_TYPE_MULTIHOP)) || if ((multihop
(!multihop && CHECK_FLAG(bfd_info->flags, BFD_FLAG_BFD_TYPE_MULTIHOP))) && !CHECK_FLAG(bfd_info->flags,
{ BFD_FLAG_BFD_TYPE_MULTIHOP))
|| (!multihop && CHECK_FLAG(bfd_info->flags,
BFD_FLAG_BFD_TYPE_MULTIHOP))) {
bgp_bfd_peer_sendmsg(peer, ZEBRA_BFD_DEST_DEREGISTER); bgp_bfd_peer_sendmsg(peer, ZEBRA_BFD_DEST_DEREGISTER);
bgp_bfd_peer_sendmsg(peer, ZEBRA_BFD_DEST_REGISTER); bgp_bfd_peer_sendmsg(peer, ZEBRA_BFD_DEST_REGISTER);
} }
} } else {
else if ((bfd_info->type == BFD_TYPE_MULTIHOP
{ && !CHECK_FLAG(bfd_info->flags,
if ((bfd_info->type == BFD_TYPE_MULTIHOP && BFD_FLAG_BFD_TYPE_MULTIHOP))
!CHECK_FLAG(bfd_info->flags, BFD_FLAG_BFD_TYPE_MULTIHOP)) || || (bfd_info->type == BFD_TYPE_SINGLEHOP
(bfd_info->type == BFD_TYPE_SINGLEHOP && && CHECK_FLAG(bfd_info->flags,
CHECK_FLAG(bfd_info->flags, BFD_FLAG_BFD_TYPE_MULTIHOP))) BFD_FLAG_BFD_TYPE_MULTIHOP))) {
{
bgp_bfd_peer_sendmsg(peer, ZEBRA_BFD_DEST_DEREGISTER); bgp_bfd_peer_sendmsg(peer, ZEBRA_BFD_DEST_DEREGISTER);
bgp_bfd_peer_sendmsg(peer, ZEBRA_BFD_DEST_REGISTER); bgp_bfd_peer_sendmsg(peer, ZEBRA_BFD_DEST_REGISTER);
} }
@ -239,9 +234,8 @@ bgp_bfd_update_type (struct peer *peer)
* bgp_bfd_dest_replay - Replay all the peers that have BFD enabled * bgp_bfd_dest_replay - Replay all the peers that have BFD enabled
* to zebra * to zebra
*/ */
static int static int bgp_bfd_dest_replay(int command, struct zclient *client,
bgp_bfd_dest_replay (int command, struct zclient *client, zebra_size_t length, zebra_size_t length, vrf_id_t vrf_id)
vrf_id_t vrf_id)
{ {
struct listnode *mnode, *node, *nnode; struct listnode *mnode, *node, *nnode;
struct bgp *bgp; struct bgp *bgp;
@ -256,8 +250,7 @@ bgp_bfd_dest_replay (int command, struct zclient *client, zebra_size_t length,
/* Replay the peer, if BFD is enabled in BGP */ /* Replay the peer, if BFD is enabled in BGP */
for (ALL_LIST_ELEMENTS_RO(bm->bgp, mnode, bgp)) for (ALL_LIST_ELEMENTS_RO(bm->bgp, mnode, bgp))
for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer)) for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
{
bgp_bfd_update_peer(peer); bgp_bfd_update_peer(peer);
} }
@ -266,10 +259,10 @@ bgp_bfd_dest_replay (int command, struct zclient *client, zebra_size_t length,
/* /*
* bgp_bfd_peer_status_update - Update the BFD status if it has changed. Bring * bgp_bfd_peer_status_update - Update the BFD status if it has changed. Bring
* down the peer if the BFD session went down from * up. * down the peer if the BFD session went down from
* * up.
*/ */
static void static void bgp_bfd_peer_status_update(struct peer *peer, int status)
bgp_bfd_peer_status_update (struct peer *peer, int status)
{ {
struct bfd_info *bfd_info; struct bfd_info *bfd_info;
int old_status; int old_status;
@ -283,8 +276,7 @@ bgp_bfd_peer_status_update (struct peer *peer, int status)
bfd_info->status = status; bfd_info->status = status;
bfd_info->last_update = bgp_clock(); bfd_info->last_update = bgp_clock();
if ((status == BFD_STATUS_DOWN) && (old_status == BFD_STATUS_UP)) if ((status == BFD_STATUS_DOWN) && (old_status == BFD_STATUS_UP)) {
{
peer->last_reset = PEER_DOWN_BFD_DOWN; peer->last_reset = PEER_DOWN_BFD_DOWN;
BGP_EVENT_ADD(peer, BGP_Stop); BGP_EVENT_ADD(peer, BGP_Stop);
} }
@ -295,8 +287,7 @@ bgp_bfd_peer_status_update (struct peer *peer, int status)
* has changed and bring down the peer * has changed and bring down the peer
* connectivity if the BFD session went down. * connectivity if the BFD session went down.
*/ */
static int static int bgp_bfd_dest_update(int command, struct zclient *zclient,
bgp_bfd_dest_update (int command, struct zclient *zclient,
zebra_size_t length, vrf_id_t vrf_id) zebra_size_t length, vrf_id_t vrf_id)
{ {
struct interface *ifp; struct interface *ifp;
@ -306,20 +297,20 @@ bgp_bfd_dest_update (int command, struct zclient *zclient,
ifp = bfd_get_peer_info(zclient->ibuf, &dp, &sp, &status, vrf_id); ifp = bfd_get_peer_info(zclient->ibuf, &dp, &sp, &status, vrf_id);
if (BGP_DEBUG (zebra, ZEBRA)) if (BGP_DEBUG(zebra, ZEBRA)) {
{
char buf[2][PREFIX2STR_BUFFER]; char buf[2][PREFIX2STR_BUFFER];
prefix2str(&dp, buf[0], sizeof(buf[0])); prefix2str(&dp, buf[0], sizeof(buf[0]));
if (ifp) if (ifp) {
{ zlog_debug(
zlog_debug("Zebra: vrf %d interface %s bfd destination %s %s", "Zebra: vrf %d interface %s bfd destination %s %s",
vrf_id, ifp->name, buf[0], bfd_get_status_str(status)); vrf_id, ifp->name, buf[0],
} bfd_get_status_str(status));
else } else {
{
prefix2str(&sp, buf[1], sizeof(buf[1])); prefix2str(&sp, buf[1], sizeof(buf[1]));
zlog_debug("Zebra: vrf %d source %s bfd destination %s %s", zlog_debug(
vrf_id, buf[1], buf[0], bfd_get_status_str(status)); "Zebra: vrf %d source %s bfd destination %s %s",
vrf_id, buf[1], buf[0],
bfd_get_status_str(status));
} }
} }
@ -330,55 +321,58 @@ bgp_bfd_dest_update (int command, struct zclient *zclient,
struct peer *peer; struct peer *peer;
for (ALL_LIST_ELEMENTS_RO(bm->bgp, mnode, bgp)) for (ALL_LIST_ELEMENTS_RO(bm->bgp, mnode, bgp))
for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer)) for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
{
if (!peer->bfd_info) if (!peer->bfd_info)
continue; continue;
if ((dp.family == AF_INET) && (peer->su.sa.sa_family == AF_INET)) if ((dp.family == AF_INET)
{ && (peer->su.sa.sa_family == AF_INET)) {
if (dp.u.prefix4.s_addr != peer->su.sin.sin_addr.s_addr) if (dp.u.prefix4.s_addr
!= peer->su.sin.sin_addr.s_addr)
continue; continue;
} } else if ((dp.family == AF_INET6)
else if ((dp.family == AF_INET6) && && (peer->su.sa.sa_family
(peer->su.sa.sa_family == AF_INET6)) == AF_INET6)) {
{ if (memcmp(&dp.u.prefix6,
if (memcmp(&dp.u.prefix6, &peer->su.sin6.sin6_addr, &peer->su.sin6.sin6_addr,
sizeof(struct in6_addr))) sizeof(struct in6_addr)))
continue; continue;
} } else
else
continue; continue;
if (ifp && (ifp == peer->nexthop.ifp)) if (ifp && (ifp == peer->nexthop.ifp)) {
{ bgp_bfd_peer_status_update(peer,
bgp_bfd_peer_status_update(peer, status); status);
} } else {
else
{
if (!peer->su_local) if (!peer->su_local)
continue; continue;
if ((sp.family == AF_INET) && if ((sp.family == AF_INET)
(peer->su_local->sa.sa_family == AF_INET)) && (peer->su_local->sa.sa_family
{ == AF_INET)) {
if (sp.u.prefix4.s_addr != peer->su_local->sin.sin_addr.s_addr) if (sp.u.prefix4.s_addr
!= peer->su_local->sin
.sin_addr.s_addr)
continue; continue;
} } else if ((sp.family == AF_INET6)
else if ((sp.family == AF_INET6) && && (peer->su_local->sa
(peer->su_local->sa.sa_family == AF_INET6)) .sa_family
{ == AF_INET6)) {
if (memcmp(&sp.u.prefix6, &peer->su_local->sin6.sin6_addr, if (memcmp(&sp.u.prefix6,
sizeof (struct in6_addr))) &peer->su_local->sin6
.sin6_addr,
sizeof(struct
in6_addr)))
continue; continue;
} } else
else
continue; continue;
if ((vrf_id != VRF_DEFAULT) && (peer->bgp->vrf_id != vrf_id)) if ((vrf_id != VRF_DEFAULT)
&& (peer->bgp->vrf_id != vrf_id))
continue; continue;
bgp_bfd_peer_status_update(peer, status); bgp_bfd_peer_status_update(peer,
status);
} }
} }
} }
@ -389,9 +383,9 @@ bgp_bfd_dest_update (int command, struct zclient *zclient,
/* /*
* bgp_bfd_peer_param_set - Set the configured BFD paramter values for peer. * bgp_bfd_peer_param_set - Set the configured BFD paramter values for peer.
*/ */
static int static int bgp_bfd_peer_param_set(struct peer *peer, u_int32_t min_rx,
bgp_bfd_peer_param_set (struct peer *peer, u_int32_t min_rx, u_int32_t min_tx, u_int32_t min_tx, u_int8_t detect_mult,
u_int8_t detect_mult, int defaults) int defaults)
{ {
struct peer_group *group; struct peer_group *group;
struct listnode *node, *nnode; struct listnode *node, *nnode;
@ -400,26 +394,23 @@ bgp_bfd_peer_param_set (struct peer *peer, u_int32_t min_rx, u_int32_t min_tx,
bfd_set_param((struct bfd_info **)&(peer->bfd_info), min_rx, min_tx, bfd_set_param((struct bfd_info **)&(peer->bfd_info), min_rx, min_tx,
detect_mult, defaults, &command); detect_mult, defaults, &command);
if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
{
group = peer->group; group = peer->group;
for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer)) for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) {
{
command = 0; command = 0;
bfd_set_param((struct bfd_info **)&(peer->bfd_info), min_rx, min_tx, bfd_set_param((struct bfd_info **)&(peer->bfd_info),
detect_mult, defaults, &command); min_rx, min_tx, detect_mult, defaults,
&command);
if ((peer->status == Established) && if ((peer->status == Established)
(command == ZEBRA_BFD_DEST_REGISTER)) && (command == ZEBRA_BFD_DEST_REGISTER))
bgp_bfd_register_peer(peer); bgp_bfd_register_peer(peer);
else if (command == ZEBRA_BFD_DEST_UPDATE) else if (command == ZEBRA_BFD_DEST_UPDATE)
bgp_bfd_update_peer(peer); bgp_bfd_update_peer(peer);
} }
} } else {
else if ((peer->status == Established)
{ && (command == ZEBRA_BFD_DEST_REGISTER))
if ((peer->status == Established) &&
(command == ZEBRA_BFD_DEST_REGISTER))
bgp_bfd_register_peer(peer); bgp_bfd_register_peer(peer);
else if (command == ZEBRA_BFD_DEST_UPDATE) else if (command == ZEBRA_BFD_DEST_UPDATE)
bgp_bfd_update_peer(peer); bgp_bfd_update_peer(peer);
@ -428,10 +419,10 @@ bgp_bfd_peer_param_set (struct peer *peer, u_int32_t min_rx, u_int32_t min_tx,
} }
/* /*
* bgp_bfd_peer_param_unset - Delete the configured BFD paramter values for peer. * bgp_bfd_peer_param_unset - Delete the configured BFD paramter values for
* peer.
*/ */
static int static int bgp_bfd_peer_param_unset(struct peer *peer)
bgp_bfd_peer_param_unset (struct peer *peer)
{ {
struct peer_group *group; struct peer_group *group;
struct listnode *node, *nnode; struct listnode *node, *nnode;
@ -439,18 +430,14 @@ bgp_bfd_peer_param_unset (struct peer *peer)
if (!peer->bfd_info) if (!peer->bfd_info)
return 0; return 0;
if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
{
bfd_info_free(&(peer->bfd_info)); bfd_info_free(&(peer->bfd_info));
group = peer->group; group = peer->group;
for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer)) for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) {
{
bgp_bfd_deregister_peer(peer); bgp_bfd_deregister_peer(peer);
bfd_info_free(&(peer->bfd_info)); bfd_info_free(&(peer->bfd_info));
} }
} } else {
else
{
bgp_bfd_deregister_peer(peer); bgp_bfd_deregister_peer(peer);
bfd_info_free(&(peer->bfd_info)); bfd_info_free(&(peer->bfd_info));
} }
@ -458,29 +445,17 @@ bgp_bfd_peer_param_unset (struct peer *peer)
} }
/* /*
* bgp_bfd_peer_param_type_set - set the BFD session type (multihop or singlehop) * bgp_bfd_peer_param_type_set - set the BFD session type (multihop or
* singlehop)
*/ */
static int static int bgp_bfd_peer_param_type_set(struct peer *peer,
bgp_bfd_peer_param_type_set (struct peer *peer, enum bfd_sess_type type) enum bfd_sess_type type)
{ {
struct peer_group *group; struct peer_group *group;
struct listnode *node, *nnode; struct listnode *node, *nnode;
int command = 0; int command = 0;
struct bfd_info *bfd_info; struct bfd_info *bfd_info;
if (!peer->bfd_info)
bfd_set_param((struct bfd_info **)&(peer->bfd_info), BFD_DEF_MIN_RX,
BFD_DEF_MIN_TX, BFD_DEF_DETECT_MULT, 1, &command);
bfd_info = (struct bfd_info *)peer->bfd_info;
bfd_info->type = type;
if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
{
group = peer->group;
for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
{
command = 0;
if (!peer->bfd_info) if (!peer->bfd_info)
bfd_set_param((struct bfd_info **)&(peer->bfd_info), bfd_set_param((struct bfd_info **)&(peer->bfd_info),
BFD_DEF_MIN_RX, BFD_DEF_MIN_TX, BFD_DEF_MIN_RX, BFD_DEF_MIN_TX,
@ -489,19 +464,28 @@ bgp_bfd_peer_param_type_set (struct peer *peer, enum bfd_sess_type type)
bfd_info = (struct bfd_info *)peer->bfd_info; bfd_info = (struct bfd_info *)peer->bfd_info;
bfd_info->type = type; bfd_info->type = type;
if (peer->status == Established) if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
{ group = peer->group;
for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) {
command = 0;
if (!peer->bfd_info)
bfd_set_param(
(struct bfd_info **)&(peer->bfd_info),
BFD_DEF_MIN_RX, BFD_DEF_MIN_TX,
BFD_DEF_DETECT_MULT, 1, &command);
bfd_info = (struct bfd_info *)peer->bfd_info;
bfd_info->type = type;
if (peer->status == Established) {
if (command == ZEBRA_BFD_DEST_REGISTER) if (command == ZEBRA_BFD_DEST_REGISTER)
bgp_bfd_register_peer(peer); bgp_bfd_register_peer(peer);
else else
bgp_bfd_update_type(peer); bgp_bfd_update_type(peer);
} }
} }
} } else {
else if (peer->status == Established) {
{
if (peer->status == Established)
{
if (command == ZEBRA_BFD_DEST_REGISTER) if (command == ZEBRA_BFD_DEST_REGISTER)
bgp_bfd_register_peer(peer); bgp_bfd_register_peer(peer);
else else
@ -515,8 +499,7 @@ bgp_bfd_peer_param_type_set (struct peer *peer, enum bfd_sess_type type)
/* /*
* bgp_bfd_peer_config_write - Write the peer BFD configuration. * bgp_bfd_peer_config_write - Write the peer BFD configuration.
*/ */
void void bgp_bfd_peer_config_write(struct vty *vty, struct peer *peer, char *addr)
bgp_bfd_peer_config_write(struct vty *vty, struct peer *peer, char *addr)
{ {
struct bfd_info *bfd_info; struct bfd_info *bfd_info;
@ -526,24 +509,25 @@ bgp_bfd_peer_config_write(struct vty *vty, struct peer *peer, char *addr)
bfd_info = (struct bfd_info *)peer->bfd_info; bfd_info = (struct bfd_info *)peer->bfd_info;
if (CHECK_FLAG(bfd_info->flags, BFD_FLAG_PARAM_CFG)) if (CHECK_FLAG(bfd_info->flags, BFD_FLAG_PARAM_CFG))
vty_outln (vty, " neighbor %s bfd %d %d %d", addr, vty_out(vty, " neighbor %s bfd %d %d %d\n", addr,
bfd_info->detect_mult, bfd_info->required_min_rx, bfd_info->detect_mult, bfd_info->required_min_rx,
bfd_info->desired_min_tx); bfd_info->desired_min_tx);
if (bfd_info->type != BFD_TYPE_NOT_CONFIGURED) if (bfd_info->type != BFD_TYPE_NOT_CONFIGURED)
vty_outln (vty, " neighbor %s bfd %s", addr, vty_out(vty, " neighbor %s bfd %s\n", addr,
(bfd_info->type == BFD_TYPE_MULTIHOP) ? "multihop" : "singlehop"); (bfd_info->type == BFD_TYPE_MULTIHOP) ? "multihop"
: "singlehop");
if (!CHECK_FLAG (bfd_info->flags, BFD_FLAG_PARAM_CFG) && if (!CHECK_FLAG(bfd_info->flags, BFD_FLAG_PARAM_CFG)
(bfd_info->type == BFD_TYPE_NOT_CONFIGURED)) && (bfd_info->type == BFD_TYPE_NOT_CONFIGURED))
vty_outln (vty, " neighbor %s bfd", addr); vty_out(vty, " neighbor %s bfd\n", addr);
} }
/* /*
* bgp_bfd_show_info - Show the peer BFD information. * bgp_bfd_show_info - Show the peer BFD information.
*/ */
void void bgp_bfd_show_info(struct vty *vty, struct peer *peer, u_char use_json,
bgp_bfd_show_info(struct vty *vty, struct peer *peer, u_char use_json, json_object *json_neigh) json_object *json_neigh)
{ {
bfd_show_info(vty, (struct bfd_info *)peer->bfd_info, bfd_show_info(vty, (struct bfd_info *)peer->bfd_info,
bgp_bfd_is_peer_multihop(peer), 0, use_json, json_neigh); bgp_bfd_is_peer_multihop(peer), 0, use_json, json_neigh);
@ -562,7 +546,7 @@ DEFUN (neighbor_bfd,
peer = peer_and_group_lookup_vty(vty, argv[idx_peer]->arg); peer = peer_and_group_lookup_vty(vty, argv[idx_peer]->arg);
if (!peer) if (!peer)
return CMD_WARNING; return CMD_WARNING_CONFIG_FAILED;
ret = bgp_bfd_peer_param_set(peer, BFD_DEF_MIN_RX, BFD_DEF_MIN_TX, ret = bgp_bfd_peer_param_set(peer, BFD_DEF_MIN_RX, BFD_DEF_MIN_TX,
BFD_DEF_DETECT_MULT, 1); BFD_DEF_DETECT_MULT, 1);
@ -570,7 +554,6 @@ DEFUN (neighbor_bfd,
return bgp_vty_return(vty, ret); return bgp_vty_return(vty, ret);
return CMD_SUCCESS; return CMD_SUCCESS;
} }
DEFUN (neighbor_bfd_param, DEFUN (neighbor_bfd_param,
@ -595,10 +578,12 @@ DEFUN (neighbor_bfd_param,
peer = peer_and_group_lookup_vty(vty, argv[idx_peer]->arg); peer = peer_and_group_lookup_vty(vty, argv[idx_peer]->arg);
if (!peer) if (!peer)
return CMD_WARNING; return CMD_WARNING_CONFIG_FAILED;
if ((ret = bfd_validate_param (vty, argv[idx_number_1]->arg, argv[idx_number_2]->arg, argv[idx_number_3]->arg, &dm_val, if ((ret = bfd_validate_param(
&rx_val, &tx_val)) != CMD_SUCCESS) vty, argv[idx_number_1]->arg, argv[idx_number_2]->arg,
argv[idx_number_3]->arg, &dm_val, &rx_val, &tx_val))
!= CMD_SUCCESS)
return ret; return ret;
ret = bgp_bfd_peer_param_set(peer, rx_val, tx_val, dm_val, 0); ret = bgp_bfd_peer_param_set(peer, rx_val, tx_val, dm_val, 0);
@ -606,7 +591,6 @@ DEFUN (neighbor_bfd_param,
return bgp_vty_return(vty, ret); return bgp_vty_return(vty, ret);
return CMD_SUCCESS; return CMD_SUCCESS;
} }
DEFUN_HIDDEN (neighbor_bfd_type, DEFUN_HIDDEN (neighbor_bfd_type,
@ -626,14 +610,14 @@ DEFUN_HIDDEN (neighbor_bfd_type,
peer = peer_and_group_lookup_vty(vty, argv[idx_peer]->arg); peer = peer_and_group_lookup_vty(vty, argv[idx_peer]->arg);
if (!peer) if (!peer)
return CMD_WARNING; return CMD_WARNING_CONFIG_FAILED;
if (strmatch(argv[idx_hop]->text, "singlehop")) if (strmatch(argv[idx_hop]->text, "singlehop"))
type = BFD_TYPE_SINGLEHOP; type = BFD_TYPE_SINGLEHOP;
else if (strmatch(argv[idx_hop]->text, "multihop")) else if (strmatch(argv[idx_hop]->text, "multihop"))
type = BFD_TYPE_MULTIHOP; type = BFD_TYPE_MULTIHOP;
else else
return CMD_WARNING; return CMD_WARNING_CONFIG_FAILED;
ret = bgp_bfd_peer_param_type_set(peer, type); ret = bgp_bfd_peer_param_type_set(peer, type);
if (ret != 0) if (ret != 0)
@ -659,7 +643,7 @@ DEFUN (no_neighbor_bfd,
peer = peer_and_group_lookup_vty(vty, argv[idx_peer]->arg); peer = peer_and_group_lookup_vty(vty, argv[idx_peer]->arg);
if (!peer) if (!peer)
return CMD_WARNING; return CMD_WARNING_CONFIG_FAILED;
ret = bgp_bfd_peer_param_unset(peer); ret = bgp_bfd_peer_param_unset(peer);
if (ret != 0) if (ret != 0)
@ -685,7 +669,7 @@ DEFUN_HIDDEN (no_neighbor_bfd_type,
peer = peer_and_group_lookup_vty(vty, argv[idx_peer]->arg); peer = peer_and_group_lookup_vty(vty, argv[idx_peer]->arg);
if (!peer) if (!peer)
return CMD_WARNING; return CMD_WARNING_CONFIG_FAILED;
if (!peer->bfd_info) if (!peer->bfd_info)
return 0; return 0;
@ -697,8 +681,7 @@ DEFUN_HIDDEN (no_neighbor_bfd_type,
return CMD_SUCCESS; return CMD_SUCCESS;
} }
void void bgp_bfd_init(void)
bgp_bfd_init(void)
{ {
bfd_gbl_init(); bfd_gbl_init();

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,15 +35,11 @@
#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,
@ -72,8 +68,7 @@ enum MRT_MSG_TYPES {
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;
@ -84,8 +79,7 @@ attr_parse (struct stream *s, u_int16_t 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);
@ -98,31 +92,24 @@ attr_parse (struct stream *s, u_int16_t len)
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; u_char origin;
origin = stream_getc(s); origin = stream_getc(s);
printf("ORIGIN: %d\n", origin); printf("ORIGIN: %d\n", origin);
} } break;
break; case BGP_ATTR_AS_PATH: {
case BGP_ATTR_AS_PATH:
{
struct aspath *aspath; 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; struct in_addr nexthop;
nexthop.s_addr = stream_get_ipv4(s); nexthop.s_addr = stream_get_ipv4(s);
printf("NEXTHOP: %s\n", inet_ntoa(nexthop)); printf("NEXTHOP: %s\n", inet_ntoa(nexthop));
} } break;
break;
default: default:
stream_getw_from(s, length); stream_getw_from(s, length);
break; break;
@ -132,8 +119,7 @@ attr_parse (struct stream *s, u_int16_t len)
return 0; return 0;
} }
int int main(int argc, char **argv)
main (int argc, char **argv)
{ {
int ret; int ret;
FILE *fp; FILE *fp;
@ -153,31 +139,27 @@ main (int argc, char **argv)
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"); fp = fopen(argv[1], "r");
if (!fp) if (!fp) {
{ fprintf(stdout,
fprintf (stdout,"%% Can't open configuration file %s due to '%s'.\n", "%% Can't open configuration file %s due to '%s'.\n",
argv[1], safe_strerror(errno)); argv[1], safe_strerror(errno));
exit(1); exit(1);
} }
while (1) while (1) {
{
stream_reset(s); stream_reset(s);
ret = fread(s->data, 12, 1, fp); ret = fread(s->data, 12, 1, fp);
if (!ret || feof (fp)) if (!ret || feof(fp)) {
{
printf("END OF FILE\n"); printf("END OF FILE\n");
break; break;
} }
if (ferror (fp)) if (ferror(fp)) {
{
printf("ERROR OF FREAD\n"); printf("ERROR OF FREAD\n");
break; break;
} }
@ -202,8 +184,7 @@ main (int argc, char **argv)
printf("TYPE: Unknown %d", type); printf("TYPE: Unknown %d", type);
if (type == MSG_TABLE_DUMP) if (type == MSG_TABLE_DUMP)
switch (subtype) switch (subtype) {
{
case AFI_IP: case AFI_IP:
printf("/AFI_IP\n"); printf("/AFI_IP\n");
break; break;
@ -214,10 +195,8 @@ main (int argc, char **argv)
printf("/UNKNOWN %d", subtype); printf("/UNKNOWN %d", subtype);
break; break;
} }
else else {
{ switch (subtype) {
switch (subtype)
{
case BGP4MP_STATE_CHANGE: case BGP4MP_STATE_CHANGE:
printf("/CHANGE\n"); printf("/CHANGE\n");
break; break;
@ -239,21 +218,18 @@ main (int argc, char **argv)
printf("len: %zd\n", len); printf("len: %zd\n", len);
fread(s->data + 12, len, 1, fp); fread(s->data + 12, len, 1, fp);
if (feof (fp)) if (feof(fp)) {
{
printf("ENDOF FILE 2\n"); printf("ENDOF FILE 2\n");
break; break;
} }
if (ferror (fp)) if (ferror(fp)) {
{
printf("ERROR OF FREAD 2\n"); printf("ERROR OF FREAD 2\n");
break; break;
} }
/* printf ("now read %d\n", len); */ /* printf ("now read %d\n", len); */
if (type == MSG_TABLE_DUMP) if (type == MSG_TABLE_DUMP) {
{
u_char status; u_char status;
time_t originated; time_t originated;
struct in_addr peer; struct in_addr peer;
@ -265,18 +241,19 @@ main (int argc, char **argv)
printf("SEQUENCE: %d\n", seq_num); printf("SEQUENCE: %d\n", seq_num);
/* start */ /* start */
while (s->getp < len - 16) while (s->getp < len - 16) {
{
p.prefix.s_addr = stream_get_ipv4(s); p.prefix.s_addr = stream_get_ipv4(s);
p.prefixlen = stream_getc(s); p.prefixlen = stream_getc(s);
printf ("PREFIX: %s/%d\n", inet_ntoa (p.prefix), p.prefixlen); printf("PREFIX: %s/%d\n", inet_ntoa(p.prefix),
p.prefixlen);
status = stream_getc(s); status = stream_getc(s);
originated = stream_getl(s); originated = stream_getl(s);
peer.s_addr = stream_get_ipv4(s); peer.s_addr = stream_get_ipv4(s);
source_as = stream_getw(s); source_as = stream_getw(s);
printf ("FROM: %s AS%d\n", inet_ntoa (peer), source_as); printf("FROM: %s AS%d\n", inet_ntoa(peer),
source_as);
printf("ORIGINATED: %s", ctime(&originated)); printf("ORIGINATED: %s", ctime(&originated));
attrlen = stream_getw(s); attrlen = stream_getw(s);
@ -286,9 +263,7 @@ main (int argc, char **argv)
printf("STATUS: 0x%x\n", status); printf("STATUS: 0x%x\n", status);
} }
} } else {
else
{
source_as = stream_getw(s); source_as = stream_getw(s);
dest_as = stream_getw(s); dest_as = stream_getw(s);
printf("source_as: %d\n", source_as); printf("source_as: %d\n", source_as);

View File

@ -40,8 +40,7 @@ struct community_list_master *
community_list_master_lookup(struct community_list_handler *ch, int master) community_list_master_lookup(struct community_list_handler *ch, int master)
{ {
if (ch) if (ch)
switch (master) switch (master) {
{
case COMMUNITY_LIST_MASTER: case COMMUNITY_LIST_MASTER:
return &ch->community_list; return &ch->community_list;
case EXTCOMMUNITY_LIST_MASTER: case EXTCOMMUNITY_LIST_MASTER:
@ -53,18 +52,16 @@ community_list_master_lookup (struct community_list_handler *ch, int master)
} }
/* Allocate a new community list entry. */ /* Allocate a new community list entry. */
static struct community_entry * static struct community_entry *community_entry_new(void)
community_entry_new (void)
{ {
return XCALLOC (MTYPE_COMMUNITY_LIST_ENTRY, sizeof (struct community_entry)); return XCALLOC(MTYPE_COMMUNITY_LIST_ENTRY,
sizeof(struct community_entry));
} }
/* Free community list entry. */ /* Free community list entry. */
static void static void community_entry_free(struct community_entry *entry)
community_entry_free (struct community_entry *entry)
{
switch (entry->style)
{ {
switch (entry->style) {
case COMMUNITY_LIST_STANDARD: case COMMUNITY_LIST_STANDARD:
if (entry->u.com) if (entry->u.com)
community_free(entry->u.com); community_free(entry->u.com);
@ -95,15 +92,13 @@ community_entry_free (struct community_entry *entry)
} }
/* Allocate a new community-list. */ /* Allocate a new community-list. */
static struct community_list * static struct community_list *community_list_new(void)
community_list_new (void)
{ {
return XCALLOC(MTYPE_COMMUNITY_LIST, sizeof(struct community_list)); return XCALLOC(MTYPE_COMMUNITY_LIST, sizeof(struct community_list));
} }
/* Free community-list. */ /* Free community-list. */
static void static void community_list_free(struct community_list *list)
community_list_free (struct community_list *list)
{ {
if (list->name) if (list->name)
XFREE(MTYPE_COMMUNITY_LIST_NAME, list->name); XFREE(MTYPE_COMMUNITY_LIST_NAME, list->name);
@ -111,8 +106,8 @@ community_list_free (struct community_list *list)
} }
static struct community_list * static struct community_list *
community_list_insert (struct community_list_handler *ch, community_list_insert(struct community_list_handler *ch, const char *name,
const char *name, int master) int master)
{ {
size_t i; size_t i;
long number; long number;
@ -132,8 +127,7 @@ community_list_insert (struct community_list_handler *ch,
/* If name is made by all digit character. We treat it as /* If name is made by all digit character. We treat it as
number. */ number. */
for (number = 0, i = 0; i < strlen (name); i++) for (number = 0, i = 0; i < strlen(name); i++) {
{
if (isdigit((int)name[i])) if (isdigit((int)name[i]))
number = (number * 10) + (name[i] - '0'); number = (number * 10) + (name[i] - '0');
else else
@ -141,8 +135,7 @@ community_list_insert (struct community_list_handler *ch,
} }
/* In case of name is all digit character */ /* In case of name is all digit character */
if (i == strlen (name)) if (i == strlen(name)) {
{
new->sort = COMMUNITY_LIST_NUMBER; new->sort = COMMUNITY_LIST_NUMBER;
/* Set access_list to number list. */ /* Set access_list to number list. */
@ -151,9 +144,7 @@ community_list_insert (struct community_list_handler *ch,
for (point = list->head; point; point = point->next) for (point = list->head; point; point = point->next)
if (atol(point->name) >= number) if (atol(point->name) >= number)
break; break;
} } else {
else
{
new->sort = COMMUNITY_LIST_STRING; new->sort = COMMUNITY_LIST_STRING;
/* Set access_list to string list. */ /* Set access_list to string list. */
@ -169,15 +160,13 @@ community_list_insert (struct community_list_handler *ch,
new->parent = list; new->parent = list;
/* In case of this is the first element of master. */ /* In case of this is the first element of master. */
if (list->head == NULL) if (list->head == NULL) {
{
list->head = list->tail = new; list->head = list->tail = new;
return new; return new;
} }
/* In case of insertion is made at the tail of access_list. */ /* In case of insertion is made at the tail of access_list. */
if (point == NULL) if (point == NULL) {
{
new->prev = list->tail; new->prev = list->tail;
list->tail->next = new; list->tail->next = new;
list->tail = new; list->tail = new;
@ -185,8 +174,7 @@ community_list_insert (struct community_list_handler *ch,
} }
/* In case of insertion is made at the head of access_list. */ /* In case of insertion is made at the head of access_list. */
if (point == list->head) if (point == list->head) {
{
new->next = list->head; new->next = list->head;
list->head->prev = new; list->head->prev = new;
list->head = new; list->head = new;
@ -204,8 +192,7 @@ community_list_insert (struct community_list_handler *ch,
return new; return new;
} }
struct community_list * struct community_list *community_list_lookup(struct community_list_handler *ch,
community_list_lookup (struct community_list_handler *ch,
const char *name, int master) const char *name, int master)
{ {
struct community_list *list; struct community_list *list;
@ -229,8 +216,8 @@ community_list_lookup (struct community_list_handler *ch,
} }
static struct community_list * static struct community_list *
community_list_get (struct community_list_handler *ch, community_list_get(struct community_list_handler *ch, const char *name,
const char *name, int master) int master)
{ {
struct community_list *list; struct community_list *list;
@ -240,14 +227,12 @@ community_list_get (struct community_list_handler *ch,
return list; return list;
} }
static void static void community_list_delete(struct community_list *list)
community_list_delete (struct community_list *list)
{ {
struct community_list_list *clist; struct community_list_list *clist;
struct community_entry *entry, *next; struct community_entry *entry, *next;
for (entry = list->head; entry; entry = next) for (entry = list->head; entry; entry = next) {
{
next = entry->next; next = entry->next;
community_entry_free(entry); community_entry_free(entry);
} }
@ -267,15 +252,13 @@ community_list_delete (struct community_list *list)
community_list_free(list); community_list_free(list);
} }
static int static int community_list_empty_p(struct community_list *list)
community_list_empty_p (struct community_list *list)
{ {
return (list->head == NULL && list->tail == NULL) ? 1 : 0; return (list->head == NULL && list->tail == NULL) ? 1 : 0;
} }
/* Add community-list entry to the list. */ /* Add community-list entry to the list. */
static void static void community_list_entry_add(struct community_list *list,
community_list_entry_add (struct community_list *list,
struct community_entry *entry) struct community_entry *entry)
{ {
entry->next = NULL; entry->next = NULL;
@ -289,9 +272,9 @@ community_list_entry_add (struct community_list *list,
} }
/* Delete community-list entry from the list. */ /* Delete community-list entry from the list. */
static void static void community_list_entry_delete(struct community_list *list,
community_list_entry_delete (struct community_list *list, struct community_entry *entry,
struct community_entry *entry, int style) int style)
{ {
if (entry->next) if (entry->next)
entry->next->prev = entry->prev; entry->next->prev = entry->prev;
@ -316,26 +299,28 @@ community_list_entry_lookup (struct community_list *list, const void *arg,
{ {
struct community_entry *entry; struct community_entry *entry;
for (entry = list->head; entry; entry = entry->next) for (entry = list->head; entry; entry = entry->next) {
{ switch (entry->style) {
switch (entry->style)
{
case COMMUNITY_LIST_STANDARD: case COMMUNITY_LIST_STANDARD:
if (entry->direct == direct && community_cmp (entry->u.com, arg)) if (entry->direct == direct
&& community_cmp(entry->u.com, arg))
return entry; return entry;
break; break;
case EXTCOMMUNITY_LIST_STANDARD: case EXTCOMMUNITY_LIST_STANDARD:
if (entry->direct == direct && ecommunity_cmp (entry->u.ecom, arg)) if (entry->direct == direct
&& ecommunity_cmp(entry->u.ecom, arg))
return entry; return entry;
break; break;
case LARGE_COMMUNITY_LIST_STANDARD: case LARGE_COMMUNITY_LIST_STANDARD:
if (entry->direct == direct && lcommunity_cmp (entry->u.lcom, arg)) if (entry->direct == direct
&& lcommunity_cmp(entry->u.lcom, arg))
return entry; return entry;
break; break;
case COMMUNITY_LIST_EXPANDED: case COMMUNITY_LIST_EXPANDED:
case EXTCOMMUNITY_LIST_EXPANDED: case EXTCOMMUNITY_LIST_EXPANDED:
case LARGE_COMMUNITY_LIST_EXPANDED: case LARGE_COMMUNITY_LIST_EXPANDED:
if (entry->direct == direct && strcmp (entry->config, arg) == 0) if (entry->direct == direct
&& strcmp(entry->config, arg) == 0)
return entry; return entry;
break; break;
default: default:
@ -345,8 +330,7 @@ community_list_entry_lookup (struct community_list *list, const void *arg,
return NULL; return NULL;
} }
static char * static char *community_str_get(struct community *com, int i)
community_str_get (struct community *com, int i)
{ {
int len; int len;
u_int32_t comval; u_int32_t comval;
@ -358,8 +342,7 @@ community_str_get (struct community *com, int i)
memcpy(&comval, com_nthval(com, i), sizeof(u_int32_t)); memcpy(&comval, com_nthval(com, i), sizeof(u_int32_t));
comval = ntohl(comval); comval = ntohl(comval);
switch (comval) switch (comval) {
{
case COMMUNITY_INTERNET: case COMMUNITY_INTERNET:
len = strlen(" internet"); len = strlen(" internet");
break; break;
@ -380,8 +363,7 @@ community_str_get (struct community *com, int i)
/* Allocate memory. */ /* Allocate memory. */
str = pnt = XMALLOC(MTYPE_COMMUNITY_STR, len); str = pnt = XMALLOC(MTYPE_COMMUNITY_STR, len);
switch (comval) switch (comval) {
{
case COMMUNITY_INTERNET: case COMMUNITY_INTERNET:
strcpy(pnt, "internet"); strcpy(pnt, "internet");
pnt += strlen("internet"); pnt += strlen("internet");
@ -413,13 +395,13 @@ community_str_get (struct community *com, int i)
/* Internal function to perform regular expression match for /* Internal function to perform regular expression match for
* a single community. */ * a single community. */
static int static int community_regexp_include(regex_t *reg, struct community *com, int i)
community_regexp_include (regex_t * reg, struct community *com, int i)
{ {
char *str; char *str;
int rv; int rv;
/* When there is no communities attribute it is treated as empty string. */ /* When there is no communities attribute it is treated as empty string.
*/
if (com == NULL || com->size == 0) if (com == NULL || com->size == 0)
str = XSTRDUP(MTYPE_COMMUNITY_STR, ""); str = XSTRDUP(MTYPE_COMMUNITY_STR, "");
else else
@ -439,8 +421,7 @@ community_regexp_include (regex_t * reg, struct community *com, int i)
/* Internal function to perform regular expression match for community /* Internal function to perform regular expression match for community
attribute. */ attribute. */
static int static int community_regexp_match(struct community *com, regex_t *reg)
community_regexp_match (struct community *com, regex_t * reg)
{ {
const char *str; const char *str;
@ -459,8 +440,7 @@ community_regexp_match (struct community *com, regex_t * reg)
return 0; return 0;
} }
static char * static char *lcommunity_str_get(struct lcommunity *lcom, int i)
lcommunity_str_get (struct lcommunity *lcom, int i)
{ {
struct lcommunity_val lcomval; struct lcommunity_val lcomval;
u_int32_t globaladmin; u_int32_t globaladmin;
@ -503,20 +483,20 @@ lcommunity_str_get (struct lcommunity *lcom, int i)
/* Internal function to perform regular expression match for /* Internal function to perform regular expression match for
* a single community. */ * a single community. */
static int static int lcommunity_regexp_include(regex_t *reg, struct lcommunity *lcom,
lcommunity_regexp_include (regex_t * reg, struct lcommunity *lcom, int i) int i)
{ {
char *str; char *str;
/* When there is no communities attribute it is treated as empty string. */ /* When there is no communities attribute it is treated as empty string.
*/
if (lcom == NULL || lcom->size == 0) if (lcom == NULL || lcom->size == 0)
str = XSTRDUP(MTYPE_LCOMMUNITY_STR, ""); str = XSTRDUP(MTYPE_LCOMMUNITY_STR, "");
else else
str = lcommunity_str_get(lcom, i); str = lcommunity_str_get(lcom, i);
/* Regular expression match. */ /* Regular expression match. */
if (regexec (reg, str, 0, NULL, 0) == 0) if (regexec(reg, str, 0, NULL, 0) == 0) {
{
XFREE(MTYPE_LCOMMUNITY_STR, str); XFREE(MTYPE_LCOMMUNITY_STR, str);
return 1; return 1;
} }
@ -526,8 +506,7 @@ lcommunity_regexp_include (regex_t * reg, struct lcommunity *lcom, int i)
return 0; return 0;
} }
static int static int lcommunity_regexp_match(struct lcommunity *com, regex_t *reg)
lcommunity_regexp_match (struct lcommunity *com, regex_t * reg)
{ {
const char *str; const char *str;
@ -547,8 +526,7 @@ lcommunity_regexp_match (struct lcommunity *com, regex_t * reg)
} }
static int static int ecommunity_regexp_match(struct ecommunity *ecom, regex_t *reg)
ecommunity_regexp_match (struct ecommunity *ecom, regex_t * reg)
{ {
const char *str; const char *str;
@ -619,76 +597,68 @@ community_regexp_delete (struct community *com, regex_t * reg)
/* When given community attribute matches to the community-list return /* When given community attribute matches to the community-list return
1 else return 0. */ 1 else return 0. */
int int community_list_match(struct community *com, struct community_list *list)
community_list_match (struct community *com, struct community_list *list)
{ {
struct community_entry *entry; struct community_entry *entry;
for (entry = list->head; entry; entry = entry->next) for (entry = list->head; entry; entry = entry->next) {
{
if (entry->any) if (entry->any)
return entry->direct == COMMUNITY_PERMIT ? 1 : 0; return entry->direct == COMMUNITY_PERMIT ? 1 : 0;
if (entry->style == COMMUNITY_LIST_STANDARD) if (entry->style == COMMUNITY_LIST_STANDARD) {
{
if (community_include(entry->u.com, COMMUNITY_INTERNET)) if (community_include(entry->u.com, COMMUNITY_INTERNET))
return entry->direct == COMMUNITY_PERMIT ? 1 : 0; return entry->direct == COMMUNITY_PERMIT ? 1
: 0;
if (community_match(com, entry->u.com)) if (community_match(com, entry->u.com))
return entry->direct == COMMUNITY_PERMIT ? 1 : 0; return entry->direct == COMMUNITY_PERMIT ? 1
} : 0;
else if (entry->style == COMMUNITY_LIST_EXPANDED) } else if (entry->style == COMMUNITY_LIST_EXPANDED) {
{
if (community_regexp_match(com, entry->reg)) if (community_regexp_match(com, entry->reg))
return entry->direct == COMMUNITY_PERMIT ? 1 : 0; return entry->direct == COMMUNITY_PERMIT ? 1
: 0;
} }
} }
return 0; return 0;
} }
int int lcommunity_list_match(struct lcommunity *lcom, struct community_list *list)
lcommunity_list_match (struct lcommunity *lcom, struct community_list *list)
{ {
struct community_entry *entry; struct community_entry *entry;
for (entry = list->head; entry; entry = entry->next) for (entry = list->head; entry; entry = entry->next) {
{
if (entry->any) if (entry->any)
return entry->direct == COMMUNITY_PERMIT ? 1 : 0; return entry->direct == COMMUNITY_PERMIT ? 1 : 0;
if (entry->style == LARGE_COMMUNITY_LIST_STANDARD) if (entry->style == LARGE_COMMUNITY_LIST_STANDARD) {
{
if (lcommunity_match(lcom, entry->u.lcom)) if (lcommunity_match(lcom, entry->u.lcom))
return entry->direct == COMMUNITY_PERMIT ? 1 : 0; return entry->direct == COMMUNITY_PERMIT ? 1
} : 0;
else if (entry->style == LARGE_COMMUNITY_LIST_EXPANDED) } else if (entry->style == LARGE_COMMUNITY_LIST_EXPANDED) {
{
if (lcommunity_regexp_match(lcom, entry->reg)) if (lcommunity_regexp_match(lcom, entry->reg))
return entry->direct == COMMUNITY_PERMIT ? 1 : 0; return entry->direct == COMMUNITY_PERMIT ? 1
: 0;
} }
} }
return 0; return 0;
} }
int int ecommunity_list_match(struct ecommunity *ecom, struct community_list *list)
ecommunity_list_match (struct ecommunity *ecom, struct community_list *list)
{ {
struct community_entry *entry; struct community_entry *entry;
for (entry = list->head; entry; entry = entry->next) for (entry = list->head; entry; entry = entry->next) {
{
if (entry->any) if (entry->any)
return entry->direct == COMMUNITY_PERMIT ? 1 : 0; return entry->direct == COMMUNITY_PERMIT ? 1 : 0;
if (entry->style == EXTCOMMUNITY_LIST_STANDARD) if (entry->style == EXTCOMMUNITY_LIST_STANDARD) {
{
if (ecommunity_match(ecom, entry->u.ecom)) if (ecommunity_match(ecom, entry->u.ecom))
return entry->direct == COMMUNITY_PERMIT ? 1 : 0; return entry->direct == COMMUNITY_PERMIT ? 1
} : 0;
else if (entry->style == EXTCOMMUNITY_LIST_EXPANDED) } else if (entry->style == EXTCOMMUNITY_LIST_EXPANDED) {
{
if (ecommunity_regexp_match(ecom, entry->reg)) if (ecommunity_regexp_match(ecom, entry->reg))
return entry->direct == COMMUNITY_PERMIT ? 1 : 0; return entry->direct == COMMUNITY_PERMIT ? 1
: 0;
} }
} }
return 0; return 0;
@ -696,37 +666,34 @@ ecommunity_list_match (struct ecommunity *ecom, struct community_list *list)
/* Perform exact matching. In case of expanded community-list, do /* Perform exact matching. In case of expanded community-list, do
same thing as community_list_match(). */ same thing as community_list_match(). */
int int community_list_exact_match(struct community *com,
community_list_exact_match (struct community *com,
struct community_list *list) struct community_list *list)
{ {
struct community_entry *entry; struct community_entry *entry;
for (entry = list->head; entry; entry = entry->next) for (entry = list->head; entry; entry = entry->next) {
{
if (entry->any) if (entry->any)
return entry->direct == COMMUNITY_PERMIT ? 1 : 0; return entry->direct == COMMUNITY_PERMIT ? 1 : 0;
if (entry->style == COMMUNITY_LIST_STANDARD) if (entry->style == COMMUNITY_LIST_STANDARD) {
{
if (community_include(entry->u.com, COMMUNITY_INTERNET)) if (community_include(entry->u.com, COMMUNITY_INTERNET))
return entry->direct == COMMUNITY_PERMIT ? 1 : 0; return entry->direct == COMMUNITY_PERMIT ? 1
: 0;
if (community_cmp(com, entry->u.com)) if (community_cmp(com, entry->u.com))
return entry->direct == COMMUNITY_PERMIT ? 1 : 0; return entry->direct == COMMUNITY_PERMIT ? 1
} : 0;
else if (entry->style == COMMUNITY_LIST_EXPANDED) } else if (entry->style == COMMUNITY_LIST_EXPANDED) {
{
if (community_regexp_match(com, entry->reg)) if (community_regexp_match(com, entry->reg))
return entry->direct == COMMUNITY_PERMIT ? 1 : 0; return entry->direct == COMMUNITY_PERMIT ? 1
: 0;
} }
} }
return 0; return 0;
} }
/* Delete all permitted communities in the list from com. */ /* Delete all permitted communities in the list from com. */
struct community * struct community *community_list_match_delete(struct community *com,
community_list_match_delete (struct community *com,
struct community_list *list) struct community_list *list)
{ {
struct community_entry *entry; struct community_entry *entry;
@ -736,19 +703,16 @@ community_list_match_delete (struct community *com,
int i; int i;
/* Loop over each community value and evaluate each against the /* Loop over each community value and evaluate each against the
* community-list. If we need to delete a community value add its index to * community-list. If we need to delete a community value add its index
* to
* com_index_to_delete. * com_index_to_delete.
*/ */
for (i = 0; i < com->size; i++) for (i = 0; i < com->size; i++) {
{
val = community_val_get(com, i); val = community_val_get(com, i);
for (entry = list->head; entry; entry = entry->next) for (entry = list->head; entry; entry = entry->next) {
{ if (entry->any) {
if (entry->any) if (entry->direct == COMMUNITY_PERMIT) {
{
if (entry->direct == COMMUNITY_PERMIT)
{
com_index_to_delete[delete_index] = i; com_index_to_delete[delete_index] = i;
delete_index++; delete_index++;
} }
@ -756,11 +720,10 @@ community_list_match_delete (struct community *com,
} }
else if ((entry->style == COMMUNITY_LIST_STANDARD) else if ((entry->style == COMMUNITY_LIST_STANDARD)
&& (community_include (entry->u.com, COMMUNITY_INTERNET) && (community_include(entry->u.com,
|| community_include (entry->u.com, val) )) COMMUNITY_INTERNET)
{ || community_include(entry->u.com, val))) {
if (entry->direct == COMMUNITY_PERMIT) if (entry->direct == COMMUNITY_PERMIT) {
{
com_index_to_delete[delete_index] = i; com_index_to_delete[delete_index] = i;
delete_index++; delete_index++;
} }
@ -768,10 +731,9 @@ community_list_match_delete (struct community *com,
} }
else if ((entry->style == COMMUNITY_LIST_EXPANDED) else if ((entry->style == COMMUNITY_LIST_EXPANDED)
&& community_regexp_include (entry->reg, com, i)) && community_regexp_include(entry->reg, com,
{ i)) {
if (entry->direct == COMMUNITY_PERMIT) if (entry->direct == COMMUNITY_PERMIT) {
{
com_index_to_delete[delete_index] = i; com_index_to_delete[delete_index] = i;
delete_index++; delete_index++;
} }
@ -781,8 +743,7 @@ community_list_match_delete (struct community *com,
} }
/* Delete all of the communities we flagged for deletion */ /* Delete all of the communities we flagged for deletion */
for (i = delete_index-1; i >= 0; i--) for (i = delete_index - 1; i >= 0; i--) {
{
val = community_val_get(com, com_index_to_delete[i]); val = community_val_get(com, com_index_to_delete[i]);
community_del_val(com, &val); community_del_val(com, &val);
} }
@ -792,14 +753,12 @@ community_list_match_delete (struct community *com,
/* To avoid duplicated entry in the community-list, this function /* To avoid duplicated entry in the community-list, this function
compares specified entry to existing entry. */ compares specified entry to existing entry. */
static int static int community_list_dup_check(struct community_list *list,
community_list_dup_check (struct community_list *list,
struct community_entry *new) struct community_entry *new)
{ {
struct community_entry *entry; struct community_entry *entry;
for (entry = list->head; entry; entry = entry->next) for (entry = list->head; entry; entry = entry->next) {
{
if (entry->style != new->style) if (entry->style != new->style)
continue; continue;
@ -812,8 +771,7 @@ community_list_dup_check (struct community_list *list,
if (entry->any) if (entry->any)
return 1; return 1;
switch (entry->style) switch (entry->style) {
{
case COMMUNITY_LIST_STANDARD: case COMMUNITY_LIST_STANDARD:
if (community_cmp(entry->u.com, new->u.com)) if (community_cmp(entry->u.com, new->u.com))
return 1; return 1;
@ -840,9 +798,8 @@ community_list_dup_check (struct community_list *list,
} }
/* Set community-list. */ /* Set community-list. */
int int community_list_set(struct community_list_handler *ch, const char *name,
community_list_set (struct community_list_handler *ch, const char *str, int direct, int style)
const char *name, const char *str, int direct, int style)
{ {
struct community_entry *entry = NULL; struct community_entry *entry = NULL;
struct community_list *list; struct community_list *list;
@ -855,22 +812,19 @@ community_list_set (struct community_list_handler *ch,
/* When community-list already has entry, new entry should have same /* When community-list already has entry, new entry should have same
style. If you want to have mixed style community-list, you can style. If you want to have mixed style community-list, you can
comment out this check. */ comment out this check. */
if (!community_list_empty_p (list)) if (!community_list_empty_p(list)) {
{
struct community_entry *first; struct community_entry *first;
first = list->head; first = list->head;
if (style != first->style) if (style != first->style) {
{
return (first->style == COMMUNITY_LIST_STANDARD return (first->style == COMMUNITY_LIST_STANDARD
? COMMUNITY_LIST_ERR_STANDARD_CONFLICT ? COMMUNITY_LIST_ERR_STANDARD_CONFLICT
: COMMUNITY_LIST_ERR_EXPANDED_CONFLICT); : COMMUNITY_LIST_ERR_EXPANDED_CONFLICT);
} }
} }
if (str) if (str) {
{
if (style == COMMUNITY_LIST_STANDARD) if (style == COMMUNITY_LIST_STANDARD)
com = community_str2com(str); com = community_str2com(str);
else else
@ -886,13 +840,13 @@ community_list_set (struct community_list_handler *ch,
entry->any = (str ? 0 : 1); entry->any = (str ? 0 : 1);
entry->u.com = com; entry->u.com = com;
entry->reg = regex; entry->reg = regex;
entry->config = (regex ? XSTRDUP (MTYPE_COMMUNITY_LIST_CONFIG, str) : NULL); entry->config =
(regex ? XSTRDUP(MTYPE_COMMUNITY_LIST_CONFIG, str) : NULL);
/* Do not put duplicated community entry. */ /* Do not put duplicated community entry. */
if (community_list_dup_check(list, entry)) if (community_list_dup_check(list, entry))
community_entry_free(entry); community_entry_free(entry);
else else {
{
community_list_entry_add(list, entry); community_list_entry_add(list, entry);
route_map_notify_dependencies(name, RMAP_EVENT_CLIST_ADDED); route_map_notify_dependencies(name, RMAP_EVENT_CLIST_ADDED);
} }
@ -901,10 +855,8 @@ community_list_set (struct community_list_handler *ch,
} }
/* Unset community-list */ /* Unset community-list */
int int community_list_unset(struct community_list_handler *ch, const char *name,
community_list_unset (struct community_list_handler *ch, const char *str, int direct, int style, int delete_all)
const char *name, const char *str,
int direct, int style, int delete_all)
{ {
struct community_entry *entry = NULL; struct community_entry *entry = NULL;
struct community_list *list; struct community_list *list;
@ -916,25 +868,21 @@ community_list_unset (struct community_list_handler *ch,
return COMMUNITY_LIST_ERR_CANT_FIND_LIST; return COMMUNITY_LIST_ERR_CANT_FIND_LIST;
/* Delete all of entry belongs to this community-list. */ /* Delete all of entry belongs to this community-list. */
if (delete_all) if (delete_all) {
{
community_list_delete(list); community_list_delete(list);
route_map_notify_dependencies(name, RMAP_EVENT_CLIST_DELETED); route_map_notify_dependencies(name, RMAP_EVENT_CLIST_DELETED);
return 0; return 0;
} }
if (style == COMMUNITY_LIST_STANDARD) if (style == COMMUNITY_LIST_STANDARD) {
{
if (str) if (str)
com = community_str2com(str); com = community_str2com(str);
} }
if (com) if (com) {
{
entry = community_list_entry_lookup(list, com, direct); entry = community_list_entry_lookup(list, com, direct);
community_free(com); community_free(com);
} } else
else
entry = community_list_entry_lookup(list, str, direct); entry = community_list_entry_lookup(list, str, direct);
if (!entry) if (!entry)
@ -947,8 +895,7 @@ community_list_unset (struct community_list_handler *ch,
} }
/* Delete all permitted large communities in the list from com. */ /* Delete all permitted large communities in the list from com. */
struct lcommunity * struct lcommunity *lcommunity_list_match_delete(struct lcommunity *lcom,
lcommunity_list_match_delete (struct lcommunity *lcom,
struct community_list *list) struct community_list *list)
{ {
struct community_entry *entry; struct community_entry *entry;
@ -958,19 +905,16 @@ lcommunity_list_match_delete (struct lcommunity *lcom,
int i; int i;
/* Loop over each lcommunity value and evaluate each against the /* Loop over each lcommunity value and evaluate each against the
* community-list. If we need to delete a community value add its index to * community-list. If we need to delete a community value add its index
* to
* com_index_to_delete. * com_index_to_delete.
*/ */
ptr = lcom->val; ptr = lcom->val;
for (i = 0; i < lcom->size; i++) for (i = 0; i < lcom->size; i++) {
{
ptr += (i * LCOMMUNITY_SIZE); ptr += (i * LCOMMUNITY_SIZE);
for (entry = list->head; entry; entry = entry->next) for (entry = list->head; entry; entry = entry->next) {
{ if (entry->any) {
if (entry->any) if (entry->direct == COMMUNITY_PERMIT) {
{
if (entry->direct == COMMUNITY_PERMIT)
{
com_index_to_delete[delete_index] = i; com_index_to_delete[delete_index] = i;
delete_index++; delete_index++;
} }
@ -978,10 +922,8 @@ lcommunity_list_match_delete (struct lcommunity *lcom,
} }
else if ((entry->style == LARGE_COMMUNITY_LIST_STANDARD) else if ((entry->style == LARGE_COMMUNITY_LIST_STANDARD)
&& lcommunity_include (entry->u.lcom, ptr) ) && lcommunity_include(entry->u.lcom, ptr)) {
{ if (entry->direct == COMMUNITY_PERMIT) {
if (entry->direct == COMMUNITY_PERMIT)
{
com_index_to_delete[delete_index] = i; com_index_to_delete[delete_index] = i;
delete_index++; delete_index++;
} }
@ -989,10 +931,9 @@ lcommunity_list_match_delete (struct lcommunity *lcom,
} }
else if ((entry->style == LARGE_COMMUNITY_LIST_STANDARD) else if ((entry->style == LARGE_COMMUNITY_LIST_STANDARD)
&& lcommunity_regexp_include (entry->reg, lcom, i)) && lcommunity_regexp_include(entry->reg, lcom,
{ i)) {
if (entry->direct == COMMUNITY_PERMIT) if (entry->direct == COMMUNITY_PERMIT) {
{
com_index_to_delete[delete_index] = i; com_index_to_delete[delete_index] = i;
delete_index++; delete_index++;
} }
@ -1003,8 +944,7 @@ lcommunity_list_match_delete (struct lcommunity *lcom,
/* Delete all of the communities we flagged for deletion */ /* Delete all of the communities we flagged for deletion */
ptr = lcom->val; ptr = lcom->val;
for (i = delete_index-1; i >= 0; i--) for (i = delete_index - 1; i >= 0; i--) {
{
ptr += (com_index_to_delete[i] * LCOMMUNITY_SIZE); ptr += (com_index_to_delete[i] * LCOMMUNITY_SIZE);
lcommunity_del_val(lcom, ptr); lcommunity_del_val(lcom, ptr);
} }
@ -1013,9 +953,8 @@ lcommunity_list_match_delete (struct lcommunity *lcom,
} }
/* Set lcommunity-list. */ /* Set lcommunity-list. */
int int lcommunity_list_set(struct community_list_handler *ch, const char *name,
lcommunity_list_set (struct community_list_handler *ch, const char *str, int direct, int style)
const char *name, const char *str, int direct, int style)
{ {
struct community_entry *entry = NULL; struct community_entry *entry = NULL;
struct community_list *list; struct community_list *list;
@ -1028,22 +967,19 @@ lcommunity_list_set (struct community_list_handler *ch,
/* When community-list already has entry, new entry should have same /* When community-list already has entry, new entry should have same
style. If you want to have mixed style community-list, you can style. If you want to have mixed style community-list, you can
comment out this check. */ comment out this check. */
if (!community_list_empty_p (list)) if (!community_list_empty_p(list)) {
{
struct community_entry *first; struct community_entry *first;
first = list->head; first = list->head;
if (style != first->style) if (style != first->style) {
{
return (first->style == COMMUNITY_LIST_STANDARD return (first->style == COMMUNITY_LIST_STANDARD
? COMMUNITY_LIST_ERR_STANDARD_CONFLICT ? COMMUNITY_LIST_ERR_STANDARD_CONFLICT
: COMMUNITY_LIST_ERR_EXPANDED_CONFLICT); : COMMUNITY_LIST_ERR_EXPANDED_CONFLICT);
} }
} }
if (str) if (str) {
{
if (style == LARGE_COMMUNITY_LIST_STANDARD) if (style == LARGE_COMMUNITY_LIST_STANDARD)
lcom = lcommunity_str2com(str); lcom = lcommunity_str2com(str);
else else
@ -1060,7 +996,8 @@ lcommunity_list_set (struct community_list_handler *ch,
entry->u.lcom = lcom; entry->u.lcom = lcom;
entry->reg = regex; entry->reg = regex;
if (lcom) if (lcom)
entry->config = lcommunity_lcom2str (lcom, LCOMMUNITY_FORMAT_COMMUNITY_LIST); entry->config = lcommunity_lcom2str(
lcom, LCOMMUNITY_FORMAT_COMMUNITY_LIST);
else if (regex) else if (regex)
entry->config = XSTRDUP(MTYPE_COMMUNITY_LIST_CONFIG, str); entry->config = XSTRDUP(MTYPE_COMMUNITY_LIST_CONFIG, str);
else else
@ -1077,10 +1014,8 @@ lcommunity_list_set (struct community_list_handler *ch,
/* Unset community-list. When str is NULL, delete all of /* Unset community-list. When str is NULL, delete all of
community-list entry belongs to the specified name. */ community-list entry belongs to the specified name. */
int int lcommunity_list_unset(struct community_list_handler *ch, const char *name,
lcommunity_list_unset (struct community_list_handler *ch, const char *str, int direct, int style)
const char *name, const char *str,
int direct, int style)
{ {
struct community_entry *entry = NULL; struct community_entry *entry = NULL;
struct community_list *list; struct community_list *list;
@ -1093,8 +1028,7 @@ lcommunity_list_unset (struct community_list_handler *ch,
return COMMUNITY_LIST_ERR_CANT_FIND_LIST; return COMMUNITY_LIST_ERR_CANT_FIND_LIST;
/* Delete all of entry belongs to this community-list. */ /* Delete all of entry belongs to this community-list. */
if (!str) if (!str) {
{
community_list_delete(list); community_list_delete(list);
return 0; return 0;
} }
@ -1126,10 +1060,8 @@ lcommunity_list_unset (struct community_list_handler *ch,
} }
/* Set extcommunity-list. */ /* Set extcommunity-list. */
int int extcommunity_list_set(struct community_list_handler *ch, const char *name,
extcommunity_list_set (struct community_list_handler *ch, const char *str, int direct, int style)
const char *name, const char *str,
int direct, int style)
{ {
struct community_entry *entry = NULL; struct community_entry *entry = NULL;
struct community_list *list; struct community_list *list;
@ -1144,14 +1076,12 @@ extcommunity_list_set (struct community_list_handler *ch,
/* When community-list already has entry, new entry should have same /* When community-list already has entry, new entry should have same
style. If you want to have mixed style community-list, you can style. If you want to have mixed style community-list, you can
comment out this check. */ comment out this check. */
if (!community_list_empty_p (list)) if (!community_list_empty_p(list)) {
{
struct community_entry *first; struct community_entry *first;
first = list->head; first = list->head;
if (style != first->style) if (style != first->style) {
{
return (first->style == EXTCOMMUNITY_LIST_STANDARD return (first->style == EXTCOMMUNITY_LIST_STANDARD
? COMMUNITY_LIST_ERR_STANDARD_CONFLICT ? COMMUNITY_LIST_ERR_STANDARD_CONFLICT
: COMMUNITY_LIST_ERR_EXPANDED_CONFLICT); : COMMUNITY_LIST_ERR_EXPANDED_CONFLICT);
@ -1167,14 +1097,16 @@ extcommunity_list_set (struct community_list_handler *ch,
return COMMUNITY_LIST_ERR_MALFORMED_VAL; return COMMUNITY_LIST_ERR_MALFORMED_VAL;
if (ecom) if (ecom)
ecom->str = ecommunity_ecom2str (ecom, ECOMMUNITY_FORMAT_DISPLAY, 0); ecom->str =
ecommunity_ecom2str(ecom, ECOMMUNITY_FORMAT_DISPLAY, 0);
entry = community_entry_new(); entry = community_entry_new();
entry->direct = direct; entry->direct = direct;
entry->style = style; entry->style = style;
entry->any = (str ? 0 : 1); entry->any = (str ? 0 : 1);
if (ecom) if (ecom)
entry->config = ecommunity_ecom2str (ecom, ECOMMUNITY_FORMAT_COMMUNITY_LIST, 0); entry->config = ecommunity_ecom2str(
ecom, ECOMMUNITY_FORMAT_COMMUNITY_LIST, 0);
else if (regex) else if (regex)
entry->config = XSTRDUP(MTYPE_COMMUNITY_LIST_CONFIG, str); entry->config = XSTRDUP(MTYPE_COMMUNITY_LIST_CONFIG, str);
@ -1184,8 +1116,7 @@ extcommunity_list_set (struct community_list_handler *ch,
/* Do not put duplicated community entry. */ /* Do not put duplicated community entry. */
if (community_list_dup_check(list, entry)) if (community_list_dup_check(list, entry))
community_entry_free(entry); community_entry_free(entry);
else else {
{
community_list_entry_add(list, entry); community_list_entry_add(list, entry);
route_map_notify_dependencies(name, RMAP_EVENT_ECLIST_ADDED); route_map_notify_dependencies(name, RMAP_EVENT_ECLIST_ADDED);
} }
@ -1195,10 +1126,9 @@ extcommunity_list_set (struct community_list_handler *ch,
/* Unset extcommunity-list. When str is NULL, delete all of /* Unset extcommunity-list. When str is NULL, delete all of
extcommunity-list entry belongs to the specified name. */ extcommunity-list entry belongs to the specified name. */
int int extcommunity_list_unset(struct community_list_handler *ch, const char *name,
extcommunity_list_unset (struct community_list_handler *ch, const char *str, int direct, int style,
const char *name, const char *str, int delete_all)
int direct, int style, int delete_all)
{ {
struct community_entry *entry = NULL; struct community_entry *entry = NULL;
struct community_list *list; struct community_list *list;
@ -1210,25 +1140,21 @@ extcommunity_list_unset (struct community_list_handler *ch,
return COMMUNITY_LIST_ERR_CANT_FIND_LIST; return COMMUNITY_LIST_ERR_CANT_FIND_LIST;
/* Delete all of entry belongs to this extcommunity-list. */ /* Delete all of entry belongs to this extcommunity-list. */
if (delete_all) if (delete_all) {
{
community_list_delete(list); community_list_delete(list);
route_map_notify_dependencies(name, RMAP_EVENT_ECLIST_DELETED); route_map_notify_dependencies(name, RMAP_EVENT_ECLIST_DELETED);
return 0; return 0;
} }
if (style == EXTCOMMUNITY_LIST_STANDARD) if (style == EXTCOMMUNITY_LIST_STANDARD) {
{
if (str) if (str)
ecom = ecommunity_str2com(str, 0, 1); ecom = ecommunity_str2com(str, 0, 1);
} }
if (ecom) if (ecom) {
{
entry = community_list_entry_lookup(list, ecom, direct); entry = community_list_entry_lookup(list, ecom, direct);
ecommunity_free(&ecom); ecommunity_free(&ecom);
} } else
else
entry = community_list_entry_lookup(list, str, direct); entry = community_list_entry_lookup(list, str, direct);
if (!entry) if (!entry)
@ -1241,8 +1167,7 @@ extcommunity_list_unset (struct community_list_handler *ch,
} }
/* Initializa community-list. Return community-list handler. */ /* Initializa community-list. Return community-list handler. */
struct community_list_handler * struct community_list_handler *community_list_init(void)
community_list_init (void)
{ {
struct community_list_handler *ch; struct community_list_handler *ch;
ch = XCALLOC(MTYPE_COMMUNITY_LIST_HANDLER, ch = XCALLOC(MTYPE_COMMUNITY_LIST_HANDLER,
@ -1251,8 +1176,7 @@ community_list_init (void)
} }
/* Terminate community-list. */ /* Terminate community-list. */
void void community_list_terminate(struct community_list_handler *ch)
community_list_terminate (struct community_list_handler *ch)
{ {
struct community_list_master *cm; struct community_list_master *cm;
struct community_list *list; struct community_list *list;

View File

@ -43,8 +43,7 @@
#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;
@ -64,8 +63,7 @@ struct community_list
}; };
/* 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;
@ -79,8 +77,7 @@ struct community_entry
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;
@ -94,23 +91,20 @@ struct community_entry
}; };
/* 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;
@ -138,20 +132,20 @@ extern int community_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 community_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, int delete_all);
extern int extcommunity_list_set(struct community_list_handler *ch, extern int extcommunity_list_set(struct community_list_handler *ch,
const char *name, const char *str, const char *name, const char *str, int direct,
int direct, int style); int style);
extern int extcommunity_list_unset(struct community_list_handler *ch, extern int extcommunity_list_unset(struct community_list_handler *ch,
const char *name, const char *str, const char *name, const char *str,
int direct, int style, int delete_all); int direct, int style, int delete_all);
extern int lcommunity_list_set(struct community_list_handler *ch, extern int lcommunity_list_set(struct community_list_handler *ch,
const char *name, const char *str, const char *name, const char *str, int direct,
int direct, int style); int style);
extern int lcommunity_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 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);
@ -164,8 +158,8 @@ 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);

View File

@ -31,24 +31,21 @@
static struct hash *comhash; static struct hash *comhash;
/* Allocate a new communities value. */ /* Allocate a new communities value. */
static struct community * static struct community *community_new(void)
community_new (void)
{ {
return (struct community *)XCALLOC(MTYPE_COMMUNITY, return (struct community *)XCALLOC(MTYPE_COMMUNITY,
sizeof(struct community)); sizeof(struct community));
} }
/* Free communities value. */ /* Free communities value. */
void void community_free(struct community *com)
community_free (struct community *com)
{ {
if (com->val) if (com->val)
XFREE(MTYPE_COMMUNITY_VAL, com->val); XFREE(MTYPE_COMMUNITY_VAL, com->val);
if (com->str) if (com->str)
XFREE(MTYPE_COMMUNITY_STR, com->str); XFREE(MTYPE_COMMUNITY_STR, com->str);
if (com->json) if (com->json) {
{
json_object_free(com->json); json_object_free(com->json);
com->json = NULL; com->json = NULL;
} }
@ -57,12 +54,12 @@ community_free (struct community *com)
} }
/* Add one community value to the community. */ /* Add one community value to the community. */
static void static void community_add_val(struct community *com, u_int32_t val)
community_add_val (struct community *com, u_int32_t val)
{ {
com->size++; com->size++;
if (com->val) if (com->val)
com->val = XREALLOC (MTYPE_COMMUNITY_VAL, com->val, com_length (com)); com->val = XREALLOC(MTYPE_COMMUNITY_VAL, com->val,
com_length(com));
else else
com->val = XMALLOC(MTYPE_COMMUNITY_VAL, com_length(com)); com->val = XMALLOC(MTYPE_COMMUNITY_VAL, com_length(com));
@ -71,8 +68,7 @@ community_add_val (struct community *com, u_int32_t val)
} }
/* Delete one community. */ /* Delete one community. */
void void community_del_val(struct community *com, u_int32_t *val)
community_del_val (struct community *com, u_int32_t *val)
{ {
int i = 0; int i = 0;
int c = 0; int c = 0;
@ -80,22 +76,20 @@ community_del_val (struct community *com, u_int32_t *val)
if (!com->val) if (!com->val)
return; return;
while (i < com->size) while (i < com->size) {
{ if (memcmp(com->val + i, val, sizeof(u_int32_t)) == 0) {
if (memcmp (com->val + i, val, sizeof (u_int32_t)) == 0)
{
c = com->size - i - 1; c = com->size - i - 1;
if (c > 0) if (c > 0)
memmove (com->val + i, com->val + (i + 1), c * sizeof (*val)); memmove(com->val + i, com->val + (i + 1),
c * sizeof(*val));
com->size--; com->size--;
if (com->size > 0) if (com->size > 0)
com->val = XREALLOC (MTYPE_COMMUNITY_VAL, com->val, com->val = XREALLOC(MTYPE_COMMUNITY_VAL,
com_length (com)); com->val, com_length(com));
else else {
{
XFREE(MTYPE_COMMUNITY_VAL, com->val); XFREE(MTYPE_COMMUNITY_VAL, com->val);
com->val = NULL; com->val = NULL;
} }
@ -106,13 +100,12 @@ community_del_val (struct community *com, u_int32_t *val)
} }
/* Delete all communities listed in com2 from com1 */ /* Delete all communities listed in com2 from com1 */
struct community * struct community *community_delete(struct community *com1,
community_delete (struct community *com1, struct community *com2) struct community *com2)
{ {
int i = 0; int i = 0;
while(i < com2->size) while (i < com2->size) {
{
community_del_val(com1, com2->val + i); community_del_val(com1, com2->val + i);
i++; i++;
} }
@ -121,8 +114,7 @@ community_delete (struct community *com1, struct community *com2)
} }
/* Callback function from qsort(). */ /* Callback function from qsort(). */
static int static int community_compare(const void *a1, const void *a2)
community_compare (const void *a1, const void *a2)
{ {
u_int32_t v1; u_int32_t v1;
u_int32_t v2; u_int32_t v2;
@ -139,8 +131,7 @@ community_compare (const void *a1, const void *a2)
return 0; return 0;
} }
int int community_include(struct community *com, u_int32_t val)
community_include (struct community *com, u_int32_t val)
{ {
int i; int i;
@ -153,8 +144,7 @@ community_include (struct community *com, u_int32_t val)
return 0; return 0;
} }
u_int32_t u_int32_t community_val_get(struct community *com, int i)
community_val_get (struct community *com, int i)
{ {
u_char *p; u_char *p;
u_int32_t val; u_int32_t val;
@ -168,8 +158,7 @@ community_val_get (struct community *com, int i)
} }
/* Sort and uniq given community. */ /* Sort and uniq given community. */
struct community * struct community *community_uniq_sort(struct community *com)
community_uniq_sort (struct community *com)
{ {
int i; int i;
struct community *new; struct community *new;
@ -178,11 +167,11 @@ community_uniq_sort (struct community *com)
if (!com) if (!com)
return NULL; return NULL;
new = community_new ();; new = community_new();
;
new->json = NULL; new->json = NULL;
for (i = 0; i < com->size; i++) for (i = 0; i < com->size; i++) {
{
val = community_val_get(com, i); val = community_val_get(com, i);
if (!community_include(new, val)) if (!community_include(new, val))
@ -204,8 +193,7 @@ community_uniq_sort (struct community *com)
0xFFFFFF03 "local-AS" 0xFFFFFF03 "local-AS"
For other values, "AS:VAL" format is used. */ For other values, "AS:VAL" format is used. */
static void static void set_community_string(struct community *com)
set_community_string (struct community *com)
{ {
int i; int i;
char *str; char *str;
@ -225,8 +213,7 @@ set_community_string (struct community *com)
json_community_list = json_object_new_array(); json_community_list = json_object_new_array();
/* When communities attribute is empty. */ /* When communities attribute is empty. */
if (com->size == 0) if (com->size == 0) {
{
str = XMALLOC(MTYPE_COMMUNITY_STR, 1); str = XMALLOC(MTYPE_COMMUNITY_STR, 1);
str[0] = '\0'; str[0] = '\0';
@ -240,13 +227,11 @@ set_community_string (struct community *com)
required string length first. */ required string length first. */
len = 0; len = 0;
for (i = 0; i < com->size; i++) for (i = 0; i < com->size; i++) {
{
memcpy(&comval, com_nthval(com, i), sizeof(u_int32_t)); memcpy(&comval, com_nthval(com, i), sizeof(u_int32_t));
comval = ntohl(comval); comval = ntohl(comval);
switch (comval) switch (comval) {
{
case COMMUNITY_INTERNET: case COMMUNITY_INTERNET:
len += strlen(" internet"); len += strlen(" internet");
break; break;
@ -270,8 +255,7 @@ set_community_string (struct community *com)
first = 1; first = 1;
/* Fill in string. */ /* Fill in string. */
for (i = 0; i < com->size; i++) for (i = 0; i < com->size; i++) {
{
memcpy(&comval, com_nthval(com, i), sizeof(u_int32_t)); memcpy(&comval, com_nthval(com, i), sizeof(u_int32_t));
comval = ntohl(comval); comval = ntohl(comval);
@ -280,8 +264,7 @@ set_community_string (struct community *com)
else else
*pnt++ = ' '; *pnt++ = ' ';
switch (comval) switch (comval) {
{
case COMMUNITY_INTERNET: case COMMUNITY_INTERNET:
strcpy(pnt, "internet"); strcpy(pnt, "internet");
pnt += strlen("internet"); pnt += strlen("internet");
@ -324,8 +307,7 @@ set_community_string (struct community *com)
} }
/* Intern communities attribute. */ /* Intern communities attribute. */
struct community * struct community *community_intern(struct community *com)
community_intern (struct community *com)
{ {
struct community *find; struct community *find;
@ -351,8 +333,7 @@ community_intern (struct community *com)
} }
/* Free community attribute. */ /* Free community attribute. */
void void community_unintern(struct community **com)
community_unintern (struct community **com)
{ {
struct community *ret; struct community *ret;
@ -360,8 +341,7 @@ community_unintern (struct community **com)
(*com)->refcnt--; (*com)->refcnt--;
/* Pull off from hash. */ /* Pull off from hash. */
if ((*com)->refcnt == 0) if ((*com)->refcnt == 0) {
{
/* Community value com must exist in hash. */ /* Community value com must exist in hash. */
ret = (struct community *)hash_release(comhash, *com); ret = (struct community *)hash_release(comhash, *com);
assert(ret != NULL); assert(ret != NULL);
@ -372,8 +352,7 @@ community_unintern (struct community **com)
} }
/* Create new community attribute. */ /* Create new community attribute. */
struct community * struct community *community_parse(u_int32_t *pnt, u_short length)
community_parse (u_int32_t *pnt, u_short length)
{ {
struct community tmp; struct community tmp;
struct community *new; struct community *new;
@ -391,26 +370,22 @@ community_parse (u_int32_t *pnt, u_short length)
return community_intern(new); return community_intern(new);
} }
struct community * struct community *community_dup(struct community *com)
community_dup (struct community *com)
{ {
struct community *new; struct community *new;
new = XCALLOC(MTYPE_COMMUNITY, sizeof(struct community)); new = XCALLOC(MTYPE_COMMUNITY, sizeof(struct community));
new->size = com->size; new->size = com->size;
if (new->size) if (new->size) {
{
new->val = XMALLOC(MTYPE_COMMUNITY_VAL, com->size * 4); new->val = XMALLOC(MTYPE_COMMUNITY_VAL, com->size * 4);
memcpy(new->val, com->val, com->size * 4); memcpy(new->val, com->val, com->size * 4);
} } 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 *community_str(struct community *com)
community_str (struct community *com)
{ {
if (!com) if (!com)
return NULL; return NULL;
@ -422,16 +397,14 @@ community_str (struct community *com)
/* Make hash value of community attribute. This function is used by /* Make hash value of community attribute. This function is used by
hash package.*/ hash package.*/
unsigned int unsigned int community_hash_make(struct community *com)
community_hash_make (struct community *com)
{ {
unsigned char *pnt = (unsigned char *)com->val; unsigned char *pnt = (unsigned char *)com->val;
int size = com->size * 4; int size = com->size * 4;
unsigned int key = 0; unsigned int key = 0;
int c; int c;
for (c = 0; c < size; c += 4) for (c = 0; c < size; c += 4) {
{
key += pnt[c]; key += pnt[c];
key += pnt[c + 1]; key += pnt[c + 1];
key += pnt[c + 2]; key += pnt[c + 2];
@ -441,8 +414,7 @@ community_hash_make (struct community *com)
return key; return key;
} }
int int community_match(const struct community *com1, const struct community *com2)
community_match (const struct community *com1, const struct community *com2)
{ {
int i = 0; int i = 0;
int j = 0; int j = 0;
@ -457,9 +429,9 @@ community_match (const struct community *com1, const struct community *com2)
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 < com1->size && j < com2->size) while (i < com1->size && j < com2->size) {
{ if (memcmp(com1->val + i, com2->val + j, sizeof(u_int32_t))
if (memcmp (com1->val + i, com2->val + j, sizeof (u_int32_t)) == 0) == 0)
j++; j++;
i++; i++;
} }
@ -472,8 +444,7 @@ community_match (const struct community *com1, const struct community *com2)
/* If two aspath have same value then return 1 else return 0. This /* If two aspath have same value then return 1 else return 0. This
function is used by hash package. */ function is used by hash package. */
int int community_cmp(const struct community *com1, const struct community *com2)
community_cmp (const struct community *com1, const struct community *com2)
{ {
if (com1 == NULL && com2 == NULL) if (com1 == NULL && com2 == NULL)
return 1; return 1;
@ -487,14 +458,15 @@ community_cmp (const struct community *com1, const struct community *com2)
} }
/* Add com2 to the end of com1. */ /* Add com2 to the end of com1. */
struct community * struct community *community_merge(struct community *com1,
community_merge (struct community *com1, struct community *com2) struct community *com2)
{ {
if (com1->val) if (com1->val)
com1->val = XREALLOC(MTYPE_COMMUNITY_VAL, com1->val, com1->val = XREALLOC(MTYPE_COMMUNITY_VAL, com1->val,
(com1->size + com2->size) * 4); (com1->size + com2->size) * 4);
else else
com1->val = XMALLOC (MTYPE_COMMUNITY_VAL, (com1->size + com2->size) * 4); com1->val = XMALLOC(MTYPE_COMMUNITY_VAL,
(com1->size + com2->size) * 4);
memcpy(com1->val + com1->size, com2->val, com2->size * 4); memcpy(com1->val + com1->size, com2->val, com2->size * 4);
com1->size += com2->size; com1->size += com2->size;
@ -503,8 +475,7 @@ community_merge (struct community *com1, struct community *com2)
} }
/* Community token enum. */ /* Community token enum. */
enum community_token enum community_token {
{
community_token_val, community_token_val,
community_token_no_export, community_token_no_export,
community_token_no_advertise, community_token_no_advertise,
@ -514,8 +485,7 @@ enum community_token
/* Get next community token from string. */ /* Get next community token from string. */
static const char * static const char *
community_gettoken (const char *buf, enum community_token *token, community_gettoken(const char *buf, enum community_token *token, u_int32_t *val)
u_int32_t *val)
{ {
const char *p = buf; const char *p = buf;
@ -528,31 +498,26 @@ community_gettoken (const char *buf, enum community_token *token,
return NULL; return NULL;
/* Well known community string check. */ /* Well known community string check. */
if (isalpha ((int) *p)) if (isalpha((int)*p)) {
{ if (strncmp(p, "internet", strlen("internet")) == 0) {
if (strncmp (p, "internet", strlen ("internet")) == 0)
{
*val = COMMUNITY_INTERNET; *val = COMMUNITY_INTERNET;
*token = community_token_no_export; *token = community_token_no_export;
p += strlen("internet"); p += strlen("internet");
return p; return p;
} }
if (strncmp (p, "no-export", strlen ("no-export")) == 0) if (strncmp(p, "no-export", strlen("no-export")) == 0) {
{
*val = COMMUNITY_NO_EXPORT; *val = COMMUNITY_NO_EXPORT;
*token = community_token_no_export; *token = community_token_no_export;
p += strlen("no-export"); p += strlen("no-export");
return p; return p;
} }
if (strncmp (p, "no-advertise", strlen ("no-advertise")) == 0) if (strncmp(p, "no-advertise", strlen("no-advertise")) == 0) {
{
*val = COMMUNITY_NO_ADVERTISE; *val = COMMUNITY_NO_ADVERTISE;
*token = community_token_no_advertise; *token = community_token_no_advertise;
p += strlen("no-advertise"); p += strlen("no-advertise");
return p; return p;
} }
if (strncmp (p, "local-AS", strlen ("local-AS")) == 0) if (strncmp(p, "local-AS", strlen("local-AS")) == 0) {
{
*val = COMMUNITY_LOCAL_AS; *val = COMMUNITY_LOCAL_AS;
*token = community_token_local_as; *token = community_token_local_as;
p += strlen("local-AS"); p += strlen("local-AS");
@ -565,53 +530,43 @@ community_gettoken (const char *buf, enum community_token *token,
} }
/* Community value. */ /* Community value. */
if (isdigit ((int) *p)) if (isdigit((int)*p)) {
{
int separator = 0; int separator = 0;
int digit = 0; int digit = 0;
u_int32_t community_low = 0; u_int32_t community_low = 0;
u_int32_t community_high = 0; u_int32_t community_high = 0;
while (isdigit ((int) *p) || *p == ':') while (isdigit((int)*p) || *p == ':') {
{ if (*p == ':') {
if (*p == ':') if (separator) {
{
if (separator)
{
*token = community_token_unknown; *token = community_token_unknown;
return NULL; return NULL;
} } else {
else
{
separator = 1; separator = 1;
digit = 0; digit = 0;
if (community_low > UINT16_MAX) if (community_low > UINT16_MAX) {
{ *token =
*token = community_token_unknown; community_token_unknown;
return NULL; return NULL;
} }
community_high = community_low << 16; community_high = community_low << 16;
community_low = 0; community_low = 0;
} }
} } else {
else
{
digit = 1; digit = 1;
community_low *= 10; community_low *= 10;
community_low += (*p - '0'); community_low += (*p - '0');
} }
p++; p++;
} }
if (! digit) if (!digit) {
{
*token = community_token_unknown; *token = community_token_unknown;
return NULL; return NULL;
} }
if (community_low > UINT16_MAX) if (community_low > UINT16_MAX) {
{
*token = community_token_unknown; *token = community_token_unknown;
return NULL; return NULL;
} }
@ -625,26 +580,22 @@ community_gettoken (const char *buf, enum community_token *token,
} }
/* convert string to community structure */ /* convert string to community structure */
struct community * struct community *community_str2com(const char *str)
community_str2com (const char *str)
{ {
struct community *com = NULL; struct community *com = NULL;
struct community *com_sort = NULL; struct community *com_sort = NULL;
u_int32_t val = 0; u_int32_t val = 0;
enum community_token token = community_token_unknown; enum community_token token = community_token_unknown;
do do {
{
str = community_gettoken(str, &token, &val); str = community_gettoken(str, &token, &val);
switch (token) switch (token) {
{
case community_token_val: case community_token_val:
case community_token_no_export: case community_token_no_export:
case community_token_no_advertise: case community_token_no_advertise:
case community_token_local_as: case community_token_local_as:
if (com == NULL) if (com == NULL) {
{
com = community_new(); com = community_new();
com->json = NULL; com->json = NULL;
} }
@ -668,29 +619,26 @@ community_str2com (const char *str)
} }
/* Return communities hash entry count. */ /* Return communities hash entry count. */
unsigned long unsigned long community_count(void)
community_count (void)
{ {
return comhash->count; return comhash->count;
} }
/* Return communities hash. */ /* Return communities hash. */
struct hash * struct hash *community_hash(void)
community_hash (void)
{ {
return comhash; return comhash;
} }
/* Initialize comminity related hash. */ /* Initialize comminity related hash. */
void void community_init(void)
community_init (void)
{ {
comhash = hash_create ((unsigned int (*) (void *))community_hash_make, comhash = hash_create(
(unsigned int (*)(void *))community_hash_make,
(int (*)(const void *, const void *))community_cmp, NULL); (int (*)(const void *, const void *))community_cmp, NULL);
} }
void void community_finish(void)
community_finish (void)
{ {
hash_free(comhash); hash_free(comhash);
comhash = NULL; comhash = NULL;

View File

@ -24,8 +24,7 @@
#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;
@ -68,8 +67,10 @@ 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_delete(struct community *,
struct community *);
extern struct community *community_dup(struct community *); extern struct community *community_dup(struct community *);
extern int community_include(struct community *, u_int32_t); extern int community_include(struct community *, u_int32_t);
extern void community_del_val(struct community *, u_int32_t *); extern void community_del_val(struct community *, u_int32_t *);

View File

@ -46,13 +46,13 @@ static struct bgp_damp_config *damp = &bgp_damp_cfg;
#define BGP_DAMP_LIST_DEL(N,A) BGP_INFO_DEL(N,A,no_reuse_list) #define BGP_DAMP_LIST_DEL(N,A) BGP_INFO_DEL(N,A,no_reuse_list)
/* Calculate reuse list index by penalty value. */ /* Calculate reuse list index by penalty value. */
static int static int bgp_reuse_index(int penalty)
bgp_reuse_index (int penalty)
{ {
unsigned int i; unsigned int i;
int index; int index;
i = (int)(((double) penalty / damp->reuse_limit - 1.0) * damp->scale_factor); i = (int)(((double)penalty / damp->reuse_limit - 1.0)
* damp->scale_factor);
if (i >= damp->reuse_index_size) if (i >= damp->reuse_index_size)
i = damp->reuse_index_size - 1; i = damp->reuse_index_size - 1;
@ -63,8 +63,7 @@ bgp_reuse_index (int penalty)
} }
/* Add BGP dampening information to reuse list. */ /* Add BGP dampening information to reuse list. */
static void static void bgp_reuse_list_add(struct bgp_damp_info *bdi)
bgp_reuse_list_add (struct bgp_damp_info *bdi)
{ {
int index; int index;
@ -78,8 +77,7 @@ bgp_reuse_list_add (struct bgp_damp_info *bdi)
} }
/* Delete BGP dampening information from reuse list. */ /* Delete BGP dampening information from reuse list. */
static void static void bgp_reuse_list_delete(struct bgp_damp_info *bdi)
bgp_reuse_list_delete (struct bgp_damp_info *bdi)
{ {
if (bdi->next) if (bdi->next)
bdi->next->prev = bdi->prev; bdi->next->prev = bdi->prev;
@ -90,8 +88,7 @@ bgp_reuse_list_delete (struct bgp_damp_info *bdi)
} }
/* Return decayed penalty value. */ /* Return decayed penalty value. */
int int bgp_damp_decay(time_t tdiff, int penalty)
bgp_damp_decay (time_t tdiff, int penalty)
{ {
unsigned int i; unsigned int i;
@ -108,8 +105,7 @@ bgp_damp_decay (time_t tdiff, int penalty)
/* Handler of reuse timer event. Each route in the current reuse-list /* Handler of reuse timer event. Each route in the current reuse-list
is evaluated. RFC2439 Section 4.8.7. */ is evaluated. RFC2439 Section 4.8.7. */
static int static int bgp_reuse_timer(struct thread *t)
bgp_reuse_timer (struct thread *t)
{ {
struct bgp_damp_info *bdi; struct bgp_damp_info *bdi;
struct bgp_damp_info *next; struct bgp_damp_info *next;
@ -131,8 +127,7 @@ bgp_reuse_timer (struct thread *t)
damp->reuse_offset = (damp->reuse_offset + 1) % damp->reuse_list_size; damp->reuse_offset = (damp->reuse_offset + 1) % damp->reuse_list_size;
/* 3. if ( the saved list head pointer is non-empty ) */ /* 3. if ( the saved list head pointer is non-empty ) */
for (; bdi; bdi = next) for (; bdi; bdi = next) {
{
struct bgp *bgp = bdi->binfo->peer->bgp; struct bgp *bgp = bdi->binfo->peer->bgp;
next = bdi->next; next = bdi->next;
@ -140,24 +135,26 @@ bgp_reuse_timer (struct thread *t)
/* Set t-diff = t-now - t-updated. */ /* Set t-diff = t-now - t-updated. */
t_diff = t_now - bdi->t_updated; t_diff = t_now - bdi->t_updated;
/* Set figure-of-merit = figure-of-merit * decay-array-ok [t-diff] */ /* Set figure-of-merit = figure-of-merit * decay-array-ok
* [t-diff] */
bdi->penalty = bgp_damp_decay(t_diff, bdi->penalty); bdi->penalty = bgp_damp_decay(t_diff, bdi->penalty);
/* Set t-updated = t-now. */ /* Set t-updated = t-now. */
bdi->t_updated = t_now; bdi->t_updated = t_now;
/* if (figure-of-merit < reuse). */ /* if (figure-of-merit < reuse). */
if (bdi->penalty < damp->reuse_limit) if (bdi->penalty < damp->reuse_limit) {
{
/* Reuse the route. */ /* Reuse the route. */
bgp_info_unset_flag (bdi->rn, bdi->binfo, BGP_INFO_DAMPED); bgp_info_unset_flag(bdi->rn, bdi->binfo,
BGP_INFO_DAMPED);
bdi->suppress_time = 0; bdi->suppress_time = 0;
if (bdi->lastrecord == BGP_RECORD_UPDATE) if (bdi->lastrecord == BGP_RECORD_UPDATE) {
{ bgp_info_unset_flag(bdi->rn, bdi->binfo,
bgp_info_unset_flag (bdi->rn, bdi->binfo, BGP_INFO_HISTORY); BGP_INFO_HISTORY);
bgp_aggregate_increment (bgp, &bdi->rn->p, bdi->binfo, bgp_aggregate_increment(bgp, &bdi->rn->p,
bdi->afi, bdi->safi); bdi->binfo, bdi->afi,
bdi->safi);
bgp_process(bgp, bdi->rn, bdi->afi, bdi->safi); bgp_process(bgp, bdi->rn, bdi->afi, bdi->safi);
} }
@ -165,9 +162,9 @@ bgp_reuse_timer (struct thread *t)
bgp_damp_info_free(bdi, 1); bgp_damp_info_free(bdi, 1);
else else
BGP_DAMP_LIST_ADD(damp, bdi); BGP_DAMP_LIST_ADD(damp, bdi);
} } else
else /* Re-insert into another list (See RFC2439 Section
/* Re-insert into another list (See RFC2439 Section 4.8.6). */ * 4.8.6). */
bgp_reuse_list_add(bdi); bgp_reuse_list_add(bdi);
} }
@ -175,9 +172,8 @@ bgp_reuse_timer (struct thread *t)
} }
/* A route becomes unreachable (RFC2439 Section 4.8.2). */ /* A route becomes unreachable (RFC2439 Section 4.8.2). */
int int bgp_damp_withdraw(struct bgp_info *binfo, struct bgp_node *rn, afi_t afi,
bgp_damp_withdraw (struct bgp_info *binfo, struct bgp_node *rn, safi_t safi, int attr_change)
afi_t afi, safi_t safi, int attr_change)
{ {
time_t t_now; time_t t_now;
struct bgp_damp_info *bdi = NULL; struct bgp_damp_info *bdi = NULL;
@ -189,8 +185,7 @@ bgp_damp_withdraw (struct bgp_info *binfo, struct bgp_node *rn,
if (binfo->extra) if (binfo->extra)
bdi = binfo->extra->damp_info; bdi = binfo->extra->damp_info;
if (bdi == NULL) if (bdi == NULL) {
{
/* If there is no previous stability history. */ /* If there is no previous stability history. */
/* RFC2439 said: /* RFC2439 said:
@ -198,10 +193,12 @@ bgp_damp_withdraw (struct bgp_info *binfo, struct bgp_node *rn,
2. set figure-of-merit = 1. 2. set figure-of-merit = 1.
3. withdraw the route. */ 3. withdraw the route. */
bdi = XCALLOC (MTYPE_BGP_DAMP_INFO, sizeof (struct bgp_damp_info)); bdi = XCALLOC(MTYPE_BGP_DAMP_INFO,
sizeof(struct bgp_damp_info));
bdi->binfo = binfo; bdi->binfo = binfo;
bdi->rn = rn; bdi->rn = rn;
bdi->penalty = (attr_change ? DEFAULT_PENALTY / 2 : DEFAULT_PENALTY); bdi->penalty =
(attr_change ? DEFAULT_PENALTY / 2 : DEFAULT_PENALTY);
bdi->flap = 1; bdi->flap = 1;
bdi->start_time = t_now; bdi->start_time = t_now;
bdi->suppress_time = 0; bdi->suppress_time = 0;
@ -210,15 +207,14 @@ bgp_damp_withdraw (struct bgp_info *binfo, struct bgp_node *rn,
bdi->safi = safi; bdi->safi = safi;
(bgp_info_extra_get(binfo))->damp_info = bdi; (bgp_info_extra_get(binfo))->damp_info = bdi;
BGP_DAMP_LIST_ADD(damp, bdi); BGP_DAMP_LIST_ADD(damp, bdi);
} } else {
else
{
last_penalty = bdi->penalty; last_penalty = bdi->penalty;
/* 1. Set t-diff = t-now - t-updated. */ /* 1. Set t-diff = t-now - t-updated. */
bdi->penalty = bdi->penalty =
(bgp_damp_decay(t_now - bdi->t_updated, bdi->penalty) (bgp_damp_decay(t_now - bdi->t_updated, bdi->penalty)
+ (attr_change ? DEFAULT_PENALTY / 2 : DEFAULT_PENALTY)); + (attr_change ? DEFAULT_PENALTY / 2
: DEFAULT_PENALTY));
if (bdi->penalty > damp->ceiling) if (bdi->penalty > damp->ceiling)
bdi->penalty = damp->ceiling; bdi->penalty = damp->ceiling;
@ -235,11 +231,9 @@ bgp_damp_withdraw (struct bgp_info *binfo, struct bgp_node *rn,
bgp_info_set_flag(rn, binfo, BGP_INFO_HISTORY); bgp_info_set_flag(rn, binfo, BGP_INFO_HISTORY);
/* Remove the route from a reuse list if it is on one. */ /* Remove the route from a reuse list if it is on one. */
if (CHECK_FLAG (bdi->binfo->flags, BGP_INFO_DAMPED)) if (CHECK_FLAG(bdi->binfo->flags, BGP_INFO_DAMPED)) {
{
/* If decay rate isn't equal to 0, reinsert brn. */ /* If decay rate isn't equal to 0, reinsert brn. */
if (bdi->penalty != last_penalty) if (bdi->penalty != last_penalty) {
{
bgp_reuse_list_delete(bdi); bgp_reuse_list_delete(bdi);
bgp_reuse_list_add(bdi); bgp_reuse_list_add(bdi);
} }
@ -248,8 +242,7 @@ bgp_damp_withdraw (struct bgp_info *binfo, struct bgp_node *rn,
/* If not suppressed before, do annonunce this withdraw and /* If not suppressed before, do annonunce this withdraw and
insert into reuse_list. */ insert into reuse_list. */
if (bdi->penalty >= damp->suppress_value) if (bdi->penalty >= damp->suppress_value) {
{
bgp_info_set_flag(rn, binfo, BGP_INFO_DAMPED); bgp_info_set_flag(rn, binfo, BGP_INFO_DAMPED);
bdi->suppress_time = t_now; bdi->suppress_time = t_now;
BGP_DAMP_LIST_DEL(damp, bdi); BGP_DAMP_LIST_DEL(damp, bdi);
@ -259,9 +252,8 @@ bgp_damp_withdraw (struct bgp_info *binfo, struct bgp_node *rn,
return BGP_DAMP_USED; return BGP_DAMP_USED;
} }
int int bgp_damp_update(struct bgp_info *binfo, struct bgp_node *rn, afi_t afi,
bgp_damp_update (struct bgp_info *binfo, struct bgp_node *rn, safi_t safi)
afi_t afi, safi_t safi)
{ {
time_t t_now; time_t t_now;
struct bgp_damp_info *bdi; struct bgp_damp_info *bdi;
@ -280,15 +272,13 @@ bgp_damp_update (struct bgp_info *binfo, struct bgp_node *rn,
&& (bdi->penalty < damp->suppress_value)) && (bdi->penalty < damp->suppress_value))
status = BGP_DAMP_USED; status = BGP_DAMP_USED;
else if (CHECK_FLAG(bdi->binfo->flags, BGP_INFO_DAMPED) else if (CHECK_FLAG(bdi->binfo->flags, BGP_INFO_DAMPED)
&& (bdi->penalty < damp->reuse_limit) ) && (bdi->penalty < damp->reuse_limit)) {
{
bgp_info_unset_flag(rn, binfo, BGP_INFO_DAMPED); bgp_info_unset_flag(rn, binfo, BGP_INFO_DAMPED);
bgp_reuse_list_delete(bdi); bgp_reuse_list_delete(bdi);
BGP_DAMP_LIST_ADD(damp, bdi); BGP_DAMP_LIST_ADD(damp, bdi);
bdi->suppress_time = 0; bdi->suppress_time = 0;
status = BGP_DAMP_USED; status = BGP_DAMP_USED;
} } else
else
status = BGP_DAMP_SUPPRESSED; status = BGP_DAMP_SUPPRESSED;
if (bdi->penalty > damp->reuse_limit / 2.0) if (bdi->penalty > damp->reuse_limit / 2.0)
@ -300,8 +290,7 @@ bgp_damp_update (struct bgp_info *binfo, struct bgp_node *rn,
} }
/* Remove dampening information and history route. */ /* Remove dampening information and history route. */
int int bgp_damp_scan(struct bgp_info *binfo, afi_t afi, safi_t safi)
bgp_damp_scan (struct bgp_info *binfo, afi_t afi, safi_t safi)
{ {
time_t t_now, t_diff; time_t t_now, t_diff;
struct bgp_damp_info *bdi; struct bgp_damp_info *bdi;
@ -311,12 +300,10 @@ bgp_damp_scan (struct bgp_info *binfo, afi_t afi, safi_t safi)
t_now = bgp_clock(); t_now = bgp_clock();
bdi = binfo->extra->damp_info; bdi = binfo->extra->damp_info;
if (CHECK_FLAG (binfo->flags, BGP_INFO_DAMPED)) if (CHECK_FLAG(binfo->flags, BGP_INFO_DAMPED)) {
{
t_diff = t_now - bdi->suppress_time; t_diff = t_now - bdi->suppress_time;
if (t_diff >= damp->max_suppress_time) if (t_diff >= damp->max_suppress_time) {
{
bgp_info_unset_flag(bdi->rn, binfo, BGP_INFO_DAMPED); bgp_info_unset_flag(bdi->rn, binfo, BGP_INFO_DAMPED);
bgp_reuse_list_delete(bdi); bgp_reuse_list_delete(bdi);
BGP_DAMP_LIST_ADD(damp, bdi); BGP_DAMP_LIST_ADD(damp, bdi);
@ -324,32 +311,28 @@ bgp_damp_scan (struct bgp_info *binfo, afi_t afi, safi_t safi)
bdi->suppress_time = 0; bdi->suppress_time = 0;
bdi->t_updated = t_now; bdi->t_updated = t_now;
/* Need to announce UPDATE once this binfo is usable again. */ /* Need to announce UPDATE once this binfo is usable
* again. */
if (bdi->lastrecord == BGP_RECORD_UPDATE) if (bdi->lastrecord == BGP_RECORD_UPDATE)
return 1; return 1;
else else
return 0; return 0;
} }
} } else {
else
{
t_diff = t_now - bdi->t_updated; t_diff = t_now - bdi->t_updated;
bdi->penalty = bgp_damp_decay(t_diff, bdi->penalty); bdi->penalty = bgp_damp_decay(t_diff, bdi->penalty);
if (bdi->penalty <= damp->reuse_limit / 2.0) if (bdi->penalty <= damp->reuse_limit / 2.0) {
{
/* release the bdi, bdi->binfo. */ /* release the bdi, bdi->binfo. */
bgp_damp_info_free(bdi, 1); bgp_damp_info_free(bdi, 1);
return 0; return 0;
} } else
else
bdi->t_updated = t_now; bdi->t_updated = t_now;
} }
return 0; return 0;
} }
void void bgp_damp_info_free(struct bgp_damp_info *bdi, int withdraw)
bgp_damp_info_free (struct bgp_damp_info *bdi, int withdraw)
{ {
struct bgp_info *binfo; struct bgp_info *binfo;
@ -372,8 +355,7 @@ bgp_damp_info_free (struct bgp_damp_info *bdi, int withdraw)
XFREE(MTYPE_BGP_DAMP_INFO, bdi); XFREE(MTYPE_BGP_DAMP_INFO, bdi);
} }
static void static void bgp_damp_parameter_set(int hlife, int reuse, int sup, int maxsup)
bgp_damp_parameter_set (int hlife, int reuse, int sup, int maxsup)
{ {
double reuse_max_ratio; double reuse_max_ratio;
unsigned int i; unsigned int i;
@ -387,18 +369,24 @@ bgp_damp_parameter_set (int hlife, int reuse, int sup, int maxsup)
/* Initialize params per bgp_damp_config. */ /* Initialize params per bgp_damp_config. */
damp->reuse_index_size = REUSE_ARRAY_SIZE; damp->reuse_index_size = REUSE_ARRAY_SIZE;
damp->ceiling = (int)(damp->reuse_limit * (pow(2, (double)damp->max_suppress_time/damp->half_life))); damp->ceiling =
(int)(damp->reuse_limit * (pow(2,
(double)damp->max_suppress_time
/ damp->half_life)));
/* Decay-array computations */ /* Decay-array computations */
damp->decay_array_size = ceil ((double) damp->max_suppress_time / DELTA_T); damp->decay_array_size =
ceil((double)damp->max_suppress_time / DELTA_T);
damp->decay_array = XMALLOC(MTYPE_BGP_DAMP_ARRAY, damp->decay_array = XMALLOC(MTYPE_BGP_DAMP_ARRAY,
sizeof(double) * (damp->decay_array_size)); sizeof(double) * (damp->decay_array_size));
damp->decay_array[0] = 1.0; damp->decay_array[0] = 1.0;
damp->decay_array[1] = exp ((1.0/((double)damp->half_life/DELTA_T)) * log(0.5)); damp->decay_array[1] =
exp((1.0 / ((double)damp->half_life / DELTA_T)) * log(0.5));
/* Calculate decay values for all possible times */ /* Calculate decay values for all possible times */
for (i = 2; i < damp->decay_array_size; i++) for (i = 2; i < damp->decay_array_size; i++)
damp->decay_array[i] = damp->decay_array[i-1] * damp->decay_array[1]; damp->decay_array[i] =
damp->decay_array[i - 1] * damp->decay_array[1];
/* Reuse-list computations */ /* Reuse-list computations */
i = ceil((double)damp->max_suppress_time / DELTA_REUSE) + 1; i = ceil((double)damp->max_suppress_time / DELTA_REUSE) + 1;
@ -415,28 +403,29 @@ bgp_damp_parameter_set (int hlife, int reuse, int sup, int maxsup)
sizeof(int) * damp->reuse_index_size); sizeof(int) * damp->reuse_index_size);
reuse_max_ratio = (double)damp->ceiling / damp->reuse_limit; reuse_max_ratio = (double)damp->ceiling / damp->reuse_limit;
j = (exp((double)damp->max_suppress_time/damp->half_life) * log10(2.0)); j = (exp((double)damp->max_suppress_time / damp->half_life)
* log10(2.0));
if (reuse_max_ratio > j && j != 0) if (reuse_max_ratio > j && j != 0)
reuse_max_ratio = j; reuse_max_ratio = j;
damp->scale_factor = (double)damp->reuse_index_size/(reuse_max_ratio - 1); damp->scale_factor =
(double)damp->reuse_index_size / (reuse_max_ratio - 1);
for (i = 0; i < damp->reuse_index_size; i++) for (i = 0; i < damp->reuse_index_size; i++) {
{
damp->reuse_index[i] = damp->reuse_index[i] =
(int)(((double)damp->half_life / DELTA_REUSE) (int)(((double)damp->half_life / DELTA_REUSE)
* log10 (1.0 / (damp->reuse_limit * ( 1.0 + ((double)i/damp->scale_factor)))) / log10(0.5)); * log10(1.0 / (damp->reuse_limit
* (1.0 + ((double)i
/ damp->scale_factor))))
/ log10(0.5));
} }
} }
int int bgp_damp_enable(struct bgp *bgp, afi_t afi, safi_t safi, time_t half,
bgp_damp_enable (struct bgp *bgp, afi_t afi, safi_t safi, time_t half,
unsigned int reuse, unsigned int suppress, time_t max) unsigned int reuse, unsigned int suppress, time_t max)
{ {
if (CHECK_FLAG (bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)) if (CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)) {
{ if (damp->half_life == half && damp->reuse_limit == reuse
if (damp->half_life == half
&& damp->reuse_limit == reuse
&& damp->suppress_value == suppress && damp->suppress_value == suppress
&& damp->max_suppress_time == max) && damp->max_suppress_time == max)
return 0; return 0;
@ -453,8 +442,7 @@ bgp_damp_enable (struct bgp *bgp, afi_t afi, safi_t safi, time_t half,
return 0; return 0;
} }
static void static void bgp_damp_config_clean(struct bgp_damp_config *damp)
bgp_damp_config_clean (struct bgp_damp_config *damp)
{ {
/* Free decay array */ /* Free decay array */
XFREE(MTYPE_BGP_DAMP_ARRAY, damp->decay_array); XFREE(MTYPE_BGP_DAMP_ARRAY, damp->decay_array);
@ -467,37 +455,32 @@ bgp_damp_config_clean (struct bgp_damp_config *damp)
} }
/* Clean all the bgp_damp_info stored in reuse_list. */ /* Clean all the bgp_damp_info stored in reuse_list. */
void void bgp_damp_info_clean(void)
bgp_damp_info_clean (void)
{ {
unsigned int i; unsigned int i;
struct bgp_damp_info *bdi, *next; struct bgp_damp_info *bdi, *next;
damp->reuse_offset = 0; damp->reuse_offset = 0;
for (i = 0; i < damp->reuse_list_size; i++) for (i = 0; i < damp->reuse_list_size; i++) {
{
if (!damp->reuse_list[i]) if (!damp->reuse_list[i])
continue; continue;
for (bdi = damp->reuse_list[i]; bdi; bdi = next) for (bdi = damp->reuse_list[i]; bdi; bdi = next) {
{
next = bdi->next; next = bdi->next;
bgp_damp_info_free(bdi, 1); bgp_damp_info_free(bdi, 1);
} }
damp->reuse_list[i] = NULL; damp->reuse_list[i] = NULL;
} }
for (bdi = damp->no_reuse_list; bdi; bdi = next) for (bdi = damp->no_reuse_list; bdi; bdi = next) {
{
next = bdi->next; next = bdi->next;
bgp_damp_info_free(bdi, 1); bgp_damp_info_free(bdi, 1);
} }
damp->no_reuse_list = NULL; damp->no_reuse_list = NULL;
} }
int int bgp_damp_disable(struct bgp *bgp, afi_t afi, safi_t safi)
bgp_damp_disable (struct bgp *bgp, afi_t afi, safi_t safi)
{ {
/* If it wasn't enabled, there's nothing to do. */ /* If it wasn't enabled, there's nothing to do. */
if (!CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)) if (!CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING))
@ -518,96 +501,96 @@ bgp_damp_disable (struct bgp *bgp, afi_t afi, safi_t safi)
return 0; return 0;
} }
void void bgp_config_write_damp(struct vty *vty)
bgp_config_write_damp (struct vty *vty)
{ {
if (bgp_damp_cfg.half_life == DEFAULT_HALF_LIFE * 60 if (bgp_damp_cfg.half_life == DEFAULT_HALF_LIFE * 60
&& bgp_damp_cfg.reuse_limit == DEFAULT_REUSE && bgp_damp_cfg.reuse_limit == DEFAULT_REUSE
&& bgp_damp_cfg.suppress_value == DEFAULT_SUPPRESS && bgp_damp_cfg.suppress_value == DEFAULT_SUPPRESS
&& bgp_damp_cfg.max_suppress_time == bgp_damp_cfg.half_life * 4) && bgp_damp_cfg.max_suppress_time == bgp_damp_cfg.half_life * 4)
vty_outln (vty, " bgp dampening"); vty_out(vty, " bgp dampening\n");
else if (bgp_damp_cfg.half_life != DEFAULT_HALF_LIFE * 60 else if (bgp_damp_cfg.half_life != DEFAULT_HALF_LIFE * 60
&& bgp_damp_cfg.reuse_limit == DEFAULT_REUSE && bgp_damp_cfg.reuse_limit == DEFAULT_REUSE
&& bgp_damp_cfg.suppress_value == DEFAULT_SUPPRESS && bgp_damp_cfg.suppress_value == DEFAULT_SUPPRESS
&& bgp_damp_cfg.max_suppress_time == bgp_damp_cfg.half_life*4) && bgp_damp_cfg.max_suppress_time
vty_outln (vty, " bgp dampening %lld", == bgp_damp_cfg.half_life * 4)
vty_out(vty, " bgp dampening %lld\n",
bgp_damp_cfg.half_life / 60LL); bgp_damp_cfg.half_life / 60LL);
else else
vty_outln (vty, " bgp dampening %lld %d %d %lld", vty_out(vty, " bgp dampening %lld %d %d %lld\n",
bgp_damp_cfg.half_life/60LL, bgp_damp_cfg.half_life / 60LL, bgp_damp_cfg.reuse_limit,
bgp_damp_cfg.reuse_limit,
bgp_damp_cfg.suppress_value, bgp_damp_cfg.suppress_value,
bgp_damp_cfg.max_suppress_time / 60LL); bgp_damp_cfg.max_suppress_time / 60LL);
} }
static const char * static const char *bgp_get_reuse_time(unsigned int penalty, char *buf,
bgp_get_reuse_time (unsigned int penalty, char *buf, size_t len, u_char use_json, json_object *json) size_t len, u_char use_json,
json_object *json)
{ {
time_t reuse_time = 0; time_t reuse_time = 0;
struct tm *tm = NULL; struct tm *tm = NULL;
int time_store = 0; int time_store = 0;
if (penalty > damp->reuse_limit) if (penalty > damp->reuse_limit) {
{ reuse_time = (int)(DELTA_T
reuse_time = (int) (DELTA_T * ((log((double)damp->reuse_limit/penalty))/(log(damp->decay_array[1])))); * ((log((double)damp->reuse_limit / penalty))
/ (log(damp->decay_array[1]))));
if (reuse_time > damp->max_suppress_time) if (reuse_time > damp->max_suppress_time)
reuse_time = damp->max_suppress_time; reuse_time = damp->max_suppress_time;
tm = gmtime(&reuse_time); tm = gmtime(&reuse_time);
} } else
else
reuse_time = 0; reuse_time = 0;
/* Making formatted timer strings. */ /* Making formatted timer strings. */
#define ONE_DAY_SECOND 60*60*24 #define ONE_DAY_SECOND 60*60*24
#define ONE_WEEK_SECOND 60*60*24*7 #define ONE_WEEK_SECOND 60*60*24*7
if (reuse_time == 0) if (reuse_time == 0) {
{
if (use_json) if (use_json)
json_object_int_add(json, "reuseTimerMsecs", 0); json_object_int_add(json, "reuseTimerMsecs", 0);
else else
snprintf(buf, len, "00:00:00"); snprintf(buf, len, "00:00:00");
} } else if (reuse_time < ONE_DAY_SECOND) {
else if (reuse_time < ONE_DAY_SECOND) if (use_json) {
{ time_store = (3600000 * tm->tm_hour)
if (use_json) + (60000 * tm->tm_min)
{ + (1000 * tm->tm_sec);
time_store = (3600000 * tm->tm_hour) + (60000 * tm->tm_min) + (1000 * tm->tm_sec); json_object_int_add(json, "reuseTimerMsecs",
json_object_int_add(json, "reuseTimerMsecs", time_store); time_store);
} } else
else snprintf(buf, len, "%02d:%02d:%02d", tm->tm_hour,
snprintf (buf, len, "%02d:%02d:%02d", tm->tm_min, tm->tm_sec);
tm->tm_hour, tm->tm_min, tm->tm_sec); } else if (reuse_time < ONE_WEEK_SECOND) {
} if (use_json) {
else if (reuse_time < ONE_WEEK_SECOND) time_store = (86400000 * tm->tm_yday)
{ + (3600000 * tm->tm_hour)
if (use_json) + (60000 * tm->tm_min)
{ + (1000 * tm->tm_sec);
time_store = (86400000 * tm->tm_yday) + (3600000 * tm->tm_hour) + (60000 * tm->tm_min) + (1000 * tm->tm_sec); json_object_int_add(json, "reuseTimerMsecs",
json_object_int_add(json, "reuseTimerMsecs", time_store); time_store);
} } else
else snprintf(buf, len, "%dd%02dh%02dm", tm->tm_yday,
snprintf (buf, len, "%dd%02dh%02dm", tm->tm_hour, tm->tm_min);
tm->tm_yday, tm->tm_hour, tm->tm_min); } else {
} if (use_json) {
else time_store =
{ (604800000 * tm->tm_yday / 7)
if (use_json) + (86400000
{ * (tm->tm_yday - ((tm->tm_yday / 7) * 7)))
time_store = (604800000 * tm->tm_yday/7) + (86400000 * (tm->tm_yday - ((tm->tm_yday/7) * 7))) + (3600000 * tm->tm_hour) + (60000 * tm->tm_min) + (1000 * tm->tm_sec); + (3600000 * tm->tm_hour) + (60000 * tm->tm_min)
json_object_int_add(json, "reuseTimerMsecs", time_store); + (1000 * tm->tm_sec);
} json_object_int_add(json, "reuseTimerMsecs",
else time_store);
snprintf (buf, len, "%02dw%dd%02dh", } else
tm->tm_yday/7, tm->tm_yday - ((tm->tm_yday/7) * 7), tm->tm_hour); snprintf(buf, len, "%02dw%dd%02dh", tm->tm_yday / 7,
tm->tm_yday - ((tm->tm_yday / 7) * 7),
tm->tm_hour);
} }
return buf; return buf;
} }
void void bgp_damp_info_vty(struct vty *vty, struct bgp_info *binfo,
bgp_damp_info_vty (struct vty *vty, struct bgp_info *binfo,
json_object *json_path) json_object *json_path)
{ {
struct bgp_damp_info *bdi; struct bgp_damp_info *bdi;
@ -631,34 +614,37 @@ bgp_damp_info_vty (struct vty *vty, struct bgp_info *binfo,
t_diff = t_now - bdi->t_updated; t_diff = t_now - bdi->t_updated;
penalty = bgp_damp_decay(t_diff, bdi->penalty); penalty = bgp_damp_decay(t_diff, bdi->penalty);
if (json_path) if (json_path) {
{
json_object_int_add(json_path, "dampeningPenalty", penalty); json_object_int_add(json_path, "dampeningPenalty", penalty);
json_object_int_add(json_path, "dampeningFlapCount", bdi->flap); json_object_int_add(json_path, "dampeningFlapCount", bdi->flap);
peer_uptime (bdi->start_time, timebuf, BGP_UPTIME_LEN, 1, json_path); peer_uptime(bdi->start_time, timebuf, BGP_UPTIME_LEN, 1,
json_path);
if (CHECK_FLAG(binfo->flags, BGP_INFO_DAMPED) if (CHECK_FLAG(binfo->flags, BGP_INFO_DAMPED)
&& !CHECK_FLAG(binfo->flags, BGP_INFO_HISTORY)) && !CHECK_FLAG(binfo->flags, BGP_INFO_HISTORY))
bgp_get_reuse_time (penalty, timebuf, BGP_UPTIME_LEN, 1, json_path); bgp_get_reuse_time(penalty, timebuf, BGP_UPTIME_LEN, 1,
} json_path);
else } else {
{ vty_out(vty,
vty_out (vty, " Dampinfo: penalty %d, flapped %d times in %s", " Dampinfo: penalty %d, flapped %d times in %s",
penalty, bdi->flap, penalty, bdi->flap,
peer_uptime (bdi->start_time, timebuf, BGP_UPTIME_LEN, 0, json_path)); peer_uptime(bdi->start_time, timebuf, BGP_UPTIME_LEN, 0,
json_path));
if (CHECK_FLAG(binfo->flags, BGP_INFO_DAMPED) if (CHECK_FLAG(binfo->flags, BGP_INFO_DAMPED)
&& !CHECK_FLAG(binfo->flags, BGP_INFO_HISTORY)) && !CHECK_FLAG(binfo->flags, BGP_INFO_HISTORY))
vty_out(vty, ", reuse in %s", vty_out(vty, ", reuse in %s",
bgp_get_reuse_time (penalty, timebuf, BGP_UPTIME_LEN, 0, json_path)); bgp_get_reuse_time(penalty, timebuf,
BGP_UPTIME_LEN, 0,
json_path));
vty_out (vty, VTYNL); vty_out(vty, "\n");
} }
} }
const char * const char *bgp_damp_reuse_time_vty(struct vty *vty, struct bgp_info *binfo,
bgp_damp_reuse_time_vty (struct vty *vty, struct bgp_info *binfo, char *timebuf, size_t len, u_char use_json,
char *timebuf, size_t len, u_char use_json, json_object *json) json_object *json)
{ {
struct bgp_damp_info *bdi; struct bgp_damp_info *bdi;
time_t t_now, t_diff; time_t t_now, t_diff;
@ -683,34 +669,27 @@ bgp_damp_reuse_time_vty (struct vty *vty, struct bgp_info *binfo,
return bgp_get_reuse_time(penalty, timebuf, len, use_json, json); return bgp_get_reuse_time(penalty, timebuf, len, use_json, json);
} }
int int bgp_show_dampening_parameters(struct vty *vty, afi_t afi, safi_t safi)
bgp_show_dampening_parameters (struct vty *vty, afi_t afi, safi_t safi)
{ {
struct bgp *bgp; struct bgp *bgp;
bgp = bgp_get_default(); bgp = bgp_get_default();
if (bgp == NULL) if (bgp == NULL) {
{ vty_out(vty, "No BGP process is configured\n");
vty_outln (vty, "No BGP process is configured");
return CMD_WARNING; return CMD_WARNING;
} }
if (CHECK_FLAG (bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)) if (CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)) {
{ vty_out(vty, "Half-life time: %lld min\n",
vty_outln (vty, "Half-life time: %lld min",
(long long)damp->half_life / 60); (long long)damp->half_life / 60);
vty_outln (vty, "Reuse penalty: %d", vty_out(vty, "Reuse penalty: %d\n", damp->reuse_limit);
damp->reuse_limit); vty_out(vty, "Suppress penalty: %d\n", damp->suppress_value);
vty_outln (vty, "Suppress penalty: %d", vty_out(vty, "Max suppress time: %lld min\n",
damp->suppress_value);
vty_outln (vty, "Max suppress time: %lld min",
(long long)damp->max_suppress_time / 60); (long long)damp->max_suppress_time / 60);
vty_outln (vty, "Max supress penalty: %u", vty_out(vty, "Max supress penalty: %u\n", damp->ceiling);
damp->ceiling); vty_out(vty, "\n");
vty_out (vty, VTYNL); } else
} vty_out(vty, "dampening not enabled for %s\n",
else
vty_outln (vty, "dampening not enabled for %s",
afi == AFI_IP ? "IPv4" : "IPv6"); afi == AFI_IP ? "IPv4" : "IPv6");
return CMD_SUCCESS; return CMD_SUCCESS;

View File

@ -22,8 +22,7 @@
#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;
@ -63,8 +62,7 @@ struct bgp_damp_info
}; };
/* 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;
@ -132,17 +130,19 @@ struct bgp_damp_config
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 *,
json_object *json_path);
extern const char *bgp_damp_reuse_time_vty(struct vty *, struct bgp_info *, extern const char *bgp_damp_reuse_time_vty(struct vty *, struct bgp_info *,
char *, size_t, u_char, json_object *); char *, size_t, u_char,
json_object *);
extern int bgp_show_dampening_parameters(struct vty *vty, afi_t, safi_t); 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

@ -92,8 +92,7 @@ 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;
}; };
@ -153,8 +152,10 @@ 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 *,
union prefixconstptr, mpls_label_t *,
int, u_int32_t, char *, int); int, u_int32_t, char *, int);
const char *bgp_notify_admin_message(char *buf, size_t bufsz, u_char *data, size_t datalen); 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 */

View File

@ -37,8 +37,7 @@
#include "bgpd/bgp_attr.h" #include "bgpd/bgp_attr.h"
#include "bgpd/bgp_dump.h" #include "bgpd/bgp_dump.h"
enum bgp_dump_type enum bgp_dump_type {
{
BGP_DUMP_ALL, BGP_DUMP_ALL,
BGP_DUMP_ALL_ET, BGP_DUMP_ALL_ET,
BGP_DUMP_UPDATES, BGP_DUMP_UPDATES,
@ -49,14 +48,10 @@ enum bgp_dump_type
static const struct bgp_dump_type_map { static const struct bgp_dump_type_map {
enum bgp_dump_type type; enum bgp_dump_type type;
const char *str; const char *str;
} bgp_dump_type_map[] = } bgp_dump_type_map[] = {
{ {BGP_DUMP_ALL, "all"}, {BGP_DUMP_ALL_ET, "all-et"},
{BGP_DUMP_ALL, "all"}, {BGP_DUMP_UPDATES, "updates"}, {BGP_DUMP_UPDATES_ET, "updates-et"},
{BGP_DUMP_ALL_ET, "all-et"}, {BGP_DUMP_ROUTES, "routes-mrt"}, {0, NULL},
{BGP_DUMP_UPDATES, "updates"},
{BGP_DUMP_UPDATES_ET, "updates-et"},
{BGP_DUMP_ROUTES, "routes-mrt"},
{0, NULL},
}; };
enum MRT_MSG_TYPES { enum MRT_MSG_TYPES {
@ -76,8 +71,7 @@ enum MRT_MSG_TYPES {
MSG_TABLE_DUMP_V2 /* routing table dump, version 2 */ MSG_TABLE_DUMP_V2 /* routing table dump, version 2 */
}; };
struct bgp_dump struct bgp_dump {
{
enum bgp_dump_type type; enum bgp_dump_type type;
char *filename; char *filename;
@ -106,8 +100,7 @@ struct bgp_dump bgp_dump_updates;
/* BGP dump structure for 'dump bgp routes' */ /* BGP dump structure for 'dump bgp routes' */
struct bgp_dump bgp_dump_routes; struct bgp_dump bgp_dump_routes;
static FILE * static FILE *bgp_dump_open_file(struct bgp_dump *bgp_dump)
bgp_dump_open_file (struct bgp_dump *bgp_dump)
{ {
int ret; int ret;
time_t clock; time_t clock;
@ -119,16 +112,13 @@ bgp_dump_open_file (struct bgp_dump *bgp_dump)
time(&clock); time(&clock);
tm = localtime(&clock); tm = localtime(&clock);
if (bgp_dump->filename[0] != DIRECTORY_SEP) if (bgp_dump->filename[0] != DIRECTORY_SEP) {
{
sprintf(fullpath, "%s/%s", vty_get_cwd(), bgp_dump->filename); sprintf(fullpath, "%s/%s", vty_get_cwd(), bgp_dump->filename);
ret = strftime(realpath, MAXPATHLEN, fullpath, tm); ret = strftime(realpath, MAXPATHLEN, fullpath, tm);
} } else
else
ret = strftime(realpath, MAXPATHLEN, bgp_dump->filename, tm); ret = strftime(realpath, MAXPATHLEN, bgp_dump->filename, tm);
if (ret == 0) if (ret == 0) {
{
zlog_warn("bgp_dump_open_file: strftime error"); zlog_warn("bgp_dump_open_file: strftime error");
return NULL; return NULL;
} }
@ -140,9 +130,9 @@ bgp_dump_open_file (struct bgp_dump *bgp_dump)
oldumask = umask(0777 & ~LOGFILE_MASK); oldumask = umask(0777 & ~LOGFILE_MASK);
bgp_dump->fp = fopen(realpath, "w"); bgp_dump->fp = fopen(realpath, "w");
if (bgp_dump->fp == NULL) if (bgp_dump->fp == NULL) {
{ zlog_warn("bgp_dump_open_file: %s: %s", realpath,
zlog_warn ("bgp_dump_open_file: %s: %s", realpath, strerror (errno)); strerror(errno));
umask(oldumask); umask(oldumask);
return NULL; return NULL;
} }
@ -151,44 +141,44 @@ bgp_dump_open_file (struct bgp_dump *bgp_dump)
return bgp_dump->fp; return bgp_dump->fp;
} }
static int static int bgp_dump_interval_add(struct bgp_dump *bgp_dump, int interval)
bgp_dump_interval_add (struct bgp_dump *bgp_dump, int interval)
{ {
int secs_into_day; int secs_into_day;
time_t t; time_t t;
struct tm *tm; struct tm *tm;
if (interval > 0) if (interval > 0) {
{
/* Periodic dump every interval seconds */ /* Periodic dump every interval seconds */
if ((interval < 86400) && ((86400 % interval) == 0)) if ((interval < 86400) && ((86400 % interval) == 0)) {
{ /* Dump at predictable times: if a day has a whole
/* Dump at predictable times: if a day has a whole number of * number of
* intervals, dump every interval seconds starting from midnight * intervals, dump every interval seconds starting from
* midnight
*/ */
(void)time(&t); (void)time(&t);
tm = localtime(&t); tm = localtime(&t);
secs_into_day = tm->tm_sec + 60*tm->tm_min + 60*60*tm->tm_hour; secs_into_day = tm->tm_sec + 60 * tm->tm_min
interval = interval - secs_into_day % interval; /* always > 0 */ + 60 * 60 * tm->tm_hour;
interval = interval
- secs_into_day % interval; /* always > 0 */
} }
bgp_dump->t_interval = NULL; bgp_dump->t_interval = NULL;
thread_add_timer(bm->master, bgp_dump_interval_func, bgp_dump, interval, thread_add_timer(bm->master, bgp_dump_interval_func, bgp_dump,
&bgp_dump->t_interval); interval, &bgp_dump->t_interval);
} } else {
else /* One-off dump: execute immediately, don't affect any scheduled
{ * dumps */
/* One-off dump: execute immediately, don't affect any scheduled dumps */
bgp_dump->t_interval = NULL; bgp_dump->t_interval = NULL;
thread_add_event(bm->master, bgp_dump_interval_func, bgp_dump, 0, thread_add_event(bm->master, bgp_dump_interval_func, bgp_dump,
&bgp_dump->t_interval); 0, &bgp_dump->t_interval);
} }
return 0; return 0;
} }
/* Dump common header. */ /* Dump common header. */
static void static void bgp_dump_header(struct stream *obuf, int type, int subtype,
bgp_dump_header (struct stream *obuf, int type, int subtype, int dump_type) int dump_type)
{ {
struct timeval clock; struct timeval clock;
long msecs; long msecs;
@ -214,8 +204,7 @@ bgp_dump_header (struct stream *obuf, int type, int subtype, int dump_type)
stream_putl(obuf, msecs); stream_putl(obuf, msecs);
} }
static void static void bgp_dump_set_size(struct stream *s, int type)
bgp_dump_set_size (struct stream *s, int type)
{ {
/* /*
* The BGP_DUMP_HEADER_SIZE stay at 12 event when ET: * The BGP_DUMP_HEADER_SIZE stay at 12 event when ET:
@ -225,8 +214,7 @@ bgp_dump_set_size (struct stream *s, int type)
stream_putl_at(s, 8, stream_get_endp(s) - BGP_DUMP_HEADER_SIZE); stream_putl_at(s, 8, stream_get_endp(s) - BGP_DUMP_HEADER_SIZE);
} }
static void static void bgp_dump_routes_index_table(struct bgp *bgp)
bgp_dump_routes_index_table(struct bgp *bgp)
{ {
struct peer *peer; struct peer *peer;
struct listnode *node; struct listnode *node;
@ -244,13 +232,10 @@ bgp_dump_routes_index_table(struct bgp *bgp)
stream_put_in_addr(obuf, &bgp->router_id); stream_put_in_addr(obuf, &bgp->router_id);
/* View name */ /* View name */
if(bgp->name) if (bgp->name) {
{
stream_putw(obuf, strlen(bgp->name)); stream_putw(obuf, strlen(bgp->name));
stream_put(obuf, bgp->name, strlen(bgp->name)); stream_put(obuf, bgp->name, strlen(bgp->name));
} } else {
else
{
stream_putw(obuf, 0); stream_putw(obuf, 0);
} }
@ -259,7 +244,9 @@ bgp_dump_routes_index_table(struct bgp *bgp)
/* Populate fake peer at index 0, for locally originated routes */ /* Populate fake peer at index 0, for locally originated routes */
/* Peer type (IPv4) */ /* Peer type (IPv4) */
stream_putc (obuf, TABLE_DUMP_V2_PEER_INDEX_TABLE_AS4+TABLE_DUMP_V2_PEER_INDEX_TABLE_IP); stream_putc(obuf,
TABLE_DUMP_V2_PEER_INDEX_TABLE_AS4
+ TABLE_DUMP_V2_PEER_INDEX_TABLE_IP);
/* Peer BGP ID (0.0.0.0) */ /* Peer BGP ID (0.0.0.0) */
stream_putl(obuf, 0); stream_putl(obuf, 0);
/* Peer IP address (0.0.0.0) */ /* Peer IP address (0.0.0.0) */
@ -268,35 +255,35 @@ bgp_dump_routes_index_table(struct bgp *bgp)
stream_putl(obuf, 0); stream_putl(obuf, 0);
/* Walk down all peers */ /* Walk down all peers */
for(ALL_LIST_ELEMENTS_RO (bgp->peer, node, peer)) for (ALL_LIST_ELEMENTS_RO(bgp->peer, node, peer)) {
{
/* Peer's type */ /* Peer's type */
if (sockunion_family(&peer->su) == AF_INET) if (sockunion_family(&peer->su) == AF_INET) {
{ stream_putc(
stream_putc (obuf, TABLE_DUMP_V2_PEER_INDEX_TABLE_AS4+TABLE_DUMP_V2_PEER_INDEX_TABLE_IP); obuf,
} TABLE_DUMP_V2_PEER_INDEX_TABLE_AS4
else if (sockunion_family(&peer->su) == AF_INET6) + TABLE_DUMP_V2_PEER_INDEX_TABLE_IP);
{ } else if (sockunion_family(&peer->su) == AF_INET6) {
stream_putc (obuf, TABLE_DUMP_V2_PEER_INDEX_TABLE_AS4+TABLE_DUMP_V2_PEER_INDEX_TABLE_IP6); stream_putc(
obuf,
TABLE_DUMP_V2_PEER_INDEX_TABLE_AS4
+ TABLE_DUMP_V2_PEER_INDEX_TABLE_IP6);
} }
/* Peer's BGP ID */ /* Peer's BGP ID */
stream_put_in_addr(obuf, &peer->remote_id); stream_put_in_addr(obuf, &peer->remote_id);
/* Peer's IP address */ /* Peer's IP address */
if (sockunion_family(&peer->su) == AF_INET) if (sockunion_family(&peer->su) == AF_INET) {
{
stream_put_in_addr(obuf, &peer->su.sin.sin_addr); stream_put_in_addr(obuf, &peer->su.sin.sin_addr);
} } else if (sockunion_family(&peer->su) == AF_INET6) {
else if (sockunion_family(&peer->su) == AF_INET6)
{
stream_write(obuf, (u_char *)&peer->su.sin6.sin6_addr, stream_write(obuf, (u_char *)&peer->su.sin6.sin6_addr,
IPV6_MAX_BYTELEN); IPV6_MAX_BYTELEN);
} }
/* Peer's AS number. */ /* Peer's AS number. */
/* Note that, as this is an AS4 compliant quagga, the RIB is always AS4 */ /* Note that, as this is an AS4 compliant quagga, the RIB is
* always AS4 */
stream_putl(obuf, peer->as); stream_putl(obuf, peer->as);
/* Store the peer number for this peer */ /* Store the peer number for this peer */
@ -311,9 +298,9 @@ bgp_dump_routes_index_table(struct bgp *bgp)
} }
static struct bgp_info * static struct bgp_info *bgp_dump_route_node_record(int afi, struct bgp_node *rn,
bgp_dump_route_node_record (int afi, struct bgp_node *rn, struct bgp_info *info,
struct bgp_info *info, unsigned int seq) unsigned int seq)
{ {
struct stream *obuf; struct stream *obuf;
size_t sizep; size_t sizep;
@ -324,10 +311,12 @@ bgp_dump_route_node_record (int afi, struct bgp_node *rn,
/* MRT header */ /* MRT header */
if (afi == AFI_IP) if (afi == AFI_IP)
bgp_dump_header (obuf, MSG_TABLE_DUMP_V2, TABLE_DUMP_V2_RIB_IPV4_UNICAST, bgp_dump_header(obuf, MSG_TABLE_DUMP_V2,
TABLE_DUMP_V2_RIB_IPV4_UNICAST,
BGP_DUMP_ROUTES); BGP_DUMP_ROUTES);
else if (afi == AFI_IP6) else if (afi == AFI_IP6)
bgp_dump_header (obuf, MSG_TABLE_DUMP_V2, TABLE_DUMP_V2_RIB_IPV6_UNICAST, bgp_dump_header(obuf, MSG_TABLE_DUMP_V2,
TABLE_DUMP_V2_RIB_IPV6_UNICAST,
BGP_DUMP_ROUTES); BGP_DUMP_ROUTES);
/* Sequence number */ /* Sequence number */
@ -337,15 +326,16 @@ bgp_dump_route_node_record (int afi, struct bgp_node *rn,
stream_putc(obuf, rn->p.prefixlen); stream_putc(obuf, rn->p.prefixlen);
/* Prefix */ /* Prefix */
if (afi == AFI_IP) if (afi == AFI_IP) {
{ /* We'll dump only the useful bits (those not 0), but have to
/* We'll dump only the useful bits (those not 0), but have to align on 8 bits */ * align on 8 bits */
stream_write (obuf, (u_char *)&rn->p.u.prefix4, (rn->p.prefixlen+7)/8); stream_write(obuf, (u_char *)&rn->p.u.prefix4,
} (rn->p.prefixlen + 7) / 8);
else if (afi == AFI_IP6) } else if (afi == AFI_IP6) {
{ /* We'll dump only the useful bits (those not 0), but have to
/* We'll dump only the useful bits (those not 0), but have to align on 8 bits */ * align on 8 bits */
stream_write (obuf, (u_char *)&rn->p.u.prefix6, (rn->p.prefixlen+7)/8); stream_write(obuf, (u_char *)&rn->p.u.prefix6,
(rn->p.prefixlen + 7) / 8);
} }
/* Save where we are now, so we can overwride the entry count later */ /* Save where we are now, so we can overwride the entry count later */
@ -358,8 +348,7 @@ bgp_dump_route_node_record (int afi, struct bgp_node *rn,
stream_putw(obuf, 0); stream_putw(obuf, 0);
endp = stream_get_endp(obuf); endp = stream_get_endp(obuf);
for (; info; info = info->next) for (; info; info = info->next) {
{
size_t cur_endp; size_t cur_endp;
/* Peer index */ /* Peer index */
@ -374,8 +363,7 @@ bgp_dump_route_node_record (int afi, struct bgp_node *rn,
cur_endp = stream_get_endp(obuf); cur_endp = stream_get_endp(obuf);
if (cur_endp > BGP_MAX_PACKET_SIZE + BGP_DUMP_MSG_HEADER if (cur_endp > BGP_MAX_PACKET_SIZE + BGP_DUMP_MSG_HEADER
+ BGP_DUMP_HEADER_SIZE) + BGP_DUMP_HEADER_SIZE) {
{
stream_set_endp(obuf, endp); stream_set_endp(obuf, endp);
break; break;
} }
@ -395,8 +383,8 @@ bgp_dump_route_node_record (int afi, struct bgp_node *rn,
/* Runs under child process. */ /* Runs under child process. */
static unsigned int static unsigned int bgp_dump_routes_func(int afi, int first_run,
bgp_dump_routes_func (int afi, int first_run, unsigned int seq) unsigned int seq)
{ {
struct bgp_info *info; struct bgp_info *info;
struct bgp_node *rn; struct bgp_node *rn;
@ -411,7 +399,8 @@ bgp_dump_routes_func (int afi, int first_run, unsigned int seq)
return seq; return seq;
/* Note that bgp_dump_routes_index_table will do ipv4 and ipv6 peers, /* Note that bgp_dump_routes_index_table will do ipv4 and ipv6 peers,
so this should only be done on the first call to bgp_dump_routes_func. so this should only be done on the first call to
bgp_dump_routes_func.
( this function will be called once for ipv4 and once for ipv6 ) */ ( this function will be called once for ipv4 and once for ipv6 ) */
if (first_run) if (first_run)
bgp_dump_routes_index_table(bgp); bgp_dump_routes_index_table(bgp);
@ -419,11 +408,9 @@ bgp_dump_routes_func (int afi, int first_run, unsigned int seq)
/* Walk down each BGP route. */ /* Walk down each BGP route. */
table = bgp->rib[afi][SAFI_UNICAST]; table = bgp->rib[afi][SAFI_UNICAST];
for (rn = bgp_table_top (table); rn; rn = bgp_route_next (rn)) for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
{
info = rn->info; info = rn->info;
while (info) while (info) {
{
info = bgp_dump_route_node_record(afi, rn, info, seq); info = bgp_dump_route_node_record(afi, rn, info, seq);
seq++; seq++;
} }
@ -434,24 +421,24 @@ bgp_dump_routes_func (int afi, int first_run, unsigned int seq)
return seq; return seq;
} }
static int static int bgp_dump_interval_func(struct thread *t)
bgp_dump_interval_func (struct thread *t)
{ {
struct bgp_dump *bgp_dump; struct bgp_dump *bgp_dump;
bgp_dump = THREAD_ARG(t); bgp_dump = THREAD_ARG(t);
bgp_dump->t_interval = NULL; bgp_dump->t_interval = NULL;
/* Reschedule dump even if file couldn't be opened this time... */ /* Reschedule dump even if file couldn't be opened this time... */
if (bgp_dump_open_file (bgp_dump) != NULL) if (bgp_dump_open_file(bgp_dump) != NULL) {
{ /* In case of bgp_dump_routes, we need special route dump
/* In case of bgp_dump_routes, we need special route dump function. */ * function. */
if (bgp_dump->type == BGP_DUMP_ROUTES) if (bgp_dump->type == BGP_DUMP_ROUTES) {
{
unsigned int seq = bgp_dump_routes_func(AFI_IP, 1, 0); unsigned int seq = bgp_dump_routes_func(AFI_IP, 1, 0);
bgp_dump_routes_func(AFI_IP6, 0, seq); bgp_dump_routes_func(AFI_IP6, 0, seq);
/* Close the file now. For a RIB dump there's no point in leaving /* Close the file now. For a RIB dump there's no point
* in leaving
* it open until the next scheduled dump starts. */ * it open until the next scheduled dump starts. */
fclose(bgp_dump->fp); bgp_dump->fp = NULL; fclose(bgp_dump->fp);
bgp_dump->fp = NULL;
} }
} }
@ -463,37 +450,32 @@ bgp_dump_interval_func (struct thread *t)
} }
/* Dump common information. */ /* Dump common information. */
static void static void bgp_dump_common(struct stream *obuf, struct peer *peer,
bgp_dump_common (struct stream *obuf, struct peer *peer, int forceas4) int forceas4)
{ {
char empty[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; char empty[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
/* Source AS number and Destination AS number. */ /* Source AS number and Destination AS number. */
if (forceas4 || CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV) ) if (forceas4 || CHECK_FLAG(peer->cap, PEER_CAP_AS4_RCV)) {
{
stream_putl(obuf, peer->as); stream_putl(obuf, peer->as);
stream_putl(obuf, peer->local_as); stream_putl(obuf, peer->local_as);
} } else {
else
{
stream_putw(obuf, peer->as); stream_putw(obuf, peer->as);
stream_putw(obuf, peer->local_as); stream_putw(obuf, peer->local_as);
} }
if (peer->su.sa.sa_family == AF_INET) if (peer->su.sa.sa_family == AF_INET) {
{
stream_putw(obuf, peer->ifindex); stream_putw(obuf, peer->ifindex);
stream_putw(obuf, AFI_IP); stream_putw(obuf, AFI_IP);
stream_put(obuf, &peer->su.sin.sin_addr, IPV4_MAX_BYTELEN); stream_put(obuf, &peer->su.sin.sin_addr, IPV4_MAX_BYTELEN);
if (peer->su_local) if (peer->su_local)
stream_put (obuf, &peer->su_local->sin.sin_addr, IPV4_MAX_BYTELEN); stream_put(obuf, &peer->su_local->sin.sin_addr,
IPV4_MAX_BYTELEN);
else else
stream_put(obuf, empty, IPV4_MAX_BYTELEN); stream_put(obuf, empty, IPV4_MAX_BYTELEN);
} } else if (peer->su.sa.sa_family == AF_INET6) {
else if (peer->su.sa.sa_family == AF_INET6)
{
/* Interface Index and Address family. */ /* Interface Index and Address family. */
stream_putw(obuf, peer->ifindex); stream_putw(obuf, peer->ifindex);
stream_putw(obuf, AFI_IP6); stream_putw(obuf, AFI_IP6);
@ -502,15 +484,15 @@ bgp_dump_common (struct stream *obuf, struct peer *peer, int forceas4)
stream_put(obuf, &peer->su.sin6.sin6_addr, IPV6_MAX_BYTELEN); stream_put(obuf, &peer->su.sin6.sin6_addr, IPV6_MAX_BYTELEN);
if (peer->su_local) if (peer->su_local)
stream_put (obuf, &peer->su_local->sin6.sin6_addr, IPV6_MAX_BYTELEN); stream_put(obuf, &peer->su_local->sin6.sin6_addr,
IPV6_MAX_BYTELEN);
else else
stream_put(obuf, empty, IPV6_MAX_BYTELEN); stream_put(obuf, empty, IPV6_MAX_BYTELEN);
} }
} }
/* Dump BGP status change. */ /* Dump BGP status change. */
void void bgp_dump_state(struct peer *peer, int status_old, int status_new)
bgp_dump_state (struct peer *peer, int status_old, int status_new)
{ {
struct stream *obuf; struct stream *obuf;
@ -537,8 +519,7 @@ bgp_dump_state (struct peer *peer, int status_old, int status_new)
fflush(bgp_dump_all.fp); fflush(bgp_dump_all.fp);
} }
static void static void bgp_dump_packet_func(struct bgp_dump *bgp_dump, struct peer *peer,
bgp_dump_packet_func (struct bgp_dump *bgp_dump, struct peer *peer,
struct stream *packet) struct stream *packet)
{ {
struct stream *obuf; struct stream *obuf;
@ -552,13 +533,10 @@ bgp_dump_packet_func (struct bgp_dump *bgp_dump, struct peer *peer,
stream_reset(obuf); stream_reset(obuf);
/* Dump header and common part. */ /* Dump header and common part. */
if (CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV) ) if (CHECK_FLAG(peer->cap, PEER_CAP_AS4_RCV)) {
{
bgp_dump_header(obuf, MSG_PROTOCOL_BGP4MP, BGP4MP_MESSAGE_AS4, bgp_dump_header(obuf, MSG_PROTOCOL_BGP4MP, BGP4MP_MESSAGE_AS4,
bgp_dump->type); bgp_dump->type);
} } else {
else
{
bgp_dump_header(obuf, MSG_PROTOCOL_BGP4MP, BGP4MP_MESSAGE, bgp_dump_header(obuf, MSG_PROTOCOL_BGP4MP, BGP4MP_MESSAGE,
bgp_dump->type); bgp_dump->type);
} }
@ -576,8 +554,7 @@ bgp_dump_packet_func (struct bgp_dump *bgp_dump, struct peer *peer,
} }
/* Called from bgp_packet.c when BGP packet is received. */ /* Called from bgp_packet.c when BGP packet is received. */
void void bgp_dump_packet(struct peer *peer, int type, struct stream *packet)
bgp_dump_packet (struct peer *peer, int type, struct stream *packet)
{ {
/* bgp_dump_all. */ /* bgp_dump_all. */
bgp_dump_packet_func(&bgp_dump_all, peer, packet); bgp_dump_packet_func(&bgp_dump_all, peer, packet);
@ -587,8 +564,7 @@ bgp_dump_packet (struct peer *peer, int type, struct stream *packet)
bgp_dump_packet_func(&bgp_dump_updates, peer, packet); bgp_dump_packet_func(&bgp_dump_updates, peer, packet);
} }
static unsigned int static unsigned int bgp_dump_parse_time(const char *str)
bgp_dump_parse_time (const char *str)
{ {
int i; int i;
int len; int len;
@ -603,15 +579,11 @@ bgp_dump_parse_time (const char *str)
seen_m = 0; seen_m = 0;
len = strlen(str); len = strlen(str);
for (i = 0; i < len; i++) for (i = 0; i < len; i++) {
{ if (isdigit((int)str[i])) {
if (isdigit ((int) str[i]))
{
time *= 10; time *= 10;
time += str[i] - '0'; time += str[i] - '0';
} } else if (str[i] == 'H' || str[i] == 'h') {
else if (str[i] == 'H' || str[i] == 'h')
{
if (seen_h) if (seen_h)
return 0; return 0;
if (seen_m) if (seen_m)
@ -619,23 +591,19 @@ bgp_dump_parse_time (const char *str)
total += time * 60 * 60; total += time * 60 * 60;
time = 0; time = 0;
seen_h = 1; seen_h = 1;
} } else if (str[i] == 'M' || str[i] == 'm') {
else if (str[i] == 'M' || str[i] == 'm')
{
if (seen_m) if (seen_m)
return 0; return 0;
total += time * 60; total += time * 60;
time = 0; time = 0;
seen_m = 1; seen_m = 1;
} } else
else
return 0; return 0;
} }
return total + time; return total + time;
} }
static int static int bgp_dump_set(struct vty *vty, struct bgp_dump *bgp_dump,
bgp_dump_set (struct vty *vty, struct bgp_dump *bgp_dump,
enum bgp_dump_type type, const char *path, enum bgp_dump_type type, const char *path,
const char *interval_str) const char *interval_str)
{ {
@ -643,16 +611,13 @@ bgp_dump_set (struct vty *vty, struct bgp_dump *bgp_dump,
/* Don't schedule duplicate dumps if the dump command is given twice */ /* Don't schedule duplicate dumps if the dump command is given twice */
if (bgp_dump->filename && strcmp(path, bgp_dump->filename) == 0 if (bgp_dump->filename && strcmp(path, bgp_dump->filename) == 0
&& type == bgp_dump->type) && type == bgp_dump->type) {
{ if (interval_str) {
if (interval_str) if (bgp_dump->interval_str
{ && strcmp(bgp_dump->interval_str, interval_str)
if (bgp_dump->interval_str && == 0)
strcmp(bgp_dump->interval_str, interval_str) == 0)
return CMD_SUCCESS; return CMD_SUCCESS;
} } else {
else
{
if (!bgp_dump->interval_str) if (!bgp_dump->interval_str)
return CMD_SUCCESS; return CMD_SUCCESS;
} }
@ -661,21 +626,18 @@ bgp_dump_set (struct vty *vty, struct bgp_dump *bgp_dump,
/* Removing previous config */ /* Removing previous config */
bgp_dump_unset(bgp_dump); bgp_dump_unset(bgp_dump);
if (interval_str) if (interval_str) {
{
/* Check interval string. */ /* Check interval string. */
interval = bgp_dump_parse_time(interval_str); interval = bgp_dump_parse_time(interval_str);
if (interval == 0) if (interval == 0) {
{ vty_out(vty, "Malformed interval string\n");
vty_outln (vty, "Malformed interval string"); return CMD_WARNING_CONFIG_FAILED;
return CMD_WARNING;
} }
/* Setting interval string */ /* Setting interval string */
bgp_dump->interval_str = XSTRDUP(MTYPE_BGP_DUMP_STR, interval_str); bgp_dump->interval_str =
} XSTRDUP(MTYPE_BGP_DUMP_STR, interval_str);
else } else {
{
interval = 0; interval = 0;
} }
@ -697,26 +659,22 @@ bgp_dump_set (struct vty *vty, struct bgp_dump *bgp_dump,
return CMD_SUCCESS; return CMD_SUCCESS;
} }
static int static int bgp_dump_unset(struct bgp_dump *bgp_dump)
bgp_dump_unset (struct bgp_dump *bgp_dump)
{ {
/* Removing file name. */ /* Removing file name. */
if (bgp_dump->filename) if (bgp_dump->filename) {
{
XFREE(MTYPE_BGP_DUMP_STR, bgp_dump->filename); XFREE(MTYPE_BGP_DUMP_STR, bgp_dump->filename);
bgp_dump->filename = NULL; bgp_dump->filename = NULL;
} }
/* Closing file. */ /* Closing file. */
if (bgp_dump->fp) if (bgp_dump->fp) {
{
fclose(bgp_dump->fp); fclose(bgp_dump->fp);
bgp_dump->fp = NULL; bgp_dump->fp = NULL;
} }
/* Removing interval thread. */ /* Removing interval thread. */
if (bgp_dump->t_interval) if (bgp_dump->t_interval) {
{
thread_cancel(bgp_dump->t_interval); thread_cancel(bgp_dump->t_interval);
bgp_dump->t_interval = NULL; bgp_dump->t_interval = NULL;
} }
@ -724,8 +682,7 @@ bgp_dump_unset (struct bgp_dump *bgp_dump)
bgp_dump->interval = 0; bgp_dump->interval = 0;
/* Removing interval string. */ /* Removing interval string. */
if (bgp_dump->interval_str) if (bgp_dump->interval_str) {
{
XFREE(MTYPE_BGP_DUMP_STR, bgp_dump->interval_str); XFREE(MTYPE_BGP_DUMP_STR, bgp_dump->interval_str);
bgp_dump->interval_str = NULL; bgp_dump->interval_str = NULL;
} }
@ -756,8 +713,7 @@ DEFUN (dump_bgp_all,
if (strmatch(argv[idx_dump_routes]->text, map->str)) if (strmatch(argv[idx_dump_routes]->text, map->str))
bgp_dump_type = map->type; bgp_dump_type = map->type;
switch (bgp_dump_type) switch (bgp_dump_type) {
{
case BGP_DUMP_ALL: case BGP_DUMP_ALL:
case BGP_DUMP_ALL_ET: case BGP_DUMP_ALL_ET:
bgp_dump_struct = &bgp_dump_all; bgp_dump_struct = &bgp_dump_all;
@ -803,8 +759,7 @@ DEFUN (no_dump_bgp_all,
if (strmatch(argv[idx_dump_routes]->text, map->str)) if (strmatch(argv[idx_dump_routes]->text, map->str))
bgp_dump_type = map->type; bgp_dump_type = map->type;
switch (bgp_dump_type) switch (bgp_dump_type) {
{
case BGP_DUMP_ALL: case BGP_DUMP_ALL:
case BGP_DUMP_ALL_ET: case BGP_DUMP_ALL_ET:
bgp_dump_struct = &bgp_dump_all; bgp_dump_struct = &bgp_dump_all;
@ -823,12 +778,7 @@ DEFUN (no_dump_bgp_all,
} }
/* BGP node structure. */ /* BGP node structure. */
static struct cmd_node bgp_dump_node = static struct cmd_node bgp_dump_node = {DUMP_NODE, "", 1};
{
DUMP_NODE,
"",
1
};
#if 0 #if 0
char * char *
@ -856,58 +806,56 @@ config_time2str (unsigned int interval)
} }
#endif #endif
static int static int config_write_bgp_dump(struct vty *vty)
config_write_bgp_dump (struct vty *vty)
{
if (bgp_dump_all.filename)
{ {
if (bgp_dump_all.filename) {
const char *type_str = "all"; const char *type_str = "all";
if (bgp_dump_all.type == BGP_DUMP_ALL_ET) if (bgp_dump_all.type == BGP_DUMP_ALL_ET)
type_str = "all-et"; type_str = "all-et";
if (bgp_dump_all.interval_str) if (bgp_dump_all.interval_str)
vty_outln (vty, "dump bgp %s %s %s", type_str, vty_out(vty, "dump bgp %s %s %s\n", type_str,
bgp_dump_all.filename,bgp_dump_all.interval_str); bgp_dump_all.filename,
bgp_dump_all.interval_str);
else else
vty_outln (vty, "dump bgp %s %s", type_str, vty_out(vty, "dump bgp %s %s\n", type_str,
bgp_dump_all.filename); bgp_dump_all.filename);
} }
if (bgp_dump_updates.filename) if (bgp_dump_updates.filename) {
{
const char *type_str = "updates"; const char *type_str = "updates";
if (bgp_dump_updates.type == BGP_DUMP_UPDATES_ET) if (bgp_dump_updates.type == BGP_DUMP_UPDATES_ET)
type_str = "updates-et"; type_str = "updates-et";
if (bgp_dump_updates.interval_str) if (bgp_dump_updates.interval_str)
vty_outln (vty, "dump bgp %s %s %s", type_str, vty_out(vty, "dump bgp %s %s %s\n", type_str,
bgp_dump_updates.filename,bgp_dump_updates.interval_str); bgp_dump_updates.filename,
bgp_dump_updates.interval_str);
else else
vty_outln (vty, "dump bgp %s %s", type_str, vty_out(vty, "dump bgp %s %s\n", type_str,
bgp_dump_updates.filename); bgp_dump_updates.filename);
} }
if (bgp_dump_routes.filename) if (bgp_dump_routes.filename) {
{
if (bgp_dump_routes.interval_str) if (bgp_dump_routes.interval_str)
vty_outln (vty, "dump bgp routes-mrt %s %s", vty_out(vty, "dump bgp routes-mrt %s %s\n",
bgp_dump_routes.filename,bgp_dump_routes.interval_str); bgp_dump_routes.filename,
bgp_dump_routes.interval_str);
else else
vty_outln (vty, "dump bgp routes-mrt %s", vty_out(vty, "dump bgp routes-mrt %s\n",
bgp_dump_routes.filename); bgp_dump_routes.filename);
} }
return 0; return 0;
} }
/* Initialize BGP packet dump functionality. */ /* Initialize BGP packet dump functionality. */
void void bgp_dump_init(void)
bgp_dump_init (void)
{ {
memset(&bgp_dump_all, 0, sizeof(struct bgp_dump)); memset(&bgp_dump_all, 0, sizeof(struct bgp_dump));
memset(&bgp_dump_updates, 0, sizeof(struct bgp_dump)); memset(&bgp_dump_updates, 0, sizeof(struct bgp_dump));
memset(&bgp_dump_routes, 0, sizeof(struct bgp_dump)); memset(&bgp_dump_routes, 0, sizeof(struct bgp_dump));
bgp_dump_obuf = stream_new ((BGP_MAX_PACKET_SIZE << 1) bgp_dump_obuf =
+ BGP_DUMP_MSG_HEADER + BGP_DUMP_HEADER_SIZE); stream_new((BGP_MAX_PACKET_SIZE << 1) + BGP_DUMP_MSG_HEADER
+ BGP_DUMP_HEADER_SIZE);
install_node(&bgp_dump_node, config_write_bgp_dump); install_node(&bgp_dump_node, config_write_bgp_dump);
@ -915,8 +863,7 @@ bgp_dump_init (void)
install_element(CONFIG_NODE, &no_dump_bgp_all_cmd); install_element(CONFIG_NODE, &no_dump_bgp_all_cmd);
} }
void void bgp_dump_finish(void)
bgp_dump_finish (void)
{ {
bgp_dump_unset(&bgp_dump_all); bgp_dump_unset(&bgp_dump_all);
bgp_dump_unset(&bgp_dump_updates); bgp_dump_unset(&bgp_dump_updates);

View File

@ -36,16 +36,14 @@
static struct hash *ecomhash; static struct hash *ecomhash;
/* Allocate a new ecommunities. */ /* Allocate a new ecommunities. */
struct ecommunity * struct ecommunity *ecommunity_new(void)
ecommunity_new (void)
{ {
return (struct ecommunity *)XCALLOC(MTYPE_ECOMMUNITY, return (struct ecommunity *)XCALLOC(MTYPE_ECOMMUNITY,
sizeof(struct ecommunity)); sizeof(struct ecommunity));
} }
/* Allocate ecommunities. */ /* Allocate ecommunities. */
void void ecommunity_free(struct ecommunity **ecom)
ecommunity_free (struct ecommunity **ecom)
{ {
if ((*ecom)->val) if ((*ecom)->val)
XFREE(MTYPE_ECOMMUNITY_VAL, (*ecom)->val); XFREE(MTYPE_ECOMMUNITY_VAL, (*ecom)->val);
@ -55,8 +53,7 @@ ecommunity_free (struct ecommunity **ecom)
ecom = NULL; ecom = NULL;
} }
static void static void ecommunity_hash_free(struct ecommunity *ecom)
ecommunity_hash_free (struct ecommunity *ecom)
{ {
ecommunity_free(&ecom); ecommunity_free(&ecom);
} }
@ -67,16 +64,14 @@ ecommunity_hash_free (struct ecommunity *ecom)
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. */
int int ecommunity_add_val(struct ecommunity *ecom, struct ecommunity_val *eval)
ecommunity_add_val (struct ecommunity *ecom, struct ecommunity_val *eval)
{ {
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 (ecom->val == NULL) if (ecom->val == NULL) {
{
ecom->size++; ecom->size++;
ecom->val = XMALLOC(MTYPE_ECOMMUNITY_VAL, ecom_length(ecom)); ecom->val = XMALLOC(MTYPE_ECOMMUNITY_VAL, ecom_length(ecom));
memcpy(ecom->val, eval->val, ECOMMUNITY_SIZE); memcpy(ecom->val, eval->val, ECOMMUNITY_SIZE);
@ -85,8 +80,7 @@ ecommunity_add_val (struct ecommunity *ecom, struct ecommunity_val *eval)
/* 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 = ecom->val; c < ecom->size; p += ECOMMUNITY_SIZE, c++) for (p = ecom->val; c < ecom->size; p += ECOMMUNITY_SIZE, c++) {
{
ret = memcmp(p, eval->val, ECOMMUNITY_SIZE); ret = memcmp(p, eval->val, ECOMMUNITY_SIZE);
if (ret == 0) if (ret == 0)
return 0; return 0;
@ -96,7 +90,8 @@ ecommunity_add_val (struct ecommunity *ecom, struct ecommunity_val *eval)
/* Add the value to the structure with numerical sorting. */ /* Add the value to the structure with numerical sorting. */
ecom->size++; ecom->size++;
ecom->val = XREALLOC (MTYPE_ECOMMUNITY_VAL, ecom->val, ecom_length (ecom)); ecom->val =
XREALLOC(MTYPE_ECOMMUNITY_VAL, ecom->val, ecom_length(ecom));
memmove(ecom->val + (c + 1) * ECOMMUNITY_SIZE, memmove(ecom->val + (c + 1) * ECOMMUNITY_SIZE,
ecom->val + c * ECOMMUNITY_SIZE, ecom->val + c * ECOMMUNITY_SIZE,
@ -109,8 +104,7 @@ ecommunity_add_val (struct ecommunity *ecom, struct ecommunity_val *eval)
/* This function takes pointer to Extended Communites strucutre then /* This function takes pointer to Extended Communites strucutre then
create a new Extended Communities structure by uniq and sort each create a new Extended Communities structure by uniq and sort each
Extended Communities value. */ Extended Communities value. */
struct ecommunity * struct ecommunity *ecommunity_uniq_sort(struct ecommunity *ecom)
ecommunity_uniq_sort (struct ecommunity *ecom)
{ {
int i; int i;
struct ecommunity *new; struct ecommunity *new;
@ -121,17 +115,16 @@ ecommunity_uniq_sort (struct ecommunity *ecom)
new = ecommunity_new(); new = ecommunity_new();
for (i = 0; i < ecom->size; i++) for (i = 0; i < ecom->size; i++) {
{ eval = (struct ecommunity_val *)(ecom->val
eval = (struct ecommunity_val *) (ecom->val + (i * ECOMMUNITY_SIZE)); + (i * ECOMMUNITY_SIZE));
ecommunity_add_val(new, eval); ecommunity_add_val(new, eval);
} }
return new; return new;
} }
/* Parse Extended Communites Attribute in BGP packet. */ /* Parse Extended Communites Attribute in BGP packet. */
struct ecommunity * struct ecommunity *ecommunity_parse(u_int8_t *pnt, u_short length)
ecommunity_parse (u_int8_t *pnt, u_short length)
{ {
struct ecommunity tmp; struct ecommunity tmp;
struct ecommunity *new; struct ecommunity *new;
@ -153,53 +146,52 @@ ecommunity_parse (u_int8_t *pnt, u_short length)
} }
/* Duplicate the Extended Communities Attribute structure. */ /* Duplicate the Extended Communities Attribute structure. */
struct ecommunity * struct ecommunity *ecommunity_dup(struct ecommunity *ecom)
ecommunity_dup (struct ecommunity *ecom)
{ {
struct ecommunity *new; struct ecommunity *new;
new = XCALLOC(MTYPE_ECOMMUNITY, sizeof(struct ecommunity)); new = XCALLOC(MTYPE_ECOMMUNITY, sizeof(struct ecommunity));
new->size = ecom->size; new->size = ecom->size;
if (new->size) if (new->size) {
{ new->val = XMALLOC(MTYPE_ECOMMUNITY_VAL,
new->val = XMALLOC (MTYPE_ECOMMUNITY_VAL, ecom->size * ECOMMUNITY_SIZE); ecom->size * ECOMMUNITY_SIZE);
memcpy(new->val, ecom->val, ecom->size * ECOMMUNITY_SIZE); memcpy(new->val, ecom->val, ecom->size * ECOMMUNITY_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 *ecommunity_str(struct ecommunity *ecom)
ecommunity_str (struct ecommunity *ecom)
{ {
if (!ecom->str) if (!ecom->str)
ecom->str = ecommunity_ecom2str (ecom, ECOMMUNITY_FORMAT_DISPLAY, 0); ecom->str =
ecommunity_ecom2str(ecom, ECOMMUNITY_FORMAT_DISPLAY, 0);
return ecom->str; return ecom->str;
} }
/* Merge two Extended Communities Attribute structure. */ /* Merge two Extended Communities Attribute structure. */
struct ecommunity * struct ecommunity *ecommunity_merge(struct ecommunity *ecom1,
ecommunity_merge (struct ecommunity *ecom1, struct ecommunity *ecom2) struct ecommunity *ecom2)
{ {
if (ecom1->val) if (ecom1->val)
ecom1->val = XREALLOC (MTYPE_ECOMMUNITY_VAL, ecom1->val, ecom1->val =
XREALLOC(MTYPE_ECOMMUNITY_VAL, ecom1->val,
(ecom1->size + ecom2->size) * ECOMMUNITY_SIZE); (ecom1->size + ecom2->size) * ECOMMUNITY_SIZE);
else else
ecom1->val = XMALLOC (MTYPE_ECOMMUNITY_VAL, ecom1->val =
XMALLOC(MTYPE_ECOMMUNITY_VAL,
(ecom1->size + ecom2->size) * ECOMMUNITY_SIZE); (ecom1->size + ecom2->size) * ECOMMUNITY_SIZE);
memcpy (ecom1->val + (ecom1->size * ECOMMUNITY_SIZE), memcpy(ecom1->val + (ecom1->size * ECOMMUNITY_SIZE), ecom2->val,
ecom2->val, ecom2->size * ECOMMUNITY_SIZE); ecom2->size * ECOMMUNITY_SIZE);
ecom1->size += ecom2->size; ecom1->size += ecom2->size;
return ecom1; return ecom1;
} }
/* Intern Extended Communities Attribute. */ /* Intern Extended Communities Attribute. */
struct ecommunity * struct ecommunity *ecommunity_intern(struct ecommunity *ecom)
ecommunity_intern (struct ecommunity *ecom)
{ {
struct ecommunity *find; struct ecommunity *find;
@ -213,14 +205,14 @@ ecommunity_intern (struct ecommunity *ecom)
find->refcnt++; find->refcnt++;
if (!find->str) if (!find->str)
find->str = ecommunity_ecom2str (find, ECOMMUNITY_FORMAT_DISPLAY, 0); find->str =
ecommunity_ecom2str(find, ECOMMUNITY_FORMAT_DISPLAY, 0);
return find; return find;
} }
/* Unintern Extended Communities Attribute. */ /* Unintern Extended Communities Attribute. */
void void ecommunity_unintern(struct ecommunity **ecom)
ecommunity_unintern (struct ecommunity **ecom)
{ {
struct ecommunity *ret; struct ecommunity *ret;
@ -228,8 +220,7 @@ ecommunity_unintern (struct ecommunity **ecom)
(*ecom)->refcnt--; (*ecom)->refcnt--;
/* Pull off from hash. */ /* Pull off from hash. */
if ((*ecom)->refcnt == 0) if ((*ecom)->refcnt == 0) {
{
/* Extended community must be in the hash. */ /* Extended community must be in the hash. */
ret = (struct ecommunity *)hash_release(ecomhash, *ecom); ret = (struct ecommunity *)hash_release(ecomhash, *ecom);
assert(ret != NULL); assert(ret != NULL);
@ -239,8 +230,7 @@ ecommunity_unintern (struct ecommunity **ecom)
} }
/* Utinity function to make hash key. */ /* Utinity function to make hash key. */
unsigned int unsigned int ecommunity_hash_make(void *arg)
ecommunity_hash_make (void *arg)
{ {
const struct ecommunity *ecom = arg; const struct ecommunity *ecom = arg;
int size = ecom->size * ECOMMUNITY_SIZE; int size = ecom->size * ECOMMUNITY_SIZE;
@ -248,8 +238,7 @@ ecommunity_hash_make (void *arg)
unsigned int key = 0; unsigned int key = 0;
int c; int c;
for (c = 0; c < size; c += ECOMMUNITY_SIZE) for (c = 0; c < size; c += ECOMMUNITY_SIZE) {
{
key += pnt[c]; key += pnt[c];
key += pnt[c + 1]; key += pnt[c + 1];
key += pnt[c + 2]; key += pnt[c + 2];
@ -264,8 +253,7 @@ ecommunity_hash_make (void *arg)
} }
/* Compare two Extended Communities Attribute structure. */ /* Compare two Extended Communities Attribute structure. */
int int ecommunity_cmp(const void *arg1, const void *arg2)
ecommunity_cmp (const void *arg1, const void *arg2)
{ {
const struct ecommunity *ecom1 = arg1; const struct ecommunity *ecom1 = arg1;
const struct ecommunity *ecom2 = arg2; const struct ecommunity *ecom2 = arg2;
@ -277,18 +265,17 @@ ecommunity_cmp (const void *arg1, const void *arg2)
return 0; return 0;
return (ecom1->size == ecom2->size return (ecom1->size == ecom2->size
&& memcmp (ecom1->val, ecom2->val, ecom1->size * ECOMMUNITY_SIZE) == 0); && memcmp(ecom1->val, ecom2->val, ecom1->size * ECOMMUNITY_SIZE)
== 0);
} }
/* Initialize Extended Comminities related hash. */ /* Initialize Extended Comminities related hash. */
void void ecommunity_init(void)
ecommunity_init (void)
{ {
ecomhash = hash_create(ecommunity_hash_make, ecommunity_cmp, NULL); ecomhash = hash_create(ecommunity_hash_make, ecommunity_cmp, NULL);
} }
void void ecommunity_finish(void)
ecommunity_finish (void)
{ {
hash_clean(ecomhash, (void (*)(void *))ecommunity_hash_free); hash_clean(ecomhash, (void (*)(void *))ecommunity_hash_free);
hash_free(ecomhash); hash_free(ecomhash);
@ -296,17 +283,62 @@ ecommunity_finish (void)
} }
/* Extended Communities token enum. */ /* Extended Communities token enum. */
enum ecommunity_token enum ecommunity_token {
{
ecommunity_token_unknown = 0, ecommunity_token_unknown = 0,
ecommunity_token_rt, ecommunity_token_rt,
ecommunity_token_soo, ecommunity_token_soo,
ecommunity_token_val, ecommunity_token_val,
}; };
/*
* Encode BGP extended community from passed values. Supports types
* defined in RFC 4360 and well-known sub-types.
*/
static int ecommunity_encode(u_char type, u_char sub_type, int trans, as_t as,
struct in_addr ip, u_int32_t val,
struct ecommunity_val *eval)
{
assert(eval);
if (type == ECOMMUNITY_ENCODE_AS) {
if (as > BGP_AS_MAX)
return -1;
} else if (type == ECOMMUNITY_ENCODE_IP
|| type == ECOMMUNITY_ENCODE_AS4) {
if (val > UINT16_MAX)
return -1;
}
/* Fill in the values. */
eval->val[0] = type;
if (!trans)
eval->val[0] |= ECOMMUNITY_FLAG_NON_TRANSITIVE;
eval->val[1] = sub_type;
if (type == ECOMMUNITY_ENCODE_AS) {
eval->val[2] = (as >> 8) & 0xff;
eval->val[3] = as & 0xff;
eval->val[4] = (val >> 24) & 0xff;
eval->val[5] = (val >> 16) & 0xff;
eval->val[6] = (val >> 8) & 0xff;
eval->val[7] = val & 0xff;
} else if (type == ECOMMUNITY_ENCODE_IP) {
memcpy(&eval->val[2], &ip, sizeof(struct in_addr));
eval->val[6] = (val >> 8) & 0xff;
eval->val[7] = val & 0xff;
} else {
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;
}
return 0;
}
/* Get next Extended Communities token from the string. */ /* Get next Extended Communities token from the string. */
static const char * static const char *ecommunity_gettoken(const char *str,
ecommunity_gettoken (const char *str, struct ecommunity_val *eval, struct ecommunity_val *eval,
enum ecommunity_token *token) enum ecommunity_token *token)
{ {
int ret; int ret;
@ -318,11 +350,11 @@ ecommunity_gettoken (const char *str, struct ecommunity_val *eval,
struct in_addr ip; struct in_addr ip;
as_t as = 0; as_t as = 0;
u_int32_t val = 0; u_int32_t val = 0;
u_char ecomm_type;
char buf[INET_ADDRSTRLEN + 1]; char buf[INET_ADDRSTRLEN + 1];
/* Skip white space. */ /* Skip white space. */
while (isspace ((int) *p)) while (isspace((int)*p)) {
{
p++; p++;
str++; str++;
} }
@ -332,47 +364,38 @@ ecommunity_gettoken (const char *str, struct ecommunity_val *eval,
return NULL; return NULL;
/* "rt" and "soo" keyword parse. */ /* "rt" and "soo" keyword parse. */
if (! isdigit ((int) *p)) if (!isdigit((int)*p)) {
{
/* "rt" match check. */ /* "rt" match check. */
if (tolower ((int) *p) == 'r') if (tolower((int)*p) == 'r') {
{
p++; p++;
if (tolower ((int) *p) == 't') if (tolower((int)*p) == 't') {
{
p++; p++;
*token = ecommunity_token_rt; *token = ecommunity_token_rt;
return p; return p;
} }
if (isspace ((int) *p) || *p == '\0') if (isspace((int)*p) || *p == '\0') {
{
*token = ecommunity_token_rt; *token = ecommunity_token_rt;
return p; return p;
} }
goto error; goto error;
} }
/* "soo" match check. */ /* "soo" match check. */
else if (tolower ((int) *p) == 's') else if (tolower((int)*p) == 's') {
{
p++; p++;
if (tolower ((int) *p) == 'o') if (tolower((int)*p) == 'o') {
{
p++; p++;
if (tolower ((int) *p) == 'o') if (tolower((int)*p) == 'o') {
{
p++; p++;
*token = ecommunity_token_soo; *token = ecommunity_token_soo;
return p; return p;
} }
if (isspace ((int) *p) || *p == '\0') if (isspace((int)*p) || *p == '\0') {
{
*token = ecommunity_token_soo; *token = ecommunity_token_soo;
return p; return p;
} }
goto error; goto error;
} }
if (isspace ((int) *p) || *p == '\0') if (isspace((int)*p) || *p == '\0') {
{
*token = ecommunity_token_soo; *token = ecommunity_token_soo;
return p; return p;
} }
@ -394,10 +417,8 @@ ecommunity_gettoken (const char *str, struct ecommunity_val *eval,
* OPQR: Four byte value * OPQR: Four byte value
* *
*/ */
while (isdigit ((int) *p) || *p == ':' || *p == '.') while (isdigit((int)*p) || *p == ':' || *p == '.') {
{ if (*p == ':') {
if (*p == ':')
{
if (separator) if (separator)
goto error; goto error;
@ -409,38 +430,30 @@ ecommunity_gettoken (const char *str, struct ecommunity_val *eval,
memset(buf, 0, INET_ADDRSTRLEN + 1); memset(buf, 0, INET_ADDRSTRLEN + 1);
memcpy(buf, str, p - str); memcpy(buf, str, p - str);
if (dot) if (dot) {
{
/* Parsing A.B.C.D in: /* Parsing A.B.C.D in:
* A.B.C.D:MN * A.B.C.D:MN
*/ */
ret = inet_aton(buf, &ip); ret = inet_aton(buf, &ip);
if (ret == 0) if (ret == 0)
goto error; goto error;
} } else {
else
{
/* ASN */ /* ASN */
as = strtoul(buf, &endptr, 10); as = strtoul(buf, &endptr, 10);
if (*endptr != '\0' || as == BGP_AS4_MAX) if (*endptr != '\0' || as == BGP_AS4_MAX)
goto error; goto error;
} }
} } else if (*p == '.') {
else if (*p == '.')
{
if (separator) if (separator)
goto error; goto error;
dot++; dot++;
if (dot > 4) if (dot > 4)
goto error; goto error;
} } else {
else
{
digit = 1; digit = 1;
/* We're past the IP/ASN part */ /* We're past the IP/ASN part */
if (separator) if (separator) {
{
val *= 10; val *= 10;
val += (*p - '0'); val += (*p - '0');
} }
@ -452,44 +465,15 @@ ecommunity_gettoken (const char *str, struct ecommunity_val *eval,
if (!digit || !separator) if (!digit || !separator)
goto error; goto error;
/* Encode result into routing distinguisher. */ /* Encode result into extended community. */
if (dot) if (dot)
{ ecomm_type = ECOMMUNITY_ENCODE_IP;
if (val > UINT16_MAX)
goto error;
eval->val[0] = ECOMMUNITY_ENCODE_IP;
eval->val[1] = 0;
memcpy (&eval->val[2], &ip, sizeof (struct in_addr));
eval->val[6] = (val >> 8) & 0xff;
eval->val[7] = val & 0xff;
}
else if (as > BGP_AS_MAX) else if (as > BGP_AS_MAX)
{ ecomm_type = ECOMMUNITY_ENCODE_AS4;
if (val > UINT16_MAX)
goto error;
eval->val[0] = ECOMMUNITY_ENCODE_AS4;
eval->val[1] = 0;
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;
}
else else
{ ecomm_type = ECOMMUNITY_ENCODE_AS;
eval->val[0] = ECOMMUNITY_ENCODE_AS; if (ecommunity_encode(ecomm_type, 0, 1, as, ip, val, eval))
eval->val[1] = 0; goto error;
eval->val[2] = (as >>8) & 0xff;
eval->val[3] = as & 0xff;
eval->val[4] = (val >>24) & 0xff;
eval->val[5] = (val >>16) & 0xff;
eval->val[6] = (val >>8) & 0xff;
eval->val[7] = val & 0xff;
}
*token = ecommunity_token_val; *token = ecommunity_token_val;
return p; return p;
@ -524,42 +508,35 @@ ecommunity_gettoken (const char *str, struct ecommunity_val *eval,
type = 0 type = 0
keyword_include = 1 keyword_include = 1
*/ */
struct ecommunity * struct ecommunity *ecommunity_str2com(const char *str, int type,
ecommunity_str2com (const char *str, int type, int keyword_included) int keyword_included)
{ {
struct ecommunity *ecom = NULL; struct ecommunity *ecom = NULL;
enum ecommunity_token token = ecommunity_token_unknown; enum ecommunity_token token = ecommunity_token_unknown;
struct ecommunity_val eval; struct ecommunity_val eval;
int keyword = 0; int keyword = 0;
while ((str = ecommunity_gettoken (str, &eval, &token))) while ((str = ecommunity_gettoken(str, &eval, &token))) {
{ switch (token) {
switch (token)
{
case ecommunity_token_rt: case ecommunity_token_rt:
case ecommunity_token_soo: case ecommunity_token_soo:
if (! keyword_included || keyword) if (!keyword_included || keyword) {
{
if (ecom) if (ecom)
ecommunity_free(&ecom); ecommunity_free(&ecom);
return NULL; return NULL;
} }
keyword = 1; keyword = 1;
if (token == ecommunity_token_rt) if (token == ecommunity_token_rt) {
{
type = ECOMMUNITY_ROUTE_TARGET; type = ECOMMUNITY_ROUTE_TARGET;
} }
if (token == ecommunity_token_soo) if (token == ecommunity_token_soo) {
{
type = ECOMMUNITY_SITE_ORIGIN; type = ECOMMUNITY_SITE_ORIGIN;
} }
break; break;
case ecommunity_token_val: case ecommunity_token_val:
if (keyword_included) if (keyword_included) {
{ if (!keyword) {
if (! keyword)
{
if (ecom) if (ecom)
ecommunity_free(&ecom); ecommunity_free(&ecom);
return NULL; return NULL;
@ -581,6 +558,73 @@ ecommunity_str2com (const char *str, int type, int keyword_included)
return ecom; return ecom;
} }
static int ecommunity_rt_soo_str(char *buf, u_int8_t *pnt, int type,
int sub_type, int format)
{
int len = 0;
const char *prefix;
/* For parse Extended Community attribute tupple. */
struct ecommunity_as {
as_t as;
u_int32_t val;
} eas;
struct ecommunity_ip {
struct in_addr ip;
u_int16_t val;
} eip;
/* Determine prefix for string, if any. */
switch (format) {
case ECOMMUNITY_FORMAT_COMMUNITY_LIST:
prefix = (sub_type == ECOMMUNITY_ROUTE_TARGET ? "rt " : "soo ");
break;
case ECOMMUNITY_FORMAT_DISPLAY:
prefix = (sub_type == ECOMMUNITY_ROUTE_TARGET ? "RT:" : "SoO:");
break;
case ECOMMUNITY_FORMAT_ROUTE_MAP:
prefix = "";
break;
default:
prefix = "";
break;
}
/* Put string into buffer. */
if (type == ECOMMUNITY_ENCODE_AS4) {
eas.as = (*pnt++ << 24);
eas.as |= (*pnt++ << 16);
eas.as |= (*pnt++ << 8);
eas.as |= (*pnt++);
eas.val = (*pnt++ << 8);
eas.val |= (*pnt++);
len = sprintf(buf, "%s%u:%u", prefix, eas.as, eas.val);
} else if (type == ECOMMUNITY_ENCODE_AS) {
eas.as = (*pnt++ << 8);
eas.as |= (*pnt++);
eas.val = (*pnt++ << 24);
eas.val |= (*pnt++ << 16);
eas.val |= (*pnt++ << 8);
eas.val |= (*pnt++);
len = sprintf(buf, "%s%u:%u", prefix, eas.as, eas.val);
} else if (type == ECOMMUNITY_ENCODE_IP) {
memcpy(&eip.ip, pnt, 4);
pnt += 4;
eip.val = (*pnt++ << 8);
eip.val |= (*pnt++);
len = sprintf(buf, "%s%s:%u", prefix, inet_ntoa(eip.ip),
eip.val);
}
return len;
}
/* Convert extended community attribute to string. /* Convert extended community attribute to string.
Due to historical reason of industry standard implementation, there Due to historical reason of industry standard implementation, there
@ -605,36 +649,20 @@ ecommunity_str2com (const char *str, int type, int keyword_included)
Filter is added to display only ECOMMUNITY_ROUTE_TARGET in some cases. Filter is added to display only ECOMMUNITY_ROUTE_TARGET in some cases.
0 value displays all 0 value displays all
*/ */
char * char *ecommunity_ecom2str(struct ecommunity *ecom, int format, int filter)
ecommunity_ecom2str (struct ecommunity *ecom, int format, int filter)
{ {
int i; int i;
u_int8_t *pnt; u_int8_t *pnt;
int encode = 0;
int type = 0; int type = 0;
int sub_type = 0;
#define ECOMMUNITY_STR_DEFAULT_LEN 27 #define ECOMMUNITY_STR_DEFAULT_LEN 27
int str_size; int str_size;
int str_pnt; int str_pnt;
char *str_buf; char *str_buf;
const char *prefix;
int len = 0; int len = 0;
int first = 1; int first = 1;
/* For parse Extended Community attribute tupple. */ if (ecom->size == 0) {
struct ecommunity_as
{
as_t as;
u_int32_t val;
} eas;
struct ecommunity_ip
{
struct in_addr ip;
u_int16_t val;
} eip;
if (ecom->size == 0)
{
str_buf = XMALLOC(MTYPE_ECOMMUNITY_STR, 1); str_buf = XMALLOC(MTYPE_ECOMMUNITY_STR, 1);
str_buf[0] = '\0'; str_buf[0] = '\0';
return str_buf; return str_buf;
@ -646,13 +674,14 @@ ecommunity_ecom2str (struct ecommunity *ecom, int format, int filter)
str_buf[0] = '\0'; str_buf[0] = '\0';
str_pnt = 0; str_pnt = 0;
for (i = 0; i < ecom->size; i++) for (i = 0; i < ecom->size; i++) {
{ int unk_ecom = 0;
/* Make it sure size is enough. */ /* Make it sure size is enough. */
while (str_pnt + ECOMMUNITY_STR_DEFAULT_LEN >= str_size) while (str_pnt + ECOMMUNITY_STR_DEFAULT_LEN >= str_size) {
{
str_size *= 2; str_size *= 2;
str_buf = XREALLOC (MTYPE_ECOMMUNITY_STR, str_buf, str_size); str_buf = XREALLOC(MTYPE_ECOMMUNITY_STR, str_buf,
str_size);
} }
/* Space between each value. */ /* Space between each value. */
@ -662,137 +691,73 @@ ecommunity_ecom2str (struct ecommunity *ecom, int format, int filter)
pnt = ecom->val + (i * 8); pnt = ecom->val + (i * 8);
/* High-order octet of type. */ /* High-order octet of type. */
encode = *pnt++; type = *pnt++;
switch (encode) if (type == ECOMMUNITY_ENCODE_AS || type == ECOMMUNITY_ENCODE_IP
{ || type == ECOMMUNITY_ENCODE_AS4) {
case ECOMMUNITY_ENCODE_AS: /* Low-order octet of type. */
case ECOMMUNITY_ENCODE_IP: sub_type = *pnt++;
case ECOMMUNITY_ENCODE_AS4: if (sub_type != ECOMMUNITY_ROUTE_TARGET
break; && sub_type != ECOMMUNITY_SITE_ORIGIN)
unk_ecom = 1;
case ECOMMUNITY_ENCODE_OPAQUE: else
len = ecommunity_rt_soo_str(str_buf + str_pnt,
pnt, type, sub_type,
format);
} else if (type == ECOMMUNITY_ENCODE_OPAQUE) {
if (filter == ECOMMUNITY_ROUTE_TARGET) if (filter == ECOMMUNITY_ROUTE_TARGET)
{
continue; continue;
} if (*pnt == ECOMMUNITY_OPAQUE_SUBTYPE_ENCAP) {
if (*pnt == ECOMMUNITY_OPAQUE_SUBTYPE_ENCAP)
{
uint16_t tunneltype; uint16_t tunneltype;
memcpy(&tunneltype, pnt + 5, 2); memcpy(&tunneltype, pnt + 5, 2);
tunneltype = ntohs(tunneltype); tunneltype = ntohs(tunneltype);
len = sprintf (str_buf + str_pnt, "ET:%d", tunneltype); len = sprintf(str_buf + str_pnt, "ET:%d",
str_pnt += len; tunneltype);
first = 0; } else
continue; unk_ecom = 1;
} } else if (type == ECOMMUNITY_ENCODE_EVPN) {
len = sprintf (str_buf + str_pnt, "?");
str_pnt += len;
first = 0;
continue;
case ECOMMUNITY_ENCODE_EVPN:
if (filter == ECOMMUNITY_ROUTE_TARGET) if (filter == ECOMMUNITY_ROUTE_TARGET)
{
continue; continue;
} if (*pnt == ECOMMUNITY_SITE_ORIGIN) {
if (*pnt == ECOMMUNITY_SITE_ORIGIN)
{
char macaddr[6]; char macaddr[6];
pnt++; pnt++;
memcpy(&macaddr, pnt, 6); memcpy(&macaddr, pnt, 6);
len = sprintf(str_buf + str_pnt, "EVPN:%02x:%02x:%02x:%02x:%02x:%02x", len = sprintf(
str_buf + str_pnt,
"EVPN:%02x:%02x:%02x:%02x:%02x:%02x",
macaddr[0], macaddr[1], macaddr[2], macaddr[0], macaddr[1], macaddr[2],
macaddr[3], macaddr[4], macaddr[5]); macaddr[3], macaddr[4], macaddr[5]);
str_pnt += len; } else if (*pnt
first = 0; == ECOMMUNITY_EVPN_SUBTYPE_MACMOBILITY) {
continue; u_int32_t seqnum;
} u_char flags = *++pnt;
memcpy(&seqnum, pnt + 2, 4);
seqnum = ntohl(seqnum);
if (flags
& ECOMMUNITY_EVPN_SUBTYPE_MACMOBILITY_FLAG_STICKY)
len = sprintf(str_buf + str_pnt,
"MM:%u, sticky MAC",
seqnum);
else
len = sprintf(str_buf + str_pnt,
"MM:%u", seqnum);
} else
unk_ecom = 1;
} else
unk_ecom = 1;
if (unk_ecom)
len = sprintf(str_buf + str_pnt, "?"); len = sprintf(str_buf + str_pnt, "?");
str_pnt += len;
first = 0;
continue;
default:
len = sprintf (str_buf + str_pnt, "?");
str_pnt += len;
first = 0;
continue;
}
/* Low-order octet of type. */
type = *pnt++;
if (type != ECOMMUNITY_ROUTE_TARGET && type != ECOMMUNITY_SITE_ORIGIN)
{
len = sprintf (str_buf + str_pnt, "?");
str_pnt += len;
first = 0;
continue;
}
switch (format)
{
case ECOMMUNITY_FORMAT_COMMUNITY_LIST:
prefix = (type == ECOMMUNITY_ROUTE_TARGET ? "rt " : "soo ");
break;
case ECOMMUNITY_FORMAT_DISPLAY:
prefix = (type == ECOMMUNITY_ROUTE_TARGET ? "RT:" : "SoO:");
break;
case ECOMMUNITY_FORMAT_ROUTE_MAP:
prefix = "";
break;
default:
prefix = "";
break;
}
/* Put string into buffer. */
if (encode == ECOMMUNITY_ENCODE_AS4)
{
eas.as = (*pnt++ << 24);
eas.as |= (*pnt++ << 16);
eas.as |= (*pnt++ << 8);
eas.as |= (*pnt++);
eas.val = (*pnt++ << 8);
eas.val |= (*pnt++);
len = sprintf( str_buf + str_pnt, "%s%u:%u", prefix,
eas.as, eas.val );
str_pnt += len; str_pnt += len;
first = 0; first = 0;
} }
if (encode == ECOMMUNITY_ENCODE_AS)
{
eas.as = (*pnt++ << 8);
eas.as |= (*pnt++);
eas.val = (*pnt++ << 24);
eas.val |= (*pnt++ << 16);
eas.val |= (*pnt++ << 8);
eas.val |= (*pnt++);
len = sprintf (str_buf + str_pnt, "%s%u:%u", prefix,
eas.as, eas.val);
str_pnt += len;
first = 0;
}
else if (encode == ECOMMUNITY_ENCODE_IP)
{
memcpy (&eip.ip, pnt, 4);
pnt += 4;
eip.val = (*pnt++ << 8);
eip.val |= (*pnt++);
len = sprintf (str_buf + str_pnt, "%s%s:%u", prefix,
inet_ntoa (eip.ip), eip.val);
str_pnt += len;
first = 0;
}
}
return str_buf; return str_buf;
} }
int int ecommunity_match(const struct ecommunity *ecom1,
ecommunity_match (const struct ecommunity *ecom1,
const struct ecommunity *ecom2) const struct ecommunity *ecom2)
{ {
int i = 0; int i = 0;
@ -808,11 +773,10 @@ ecommunity_match (const struct ecommunity *ecom1,
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 < ecom1->size && j < ecom2->size) while (i < ecom1->size && j < ecom2->size) {
{
if (memcmp(ecom1->val + i * ECOMMUNITY_SIZE, if (memcmp(ecom1->val + i * ECOMMUNITY_SIZE,
ecom2->val + j * ECOMMUNITY_SIZE, ecom2->val + j * ECOMMUNITY_SIZE, ECOMMUNITY_SIZE)
ECOMMUNITY_SIZE) == 0) == 0)
j++; j++;
i++; i++;
} }
@ -824,17 +788,16 @@ ecommunity_match (const struct ecommunity *ecom1,
} }
/* return first occurence of type */ /* return first occurence of type */
extern struct ecommunity_val *ecommunity_lookup (const struct ecommunity *ecom, uint8_t type, uint8_t subtype) extern struct ecommunity_val *ecommunity_lookup(const struct ecommunity *ecom,
uint8_t type, uint8_t subtype)
{ {
u_int8_t *p; u_int8_t *p;
int c; int c;
/* 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 = ecom->val; c < ecom->size; p += ECOMMUNITY_SIZE, c++) for (p = ecom->val; c < ecom->size; p += ECOMMUNITY_SIZE, c++) {
{ if (p == NULL) {
if(p == NULL)
{
continue; continue;
} }
if (p[0] == type && p[1] == subtype) if (p[0] == type && p[1] == subtype)
@ -846,22 +809,20 @@ extern struct ecommunity_val *ecommunity_lookup (const struct ecommunity *ecom,
/* remove ext. community matching type and subtype /* remove ext. community matching type and subtype
* return 1 on success ( removed ), 0 otherwise (not present) * return 1 on success ( removed ), 0 otherwise (not present)
*/ */
extern int ecommunity_strip (struct ecommunity *ecom, uint8_t type, uint8_t subtype) extern int ecommunity_strip(struct ecommunity *ecom, uint8_t type,
uint8_t subtype)
{ {
u_int8_t *p; u_int8_t *p;
int c, found = 0; int c, found = 0;
/* When this is fist value, just add it. */ /* When this is fist value, just add it. */
if (ecom == NULL || ecom->val == NULL) if (ecom == NULL || ecom->val == NULL) {
{
return 0; return 0;
} }
/* 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 = ecom->val; c < ecom->size; p += ECOMMUNITY_SIZE, c++) for (p = ecom->val; c < ecom->size; p += ECOMMUNITY_SIZE, c++) {
{ if (p[0] == type && p[1] == subtype) {
if (p[0] == type && p[1] == subtype)
{
found = 1; found = 1;
break; break;
} }

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,8 +56,7 @@
#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;
@ -69,19 +71,64 @@ struct ecommunity
}; };
/* 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)
/*
* Encode BGP Route Target AS:nn.
*/
static inline void encode_route_target_as(as_t as, u_int32_t val,
struct ecommunity_val *eval)
{
eval->val[0] = ECOMMUNITY_ENCODE_AS;
eval->val[1] = ECOMMUNITY_ROUTE_TARGET;
eval->val[2] = (as >> 8) & 0xff;
eval->val[3] = as & 0xff;
eval->val[4] = (val >> 24) & 0xff;
eval->val[5] = (val >> 16) & 0xff;
eval->val[6] = (val >> 8) & 0xff;
eval->val[7] = val & 0xff;
}
/*
* Encode BGP Route Target IP:nn.
*/
static inline void encode_route_target_ip(struct in_addr ip, u_int16_t val,
struct ecommunity_val *eval)
{
eval->val[0] = ECOMMUNITY_ENCODE_IP;
eval->val[1] = ECOMMUNITY_ROUTE_TARGET;
memcpy(&eval->val[2], &ip, sizeof(struct in_addr));
eval->val[6] = (val >> 8) & 0xff;
eval->val[7] = val & 0xff;
}
/*
* Encode BGP Route Target AS4:nn.
*/
static inline void encode_route_target_as4(as_t as, u_int16_t val,
struct ecommunity_val *eval)
{
eval->val[0] = ECOMMUNITY_ENCODE_AS4;
eval->val[1] = ECOMMUNITY_ROUTE_TARGET;
eval->val[2] = (as >> 24) & 0xff;
eval->val[3] = (as >> 16) & 0xff;
eval->val[4] = (as >> 8) & 0xff;
eval->val[5] = as & 0xff;
eval->val[6] = (val >> 8) & 0xff;
eval->val[7] = val & 0xff;
}
extern void ecommunity_init(void); extern void ecommunity_init(void);
extern void ecommunity_finish(void); extern void ecommunity_finish(void);
extern void ecommunity_free(struct ecommunity **); extern void ecommunity_free(struct ecommunity **);
extern struct ecommunity *ecommunity_parse(u_int8_t *, u_short); extern struct ecommunity *ecommunity_parse(u_int8_t *, u_short);
extern struct ecommunity *ecommunity_dup(struct ecommunity *); extern struct ecommunity *ecommunity_dup(struct ecommunity *);
extern struct ecommunity *ecommunity_merge (struct ecommunity *, struct ecommunity *); extern struct ecommunity *ecommunity_merge(struct ecommunity *,
struct ecommunity *);
extern struct ecommunity *ecommunity_uniq_sort(struct ecommunity *); extern struct ecommunity *ecommunity_uniq_sort(struct ecommunity *);
extern struct ecommunity *ecommunity_intern(struct ecommunity *); extern struct ecommunity *ecommunity_intern(struct ecommunity *);
extern int ecommunity_cmp(const void *, const void *); extern int ecommunity_cmp(const void *, const void *);
@ -89,14 +136,18 @@ extern void ecommunity_unintern (struct ecommunity **);
extern unsigned int ecommunity_hash_make(void *); extern unsigned int ecommunity_hash_make(void *);
extern struct ecommunity *ecommunity_str2com(const char *, int, int); extern struct ecommunity *ecommunity_str2com(const char *, int, int);
extern char *ecommunity_ecom2str(struct ecommunity *, int, int); extern char *ecommunity_ecom2str(struct ecommunity *, int, int);
extern int ecommunity_match (const struct ecommunity *, const struct ecommunity *); extern int ecommunity_match(const struct ecommunity *,
const struct ecommunity *);
extern char *ecommunity_str(struct ecommunity *); extern char *ecommunity_str(struct ecommunity *);
extern struct ecommunity_val *ecommunity_lookup (const struct ecommunity *, uint8_t, uint8_t ); extern struct ecommunity_val *ecommunity_lookup(const struct ecommunity *,
extern int ecommunity_add_val (struct ecommunity *ecom, struct ecommunity_val *eval); 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,
uint8_t subtype);
extern struct ecommunity *ecommunity_new(void); 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,157 +19,115 @@
#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 extern void bgp_encap_type_gre_to_tlv(struct bgp_encap_type_gre *bet,
bgp_encap_type_gre_to_tlv(
struct bgp_encap_type_gre *bet,
struct attr *attr); struct attr *attr);
extern void extern void bgp_encap_type_ip_in_ip_to_tlv(struct bgp_encap_type_ip_in_ip *bet,
bgp_encap_type_ip_in_ip_to_tlv(
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_transmit_tunnel_endpoint( struct bgp_encap_type_transmit_tunnel_endpoint *bet, struct attr *attr);
struct bgp_encap_type_transmit_tunnel_endpoint *bet,
struct attr *attr);
extern void extern void bgp_encap_type_ipsec_in_tunnel_mode_to_tlv(
bgp_encap_type_ipsec_in_tunnel_mode_to_tlv( struct bgp_encap_type_ipsec_in_tunnel_mode *bet, struct attr *attr);
struct bgp_encap_type_ipsec_in_tunnel_mode *bet,
struct attr *attr);
extern void extern void bgp_encap_type_ip_in_ip_tunnel_with_ipsec_transport_mode_to_tlv(
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 bgp_encap_type_ip_in_ip_tunnel_with_ipsec_transport_mode *bet,
struct attr *attr); struct attr *attr);
extern void extern void bgp_encap_type_mpls_in_ip_tunnel_with_ipsec_transport_mode_to_tlv(
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 bgp_encap_type_mpls_in_ip_tunnel_with_ipsec_transport_mode *bet,
struct attr *attr); struct attr *attr);
extern void extern void bgp_encap_type_pbb_to_tlv(struct bgp_encap_type_pbb *bet,
bgp_encap_type_pbb_to_tlv( struct attr *attr);
struct bgp_encap_type_pbb *bet,
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); struct attr *attr);
extern void extern void
bgp_encap_type_vxlan_to_tlv( bgp_encap_type_mpls_in_gre_to_tlv(struct bgp_encap_type_mpls_in_gre *bet,
struct bgp_encap_type_vxlan *bet,
struct attr *attr); struct attr *attr);
extern void extern void
bgp_encap_type_nvgre_to_tlv( bgp_encap_type_vxlan_gpe_to_tlv(struct bgp_encap_type_vxlan_gpe *bet,
struct bgp_encap_type_nvgre *bet,
struct attr *attr); struct attr *attr);
extern void extern void
bgp_encap_type_mpls_to_tlv( bgp_encap_type_mpls_in_udp_to_tlv(struct bgp_encap_type_mpls_in_udp *bet,
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); 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 extern int tlv_to_bgp_encap_type_gre(
tlv_to_bgp_encap_type_gre(
struct bgp_attr_encap_subtlv *stlv, /* subtlv chain */ struct bgp_attr_encap_subtlv *stlv, /* subtlv chain */
struct bgp_encap_type_gre *bet); /* caller-allocated */ 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_ip_in_ip(
struct bgp_attr_encap_subtlv *stlv, /* subtlv chain */ struct bgp_attr_encap_subtlv *stlv, /* subtlv chain */
struct bgp_encap_type_ip_in_ip *bet); /* caller-allocated */ 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_transmit_tunnel_endpoint(
struct bgp_attr_encap_subtlv *stlv, struct bgp_attr_encap_subtlv *stlv,
struct bgp_encap_type_transmit_tunnel_endpoint *bet); struct bgp_encap_type_transmit_tunnel_endpoint *bet);
extern int extern int tlv_to_bgp_encap_type_ipsec_in_tunnel_mode(
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_ipsec_in_tunnel_mode *bet); /* caller-allocated */ struct bgp_encap_type_ipsec_in_tunnel_mode *bet); /* caller-allocated */
extern int extern int tlv_to_bgp_encap_type_ip_in_ip_tunnel_with_ipsec_transport_mode(
tlv_to_bgp_encap_type_ip_in_ip_tunnel_with_ipsec_transport_mode(
struct bgp_attr_encap_subtlv *stlv, struct bgp_attr_encap_subtlv *stlv,
struct bgp_encap_type_ip_in_ip_tunnel_with_ipsec_transport_mode *bet); struct bgp_encap_type_ip_in_ip_tunnel_with_ipsec_transport_mode *bet);
extern int extern int tlv_to_bgp_encap_type_mpls_in_ip_tunnel_with_ipsec_transport_mode(
tlv_to_bgp_encap_type_mpls_in_ip_tunnel_with_ipsec_transport_mode(
struct bgp_attr_encap_subtlv *stlv, struct bgp_attr_encap_subtlv *stlv,
struct bgp_encap_type_mpls_in_ip_tunnel_with_ipsec_transport_mode *bet); struct bgp_encap_type_mpls_in_ip_tunnel_with_ipsec_transport_mode *bet);
extern int extern int tlv_to_bgp_encap_type_vxlan(struct bgp_attr_encap_subtlv *stlv,
tlv_to_bgp_encap_type_vxlan(
struct bgp_attr_encap_subtlv *stlv,
struct bgp_encap_type_vxlan *bet); struct bgp_encap_type_vxlan *bet);
extern int extern int tlv_to_bgp_encap_type_nvgre(struct bgp_attr_encap_subtlv *stlv,
tlv_to_bgp_encap_type_nvgre(
struct bgp_attr_encap_subtlv *stlv,
struct bgp_encap_type_nvgre *bet); struct bgp_encap_type_nvgre *bet);
extern int extern int tlv_to_bgp_encap_type_mpls(struct bgp_attr_encap_subtlv *stlv,
tlv_to_bgp_encap_type_mpls( struct bgp_encap_type_mpls *bet);
struct bgp_attr_encap_subtlv *stlv,
extern int tlv_to_bgp_encap_type_mpls(struct bgp_attr_encap_subtlv *stlv,
struct bgp_encap_type_mpls *bet); struct bgp_encap_type_mpls *bet);
extern int extern int
tlv_to_bgp_encap_type_mpls( tlv_to_bgp_encap_type_mpls_in_gre(struct bgp_attr_encap_subtlv *stlv,
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); struct bgp_encap_type_mpls_in_gre *bet);
extern int extern int
tlv_to_bgp_encap_type_vxlan_gpe( tlv_to_bgp_encap_type_vxlan_gpe(struct bgp_attr_encap_subtlv *stlv,
struct bgp_attr_encap_subtlv *stlv,
struct bgp_encap_type_vxlan_gpe *bet); struct bgp_encap_type_vxlan_gpe *bet);
extern int extern int
tlv_to_bgp_encap_type_mpls_in_udp( 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_mpls_in_udp *bet);
extern int extern int tlv_to_bgp_encap_type_pbb(
tlv_to_bgp_encap_type_pbb(
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_pbb *bet); /* caller-allocated */

View File

@ -19,7 +19,11 @@
#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,
@ -43,7 +47,8 @@ typedef enum {
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;
/* /*
@ -213,4 +218,14 @@ struct bgp_encap_type_pbb {
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,
extern void struct prefix *p, struct bgp_info *ri);
bgp_packet_mpattr_route_type_5(struct stream *s, extern int bgp_evpn_unimport_route(struct bgp *bgp, afi_t afi, safi_t safi,
struct prefix *p, struct prefix_rd *prd, struct prefix *p, struct bgp_info *ri);
u_char * label, struct attr *attr); extern int bgp_evpn_local_macip_del(struct bgp *bgp, vni_t vni,
/* EVPN route types as per RFC7432 and struct ethaddr *mac, struct ipaddr *ip);
* as per draft-ietf-bess-evpn-prefix-advertisement-02 extern int bgp_evpn_local_macip_add(struct bgp *bgp, vni_t vni,
*/ struct ethaddr *mac, struct ipaddr *ip,
#define EVPN_ETHERNET_AUTO_DISCOVERY 1 u_char sticky);
#define EVPN_MACIP_ADVERTISEMENT 2 extern int bgp_evpn_local_vni_del(struct bgp *bgp, vni_t vni);
#define EVPN_INCLUSIVE_MULTICAST_ETHERNET_TAG 3 extern int bgp_evpn_local_vni_add(struct bgp *bgp, vni_t vni,
#define EVPN_ETHERNET_SEGMENT 4 struct in_addr originator_ip);
#define EVPN_IP_PREFIX 5 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);
#endif /* _QUAGGA_BGP_EVPN_H */ #endif /* _QUAGGA_BGP_EVPN_H */

213
bgpd/bgp_evpn_private.h Normal file
View File

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

File diff suppressed because it is too large Load Diff

View File

@ -21,6 +21,8 @@
#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"

View File

@ -33,15 +33,13 @@
#include "bgpd/bgp_filter.h" #include "bgpd/bgp_filter.h"
/* List of AS filter list. */ /* List of AS filter list. */
struct as_list_list struct as_list_list {
{
struct as_list *head; struct as_list *head;
struct as_list *tail; struct as_list *tail;
}; };
/* AS path filter master. */ /* AS path filter master. */
struct as_list_master struct as_list_master {
{
/* List of access_list which name is number. */ /* List of access_list which name is number. */
struct as_list_list num; struct as_list_list num;
@ -56,8 +54,7 @@ struct as_list_master
}; };
/* Element of AS path filter. */ /* Element of AS path filter. */
struct as_filter struct as_filter {
{
struct as_filter *next; struct as_filter *next;
struct as_filter *prev; struct as_filter *prev;
@ -68,8 +65,7 @@ struct as_filter
}; };
/* AS path filter list. */ /* AS path filter list. */
struct as_list struct as_list {
{
char *name; char *name;
enum access_type type; enum access_type type;
@ -83,24 +79,19 @@ struct as_list
/* ip as-path access-list 10 permit AS1. */ /* ip as-path access-list 10 permit AS1. */
static struct as_list_master as_list_master = static struct as_list_master as_list_master = {{NULL, NULL},
{
{NULL, NULL},
{NULL, NULL}, {NULL, NULL},
NULL, NULL,
NULL NULL};
};
/* Allocate new AS filter. */ /* Allocate new AS filter. */
static struct as_filter * static struct as_filter *as_filter_new(void)
as_filter_new (void)
{ {
return XCALLOC(MTYPE_AS_FILTER, sizeof(struct as_filter)); return XCALLOC(MTYPE_AS_FILTER, sizeof(struct as_filter));
} }
/* Free allocated AS filter. */ /* Free allocated AS filter. */
static void static void as_filter_free(struct as_filter *asfilter)
as_filter_free (struct as_filter *asfilter)
{ {
if (asfilter->reg) if (asfilter->reg)
bgp_regex_free(asfilter->reg); bgp_regex_free(asfilter->reg);
@ -110,8 +101,8 @@ as_filter_free (struct as_filter *asfilter)
} }
/* Make new AS filter. */ /* Make new AS filter. */
static struct as_filter * static struct as_filter *as_filter_make(regex_t *reg, const char *reg_str,
as_filter_make (regex_t *reg, const char *reg_str, enum as_filter_type type) enum as_filter_type type)
{ {
struct as_filter *asfilter; struct as_filter *asfilter;
@ -123,8 +114,8 @@ as_filter_make (regex_t *reg, const char *reg_str, enum as_filter_type type)
return asfilter; return asfilter;
} }
static struct as_filter * static struct as_filter *as_filter_lookup(struct as_list *aslist,
as_filter_lookup (struct as_list *aslist, const char *reg_str, const char *reg_str,
enum as_filter_type type) enum as_filter_type type)
{ {
struct as_filter *asfilter; struct as_filter *asfilter;
@ -135,8 +126,8 @@ as_filter_lookup (struct as_list *aslist, const char *reg_str,
return NULL; return NULL;
} }
static void static void as_list_filter_add(struct as_list *aslist,
as_list_filter_add (struct as_list *aslist, struct as_filter *asfilter) struct as_filter *asfilter)
{ {
asfilter->next = NULL; asfilter->next = NULL;
asfilter->prev = aslist->tail; asfilter->prev = aslist->tail;
@ -150,12 +141,10 @@ as_list_filter_add (struct as_list *aslist, struct as_filter *asfilter)
/* Run hook function. */ /* Run hook function. */
if (as_list_master.add_hook) if (as_list_master.add_hook)
(*as_list_master.add_hook)(aslist->name); (*as_list_master.add_hook)(aslist->name);
} }
/* Lookup as_list from list of as_list by name. */ /* Lookup as_list from list of as_list by name. */
struct as_list * struct as_list *as_list_lookup(const char *name)
as_list_lookup (const char *name)
{ {
struct as_list *aslist; struct as_list *aslist;
@ -173,17 +162,14 @@ as_list_lookup (const char *name)
return NULL; return NULL;
} }
static struct as_list * static struct as_list *as_list_new(void)
as_list_new (void)
{ {
return XCALLOC(MTYPE_AS_LIST, sizeof(struct as_list)); return XCALLOC(MTYPE_AS_LIST, sizeof(struct as_list));
} }
static void static void as_list_free(struct as_list *aslist)
as_list_free (struct as_list *aslist)
{
if (aslist->name)
{ {
if (aslist->name) {
XFREE(MTYPE_AS_STR, aslist->name); XFREE(MTYPE_AS_STR, aslist->name);
aslist->name = NULL; aslist->name = NULL;
} }
@ -192,8 +178,7 @@ as_list_free (struct as_list *aslist)
/* Insert new AS list to list of as_list. Each as_list is sorted by /* Insert new AS list to list of as_list. Each as_list is sorted by
the name. */ the name. */
static struct as_list * static struct as_list *as_list_insert(const char *name)
as_list_insert (const char *name)
{ {
size_t i; size_t i;
long number; long number;
@ -208,8 +193,7 @@ as_list_insert (const char *name)
/* If name is made by all digit character. We treat it as /* If name is made by all digit character. We treat it as
number. */ number. */
for (number = 0, i = 0; i < strlen (name); i++) for (number = 0, i = 0; i < strlen(name); i++) {
{
if (isdigit((int)name[i])) if (isdigit((int)name[i]))
number = (number * 10) + (name[i] - '0'); number = (number * 10) + (name[i] - '0');
else else
@ -217,8 +201,7 @@ as_list_insert (const char *name)
} }
/* In case of name is all digit character */ /* In case of name is all digit character */
if (i == strlen (name)) if (i == strlen(name)) {
{
aslist->type = ACCESS_TYPE_NUMBER; aslist->type = ACCESS_TYPE_NUMBER;
/* Set access_list to number list. */ /* Set access_list to number list. */
@ -227,9 +210,7 @@ as_list_insert (const char *name)
for (point = list->head; point; point = point->next) for (point = list->head; point; point = point->next)
if (atol(point->name) >= number) if (atol(point->name) >= number)
break; break;
} } else {
else
{
aslist->type = ACCESS_TYPE_STRING; aslist->type = ACCESS_TYPE_STRING;
/* Set access_list to string list. */ /* Set access_list to string list. */
@ -242,15 +223,13 @@ as_list_insert (const char *name)
} }
/* In case of this is the first element of master. */ /* In case of this is the first element of master. */
if (list->head == NULL) if (list->head == NULL) {
{
list->head = list->tail = aslist; list->head = list->tail = aslist;
return aslist; return aslist;
} }
/* In case of insertion is made at the tail of access_list. */ /* In case of insertion is made at the tail of access_list. */
if (point == NULL) if (point == NULL) {
{
aslist->prev = list->tail; aslist->prev = list->tail;
list->tail->next = aslist; list->tail->next = aslist;
list->tail = aslist; list->tail = aslist;
@ -258,8 +237,7 @@ as_list_insert (const char *name)
} }
/* In case of insertion is made at the head of access_list. */ /* In case of insertion is made at the head of access_list. */
if (point == list->head) if (point == list->head) {
{
aslist->next = list->head; aslist->next = list->head;
list->head->prev = aslist; list->head->prev = aslist;
list->head = aslist; list->head = aslist;
@ -277,8 +255,7 @@ as_list_insert (const char *name)
return aslist; return aslist;
} }
static struct as_list * static struct as_list *as_list_get(const char *name)
as_list_get (const char *name)
{ {
struct as_list *aslist; struct as_list *aslist;
@ -289,11 +266,9 @@ as_list_get (const char *name)
return aslist; return aslist;
} }
static const char * static const char *filter_type_str(enum as_filter_type type)
filter_type_str (enum as_filter_type type)
{
switch (type)
{ {
switch (type) {
case AS_FILTER_PERMIT: case AS_FILTER_PERMIT:
return "permit"; return "permit";
case AS_FILTER_DENY: case AS_FILTER_DENY:
@ -303,14 +278,12 @@ filter_type_str (enum as_filter_type type)
} }
} }
static void static void as_list_delete(struct as_list *aslist)
as_list_delete (struct as_list *aslist)
{ {
struct as_list_list *list; struct as_list_list *list;
struct as_filter *filter, *next; struct as_filter *filter, *next;
for (filter = aslist->head; filter; filter = next) for (filter = aslist->head; filter; filter = next) {
{
next = filter->next; next = filter->next;
as_filter_free(filter); as_filter_free(filter);
} }
@ -333,8 +306,7 @@ as_list_delete (struct as_list *aslist)
as_list_free(aslist); as_list_free(aslist);
} }
static int static int as_list_empty(struct as_list *aslist)
as_list_empty (struct as_list *aslist)
{ {
if (aslist->head == NULL && aslist->tail == NULL) if (aslist->head == NULL && aslist->tail == NULL)
return 1; return 1;
@ -342,8 +314,8 @@ as_list_empty (struct as_list *aslist)
return 0; return 0;
} }
static void static void as_list_filter_delete(struct as_list *aslist,
as_list_filter_delete (struct as_list *aslist, struct as_filter *asfilter) struct as_filter *asfilter)
{ {
char *name = XSTRDUP(MTYPE_AS_STR, aslist->name); char *name = XSTRDUP(MTYPE_AS_STR, aslist->name);
@ -370,8 +342,7 @@ as_list_filter_delete (struct as_list *aslist, struct as_filter *asfilter)
XFREE(MTYPE_AS_STR, name); XFREE(MTYPE_AS_STR, name);
} }
static int static int as_filter_match(struct as_filter *asfilter, struct aspath *aspath)
as_filter_match (struct as_filter *asfilter, struct aspath *aspath)
{ {
if (bgp_regexec(asfilter->reg, aspath) != REG_NOMATCH) if (bgp_regexec(asfilter->reg, aspath) != REG_NOMATCH)
return 1; return 1;
@ -379,8 +350,7 @@ as_filter_match (struct as_filter *asfilter, struct aspath *aspath)
} }
/* Apply AS path filter to AS. */ /* Apply AS path filter to AS. */
enum as_filter_type enum as_filter_type as_list_apply(struct as_list *aslist, void *object)
as_list_apply (struct as_list *aslist, void *object)
{ {
struct as_filter *asfilter; struct as_filter *asfilter;
struct aspath *aspath; struct aspath *aspath;
@ -390,8 +360,7 @@ as_list_apply (struct as_list *aslist, void *object)
if (aslist == NULL) if (aslist == NULL)
return AS_FILTER_DENY; return AS_FILTER_DENY;
for (asfilter = aslist->head; asfilter; asfilter = asfilter->next) for (asfilter = aslist->head; asfilter; asfilter = asfilter->next) {
{
if (as_filter_match(asfilter, aspath)) if (as_filter_match(asfilter, aspath))
return asfilter->type; return asfilter->type;
} }
@ -399,26 +368,22 @@ as_list_apply (struct as_list *aslist, void *object)
} }
/* Add hook function. */ /* Add hook function. */
void void as_list_add_hook(void (*func)(char *))
as_list_add_hook (void (*func) (char *))
{ {
as_list_master.add_hook = func; as_list_master.add_hook = func;
} }
/* Delete hook function. */ /* Delete hook function. */
void void as_list_delete_hook(void (*func)(const char *))
as_list_delete_hook (void (*func) (const char *))
{ {
as_list_master.delete_hook = func; as_list_master.delete_hook = func;
} }
static int static int as_list_dup_check(struct as_list *aslist, struct as_filter *new)
as_list_dup_check (struct as_list *aslist, struct as_filter *new)
{ {
struct as_filter *asfilter; struct as_filter *asfilter;
for (asfilter = aslist->head; asfilter; asfilter = asfilter->next) for (asfilter = aslist->head; asfilter; asfilter = asfilter->next) {
{
if (asfilter->type == new->type if (asfilter->type == new->type
&& strcmp(asfilter->reg_str, new->reg_str) == 0) && strcmp(asfilter->reg_str, new->reg_str) == 0)
return 1; return 1;
@ -445,21 +410,22 @@ DEFUN (ip_as_path,
char *regstr; char *regstr;
/* Retrieve access list name */ /* Retrieve access list name */
char *alname = argv_find (argv, argc, "WORD", &idx) ? argv[idx]->arg : NULL; char *alname =
argv_find(argv, argc, "WORD", &idx) ? argv[idx]->arg : NULL;
/* Check the filter type. */ /* Check the filter type. */
type = argv_find (argv, argc, "deny", &idx) ? AS_FILTER_DENY : AS_FILTER_PERMIT; type = argv_find(argv, argc, "deny", &idx) ? AS_FILTER_DENY
: AS_FILTER_PERMIT;
/* Check AS path regex. */ /* Check AS path regex. */
argv_find(argv, argc, "LINE", &idx); argv_find(argv, argc, "LINE", &idx);
regstr = argv_concat(argv, argc, idx); regstr = argv_concat(argv, argc, idx);
regex = bgp_regcomp(regstr); regex = bgp_regcomp(regstr);
if (!regex) if (!regex) {
{ vty_out(vty, "can't compile regexp %s\n", regstr);
vty_outln (vty, "can't compile regexp %s", regstr);
XFREE(MTYPE_TMP, regstr); XFREE(MTYPE_TMP, regstr);
return CMD_WARNING; return CMD_WARNING_CONFIG_FAILED;
} }
asfilter = as_filter_make(regex, regstr, type); asfilter = as_filter_make(regex, regstr, type);
@ -497,14 +463,15 @@ DEFUN (no_ip_as_path,
char *regstr; char *regstr;
regex_t *regex; regex_t *regex;
char *aslistname = argv_find (argv, argc, "WORD", &idx) ? argv[idx]->arg : NULL; char *aslistname =
argv_find(argv, argc, "WORD", &idx) ? argv[idx]->arg : NULL;
/* Lookup AS list from AS path list. */ /* Lookup AS list from AS path list. */
aslist = as_list_lookup(aslistname); aslist = as_list_lookup(aslistname);
if (aslist == NULL) if (aslist == NULL) {
{ vty_out(vty, "ip as-path access-list %s doesn't exist\n",
vty_outln (vty, "ip as-path access-list %s doesn't exist",aslistname); aslistname);
return CMD_WARNING; return CMD_WARNING_CONFIG_FAILED;
} }
/* Check the filter type. */ /* Check the filter type. */
@ -512,10 +479,9 @@ DEFUN (no_ip_as_path,
type = AS_FILTER_PERMIT; type = AS_FILTER_PERMIT;
else if (argv_find(argv, argc, "deny", &idx)) else if (argv_find(argv, argc, "deny", &idx))
type = AS_FILTER_DENY; type = AS_FILTER_DENY;
else else {
{ vty_out(vty, "filter type must be [permit|deny]\n");
vty_outln (vty, "filter type must be [permit|deny]"); return CMD_WARNING_CONFIG_FAILED;
return CMD_WARNING;
} }
/* Compile AS path. */ /* Compile AS path. */
@ -523,11 +489,10 @@ DEFUN (no_ip_as_path,
regstr = argv_concat(argv, argc, idx); regstr = argv_concat(argv, argc, idx);
regex = bgp_regcomp(regstr); regex = bgp_regcomp(regstr);
if (!regex) if (!regex) {
{ vty_out(vty, "can't compile regexp %s\n", regstr);
vty_outln (vty, "can't compile regexp %s", regstr);
XFREE(MTYPE_TMP, regstr); XFREE(MTYPE_TMP, regstr);
return CMD_WARNING; return CMD_WARNING_CONFIG_FAILED;
} }
/* Lookup asfilter. */ /* Lookup asfilter. */
@ -536,10 +501,9 @@ DEFUN (no_ip_as_path,
XFREE(MTYPE_TMP, regstr); XFREE(MTYPE_TMP, regstr);
bgp_regex_free(regex); bgp_regex_free(regex);
if (asfilter == NULL) if (asfilter == NULL) {
{ vty_out(vty, "\n");
vty_out (vty, VTYNL); return CMD_WARNING_CONFIG_FAILED;
return CMD_WARNING;
} }
as_list_filter_delete(aslist, asfilter); as_list_filter_delete(aslist, asfilter);
@ -560,11 +524,10 @@ DEFUN (no_ip_as_path_all,
struct as_list *aslist; struct as_list *aslist;
aslist = as_list_lookup(argv[idx_word]->arg); aslist = as_list_lookup(argv[idx_word]->arg);
if (aslist == NULL) if (aslist == NULL) {
{ vty_out(vty, "ip as-path access-list %s doesn't exist\n",
vty_outln (vty, "ip as-path access-list %s doesn't exist",
argv[idx_word]->arg); argv[idx_word]->arg);
return CMD_WARNING; return CMD_WARNING_CONFIG_FAILED;
} }
as_list_delete(aslist); as_list_delete(aslist);
@ -576,44 +539,41 @@ DEFUN (no_ip_as_path_all,
return CMD_SUCCESS; return CMD_SUCCESS;
} }
static void static void as_list_show(struct vty *vty, struct as_list *aslist)
as_list_show (struct vty *vty, struct as_list *aslist)
{ {
struct as_filter *asfilter; struct as_filter *asfilter;
vty_outln (vty, "AS path access list %s", aslist->name); vty_out(vty, "AS path access list %s\n", aslist->name);
for (asfilter = aslist->head; asfilter; asfilter = asfilter->next) for (asfilter = aslist->head; asfilter; asfilter = asfilter->next) {
{ vty_out(vty, " %s %s\n", filter_type_str(asfilter->type),
vty_outln (vty, " %s %s", filter_type_str (asfilter->type),
asfilter->reg_str); asfilter->reg_str);
} }
} }
static void static void as_list_show_all(struct vty *vty)
as_list_show_all (struct vty *vty)
{ {
struct as_list *aslist; struct as_list *aslist;
struct as_filter *asfilter; struct as_filter *asfilter;
for (aslist = as_list_master.num.head; aslist; aslist = aslist->next) for (aslist = as_list_master.num.head; aslist; aslist = aslist->next) {
{ vty_out(vty, "AS path access list %s\n", aslist->name);
vty_outln (vty, "AS path access list %s", aslist->name);
for (asfilter = aslist->head; asfilter; asfilter = asfilter->next) for (asfilter = aslist->head; asfilter;
{ asfilter = asfilter->next) {
vty_outln (vty, " %s %s", filter_type_str (asfilter->type), vty_out(vty, " %s %s\n",
filter_type_str(asfilter->type),
asfilter->reg_str); asfilter->reg_str);
} }
} }
for (aslist = as_list_master.str.head; aslist; aslist = aslist->next) for (aslist = as_list_master.str.head; aslist; aslist = aslist->next) {
{ vty_out(vty, "AS path access list %s\n", aslist->name);
vty_outln (vty, "AS path access list %s", aslist->name);
for (asfilter = aslist->head; asfilter; asfilter = asfilter->next) for (asfilter = aslist->head; asfilter;
{ asfilter = asfilter->next) {
vty_outln (vty, " %s %s", filter_type_str (asfilter->type), vty_out(vty, " %s %s\n",
filter_type_str(asfilter->type),
asfilter->reg_str); asfilter->reg_str);
} }
} }
@ -648,26 +608,25 @@ DEFUN (show_ip_as_path_access_list_all,
return CMD_SUCCESS; return CMD_SUCCESS;
} }
static int static int config_write_as_list(struct vty *vty)
config_write_as_list (struct vty *vty)
{ {
struct as_list *aslist; struct as_list *aslist;
struct as_filter *asfilter; struct as_filter *asfilter;
int write = 0; int write = 0;
for (aslist = as_list_master.num.head; aslist; aslist = aslist->next) for (aslist = as_list_master.num.head; aslist; aslist = aslist->next)
for (asfilter = aslist->head; asfilter; asfilter = asfilter->next) for (asfilter = aslist->head; asfilter;
{ asfilter = asfilter->next) {
vty_outln (vty, "ip as-path access-list %s %s %s", vty_out(vty, "ip as-path access-list %s %s %s\n",
aslist->name, filter_type_str(asfilter->type), aslist->name, filter_type_str(asfilter->type),
asfilter->reg_str); asfilter->reg_str);
write++; write++;
} }
for (aslist = as_list_master.str.head; aslist; aslist = aslist->next) for (aslist = as_list_master.str.head; aslist; aslist = aslist->next)
for (asfilter = aslist->head; asfilter; asfilter = asfilter->next) for (asfilter = aslist->head; asfilter;
{ asfilter = asfilter->next) {
vty_outln (vty, "ip as-path access-list %s %s %s", vty_out(vty, "ip as-path access-list %s %s %s\n",
aslist->name, filter_type_str(asfilter->type), aslist->name, filter_type_str(asfilter->type),
asfilter->reg_str); asfilter->reg_str);
write++; write++;
@ -675,16 +634,10 @@ config_write_as_list (struct vty *vty)
return write; return write;
} }
static struct cmd_node as_list_node = static struct cmd_node as_list_node = {AS_LIST_NODE, "", 1};
{
AS_LIST_NODE,
"",
1
};
/* Register functions. */ /* Register functions. */
void void bgp_filter_init(void)
bgp_filter_init (void)
{ {
install_node(&as_list_node, config_write_as_list); install_node(&as_list_node, config_write_as_list);
@ -696,20 +649,17 @@ bgp_filter_init (void)
install_element(VIEW_NODE, &show_ip_as_path_access_list_all_cmd); install_element(VIEW_NODE, &show_ip_as_path_access_list_all_cmd);
} }
void void bgp_filter_reset(void)
bgp_filter_reset (void)
{ {
struct as_list *aslist; struct as_list *aslist;
struct as_list *next; struct as_list *next;
for (aslist = as_list_master.num.head; aslist; aslist = next) for (aslist = as_list_master.num.head; aslist; aslist = next) {
{
next = aslist->next; next = aslist->next;
as_list_delete(aslist); as_list_delete(aslist);
} }
for (aslist = as_list_master.str.head; aslist; aslist = next) for (aslist = as_list_master.str.head; aslist; aslist = next) {
{
next = aslist->next; next = aslist->next;
as_list_delete(aslist); as_list_delete(aslist);
} }

View File

@ -21,11 +21,7 @@
#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);

File diff suppressed because it is too large Load Diff

View File

@ -68,7 +68,8 @@
#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), \
NULL); \
} while (0) } while (0)
#define BGP_EVENT_FLUSH(P) \ #define BGP_EVENT_FLUSH(P) \

View File

@ -41,8 +41,7 @@
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;
@ -63,34 +62,30 @@ bgp_parse_fec_update (void)
/* 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"); zlog_debug("no node for the prefix");
return -1; 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);
@ -98,22 +93,23 @@ bgp_parse_fec_update (void)
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
&& !CHECK_FLAG(to->af_flags[afi][safi],
PEER_FLAG_FORCE_NEXTHOP_SELF)) PEER_FLAG_FORCE_NEXTHOP_SELF))
return remote_label; return remote_label;
@ -123,9 +119,7 @@ bgp_adv_label (struct bgp_node *rn, struct bgp_info *ri, struct peer *to,
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;
@ -146,22 +140,16 @@ bgp_reg_dereg_for_label (struct bgp_node *rn, struct bgp_info *ri,
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) {
assert (ri->attr->extra);
if (ri->attr->extra->label_index != BGP_INVALID_LABEL_INDEX)
{
flags |= ZEBRA_FEC_REGISTER_LABEL_INDEX; flags |= ZEBRA_FEC_REGISTER_LABEL_INDEX;
stream_putl (s, ri->attr->extra->label_index); stream_putl(s, ri->attr->label_index);
} }
} }
SET_FLAG(rn->flags, BGP_NODE_REGISTERED_FOR_LABEL); SET_FLAG(rn->flags, BGP_NODE_REGISTERED_FOR_LABEL);
} } else
else
UNSET_FLAG(rn->flags, BGP_NODE_REGISTERED_FOR_LABEL); UNSET_FLAG(rn->flags, BGP_NODE_REGISTERED_FOR_LABEL);
/* Set length and flags */ /* Set length and flags */
@ -171,30 +159,40 @@ bgp_reg_dereg_for_label (struct bgp_node *rn, struct bgp_info *ri,
zclient_send_message(zclient); 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 += 3; llen += BGP_LABEL_BYTES;
bgp_set_valid_label(label);
label_depth += 1;
if (bgp_is_withdraw_label(label) || label_bos(label)) if (bgp_is_withdraw_label(label) || label_bos(label))
break; 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))) if (!(bgp_is_withdraw_label(label) || label_bos(label)))
zlog_warn("%s: [Update:RCVD] invalid label - no bottom of stack", zlog_warn(
"%s rcvd UPDATE with invalid label stack - no bottom of stack",
peer->host); peer->host);
return llen; 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;
@ -206,7 +204,7 @@ bgp_nlri_parse_label (struct peer *peer, struct attr *attr,
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. */
@ -219,17 +217,17 @@ bgp_nlri_parse_label (struct peer *peer, struct attr *attr,
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)
@ -245,23 +243,21 @@ bgp_nlri_parse_label (struct peer *peer, struct attr *attr,
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,
@ -277,62 +273,66 @@ bgp_nlri_parse_label (struct peer *peer, struct attr *attr,
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
* (e.g., an unexpected multicast IP address), an error SHOULD * incorrect
* be logged locally, and the prefix SHOULD be ignored. * (e.g., an unexpected multicast IP address),
* an error SHOULD
* be logged locally, and the prefix SHOULD be
* ignored.
*/ */
zlog_err ("%s: IPv4 labeled-unicast NLRI is multicast address %s, ignoring", zlog_err(
"%s: IPv4 labeled-unicast NLRI is multicast address %s, ignoring",
peer->host, inet_ntoa(p.u.prefix4)); peer->host, inet_ntoa(p.u.prefix4));
continue; 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;
} }

View File

@ -32,82 +32,80 @@ 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.
*/
if ((safi == SAFI_LABELED_UNICAST) || (safi == SAFI_MPLS_VPN)
|| (safi == SAFI_EVPN))
return 1; return 1;
return 0; 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;
/* 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 1;
return 0; 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;
return pkt;
}
static inline int
bgp_is_valid_label (u_char *t)
{ {
u_char *t = (u_char *)label;
if (!t) if (!t)
return 0; return 0;
return (t[2] & 0x02); return (t[2] & 0x02);
} }
static inline void static inline void bgp_set_valid_label(mpls_label_t *label)
bgp_set_valid_label (u_char *t)
{ {
u_char *t = (u_char *)label;
if (t) if (t)
t[2] |= 0x02; t[2] |= 0x02;
} }
static inline void static inline void bgp_unset_valid_label(mpls_label_t *label)
bgp_unset_valid_label (u_char *t)
{ {
u_char *t = (u_char *)label;
if (t) if (t)
t[2] &= ~0x02; t[2] &= ~0x02;
} }
static inline void static inline void bgp_register_for_label(struct bgp_node *rn,
bgp_register_for_label (struct bgp_node *rn, struct bgp_info *ri) struct bgp_info *ri)
{ {
bgp_reg_dereg_for_label(rn, ri, 1); bgp_reg_dereg_for_label(rn, ri, 1);
} }
static inline void static inline void bgp_unregister_for_label(struct bgp_node *rn)
bgp_unregister_for_label (struct bgp_node *rn)
{ {
bgp_reg_dereg_for_label(rn, NULL, 0); bgp_reg_dereg_for_label(rn, NULL, 0);
} }
/* Label stream to value */ /* 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[])
{ {
u_char *t = (u_char *)label;
t[0] = ((l & 0x000FF000) >> 12); t[0] = ((l & 0x000FF000) >> 12);
t[1] = ((l & 0x00000FF0) >> 4); t[1] = ((l & 0x00000FF0) >> 4);
t[2] = ((l & 0x0000000F) << 4); t[2] = ((l & 0x0000000F) << 4);
@ -116,9 +114,9 @@ label_ntop (u_int32_t l, int bos, u_char t[])
} }
/* 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[])
{ {
u_char *t = (u_char *)label;
return (t[2] & 0x01); return (t[2] & 0x01);
}; };

View File

@ -34,16 +34,14 @@
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);
@ -53,8 +51,7 @@ lcommunity_free (struct 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);
} }
@ -64,16 +61,15 @@ 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);
@ -82,8 +78,7 @@ lcommunity_add_val (struct lcommunity *lcom, struct lcommunity_val *lval)
/* 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;
@ -93,7 +88,8 @@ lcommunity_add_val (struct lcommunity *lcom, struct lcommunity_val *lval)
/* 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,
@ -106,8 +102,7 @@ lcommunity_add_val (struct lcommunity *lcom, struct lcommunity_val *lval)
/* 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;
@ -118,17 +113,16 @@ lcommunity_uniq_sort (struct lcommunity *lcom)
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;
@ -150,53 +144,52 @@ lcommunity_parse (u_int8_t *pnt, u_short length)
} }
/* 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 =
lcommunity_lcom2str(lcom, LCOMMUNITY_FORMAT_DISPLAY);
return lcom->str; 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 =
XREALLOC(MTYPE_LCOMMUNITY_VAL, lcom1->val,
(lcom1->size + lcom2->size) * LCOMMUNITY_SIZE); (lcom1->size + lcom2->size) * LCOMMUNITY_SIZE);
else else
lcom1->val = XMALLOC (MTYPE_LCOMMUNITY_VAL, lcom1->val =
XMALLOC(MTYPE_LCOMMUNITY_VAL,
(lcom1->size + lcom2->size) * LCOMMUNITY_SIZE); (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;
@ -210,14 +203,14 @@ lcommunity_intern (struct lcommunity *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;
@ -225,8 +218,7 @@ lcommunity_unintern (struct lcommunity **lcom)
(*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);
@ -236,8 +228,7 @@ lcommunity_unintern (struct lcommunity **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;
@ -245,8 +236,7 @@ lcommunity_hash_make (void *arg)
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];
@ -265,32 +255,29 @@ lcommunity_hash_make (void *arg)
} }
/* 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);
@ -298,22 +285,20 @@ lcommunity_finish (void)
} }
/* 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++;
} }
@ -323,25 +308,19 @@ lcommunity_gettoken (const char *str, struct lcommunity_val *lval,
return NULL; return NULL;
/* Community value. */ /* Community value. */
if (isdigit ((int) *p)) if (isdigit((int)*p)) {
{
int separator = 0; int separator = 0;
int digit = 0; int digit = 0;
u_int32_t globaladmin = 0; u_int32_t globaladmin = 0;
u_int32_t localdata1 = 0; u_int32_t localdata1 = 0;
u_int32_t localdata2 = 0; u_int32_t localdata2 = 0;
while (isdigit ((int) *p) || *p == ':') while (isdigit((int)*p) || *p == ':') {
{ if (*p == ':') {
if (*p == ':') if (separator == 2) {
{
if (separator == 2)
{
*token = lcommunity_token_unknown; *token = lcommunity_token_unknown;
return NULL; return NULL;
} } else {
else
{
separator++; separator++;
digit = 0; digit = 0;
if (separator == 1) { if (separator == 1) {
@ -351,17 +330,14 @@ lcommunity_gettoken (const char *str, struct lcommunity_val *lval,
} }
localdata2 = 0; localdata2 = 0;
} }
} } else {
else
{
digit = 1; digit = 1;
localdata2 *= 10; localdata2 *= 10;
localdata2 += (*p - '0'); localdata2 += (*p - '0');
} }
p++; p++;
} }
if (! digit) if (!digit) {
{
*token = lcommunity_token_unknown; *token = lcommunity_token_unknown;
return NULL; return NULL;
} }
@ -396,17 +372,14 @@ 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: case lcommunity_token_val:
if (lcom == NULL) if (lcom == NULL)
lcom = lcommunity_new(); lcom = lcommunity_new();
@ -422,8 +395,7 @@ lcommunity_str2com (const char *str)
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;
@ -440,8 +412,7 @@ lcommunity_include (struct lcommunity *lcom, u_char *ptr)
/* 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;
@ -453,8 +424,7 @@ lcommunity_lcom2str (struct lcommunity *lcom, int format)
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;
@ -465,13 +435,12 @@ lcommunity_lcom2str (struct lcommunity *lcom, int format)
str_size = LCOMMUNITY_STR_DEFAULT_LEN + 1; str_size = LCOMMUNITY_STR_DEFAULT_LEN + 1;
str_pnt = 0; str_pnt = 0;
for (i = 0; i < lcom->size; i++) for (i = 0; i < lcom->size; i++) {
{
/* Make it sure size is enough. */ /* Make it sure size is enough. */
while (str_pnt + LCOMMUNITY_STR_DEFAULT_LEN >= str_size) while (str_pnt + LCOMMUNITY_STR_DEFAULT_LEN >= str_size) {
{
str_size *= 2; str_size *= 2;
str_buf = XREALLOC (MTYPE_LCOMMUNITY_STR, str_buf, str_size); str_buf = XREALLOC(MTYPE_LCOMMUNITY_STR, str_buf,
str_size);
} }
/* Space between each value. */ /* Space between each value. */
@ -503,8 +472,7 @@ lcommunity_lcom2str (struct lcommunity *lcom, int format)
return str_buf; 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;
@ -520,9 +488,10 @@ lcommunity_match (const struct lcommunity *lcom1,
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)
== 0)
j++; j++;
i++; i++;
} }
@ -534,8 +503,7 @@ lcommunity_match (const struct lcommunity *lcom1,
} }
/* 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;
@ -543,22 +511,24 @@ lcommunity_del_val (struct lcommunity *lcom, u_char *ptr)
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 =
XREALLOC(MTYPE_COMMUNITY_VAL, lcom->val,
lcom_length(lcom)); lcom_length(lcom));
else else {
{
XFREE(MTYPE_COMMUNITY_VAL, lcom->val); XFREE(MTYPE_COMMUNITY_VAL, lcom->val);
lcom->val = NULL; lcom->val = NULL;
} }

View File

@ -30,8 +30,7 @@
#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;
@ -46,8 +45,7 @@ struct lcommunity
}; };
/* 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];
}; };
@ -58,7 +56,8 @@ 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 *,
struct lcommunity *);
extern struct lcommunity *lcommunity_uniq_sort(struct lcommunity *); extern struct lcommunity *lcommunity_uniq_sort(struct lcommunity *);
extern struct lcommunity *lcommunity_intern(struct lcommunity *); extern struct lcommunity *lcommunity_intern(struct lcommunity *);
extern int lcommunity_cmp(const void *, const void *); extern int lcommunity_cmp(const void *, const void *);
@ -67,7 +66,8 @@ extern unsigned int lcommunity_hash_make (void *);
extern struct hash *lcommunity_hash(void); extern struct hash *lcommunity_hash(void);
extern struct lcommunity *lcommunity_str2com(const char *); extern struct lcommunity *lcommunity_str2com(const char *);
extern char *lcommunity_lcom2str(struct lcommunity *, int); extern char *lcommunity_lcom2str(struct lcommunity *, int);
extern int lcommunity_match (const struct lcommunity *, const struct lcommunity *); extern int lcommunity_match(const struct lcommunity *,
const struct lcommunity *);
extern char *lcommunity_str(struct lcommunity *); extern char *lcommunity_str(struct lcommunity *);
extern int lcommunity_include(struct lcommunity *lcom, u_char *ptr); extern int lcommunity_include(struct lcommunity *lcom, u_char *ptr);
extern void lcommunity_del_val(struct lcommunity *lcom, u_char *ptr); extern void lcommunity_del_val(struct lcommunity *lcom, u_char *ptr);

View File

@ -60,16 +60,14 @@
#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);
@ -79,8 +77,7 @@ 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,
@ -103,15 +100,11 @@ static struct quagga_signal_t bgp_signals[] =
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,
@ -127,8 +120,7 @@ struct zebra_privs_t bgpd_privs =
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");
@ -144,13 +136,11 @@ sighup (void)
} }
/* 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);
@ -162,8 +152,7 @@ sigint (void)
} }
/* SIGUSR1 handler. */ /* SIGUSR1 handler. */
void void sigusr1(void)
sigusr1 (void)
{ {
zlog_rotate(); zlog_rotate();
} }
@ -175,8 +164,7 @@ 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;
@ -232,12 +220,6 @@ bgp_exit (int status)
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)
@ -253,8 +235,7 @@ bgp_exit (int status)
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);
@ -262,8 +243,7 @@ bgp_vrf_new (struct vrf *vrf)
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);
@ -271,8 +251,7 @@ bgp_vrf_delete (struct vrf *vrf)
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;
@ -281,8 +260,7 @@ bgp_vrf_enable (struct vrf *vrf)
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);
@ -296,8 +274,7 @@ bgp_vrf_enable (struct vrf *vrf)
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;
@ -309,10 +286,10 @@ bgp_vrf_disable (struct vrf *vrf)
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 "down". */ /* We have instance configured, unlink from VRF and make it
* "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)
@ -324,36 +301,27 @@ bgp_vrf_disable (struct vrf *vrf)
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;
@ -364,7 +332,8 @@ main (int argc, char **argv)
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:l:rne:", longopts,
" -p, --bgp_port Set bgp protocol's port number\n" " -p, --bgp_port Set bgp protocol's port number\n"
" -l, --listenon Listen on specified address (implies -n)\n" " -l, --listenon Listen on specified address (implies -n)\n"
" -r, --retain When program terminates, retain added route by bgpd.\n" " -r, --retain When program terminates, retain added route by bgpd.\n"
@ -373,15 +342,13 @@ main (int argc, char **argv)
" -e, --ecmp Specify ECMP to use.\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':
@ -393,9 +360,11 @@ main (int argc, char **argv)
break; break;
case 'e': case 'e':
multipath_num = atoi(optarg); multipath_num = atoi(optarg);
if (multipath_num > MULTIPATH_NUM || multipath_num <= 0) if (multipath_num > MULTIPATH_NUM
{ || multipath_num <= 0) {
zlog_err ("Multipath Number specified must be less than %d and greater than 0", MULTIPATH_NUM); zlog_err(
"Multipath Number specified must be less than %d and greater than 0",
MULTIPATH_NUM);
return 1; return 1;
} }
break; break;
@ -405,6 +374,7 @@ main (int argc, char **argv)
case 'l': case 'l':
bgp_address = optarg; bgp_address = optarg;
/* listenon implies -n */ /* listenon implies -n */
/* fallthru */
case 'n': case 'n':
no_fib_flag = 1; no_fib_flag = 1;
break; break;
@ -433,8 +403,7 @@ main (int argc, char **argv)
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);

View File

@ -43,7 +43,6 @@ 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")
@ -114,3 +113,7 @@ 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 */

View File

@ -45,15 +45,13 @@
* *
* Record maximum-paths configuration for BGP instance * Record maximum-paths configuration for BGP instance
*/ */
int int bgp_maximum_paths_set(struct bgp *bgp, afi_t afi, safi_t safi, int peertype,
bgp_maximum_paths_set (struct bgp *bgp, afi_t afi, safi_t safi, u_int16_t maxpaths, u_int16_t options)
int peertype, u_int16_t maxpaths, u_int16_t options)
{ {
if (!bgp || (afi >= AFI_MAX) || (safi >= SAFI_MAX)) if (!bgp || (afi >= AFI_MAX) || (safi >= SAFI_MAX))
return -1; return -1;
switch (peertype) switch (peertype) {
{
case BGP_PEER_IBGP: case BGP_PEER_IBGP:
bgp->maxpaths[afi][safi].maxpaths_ibgp = maxpaths; bgp->maxpaths[afi][safi].maxpaths_ibgp = maxpaths;
bgp->maxpaths[afi][safi].ibgp_flags |= options; bgp->maxpaths[afi][safi].ibgp_flags |= options;
@ -73,15 +71,13 @@ bgp_maximum_paths_set (struct bgp *bgp, afi_t afi, safi_t safi,
* *
* Remove maximum-paths configuration from BGP instance * Remove maximum-paths configuration from BGP instance
*/ */
int int bgp_maximum_paths_unset(struct bgp *bgp, afi_t afi, safi_t safi,
bgp_maximum_paths_unset (struct bgp *bgp, afi_t afi, safi_t safi,
int peertype) int peertype)
{ {
if (!bgp || (afi >= AFI_MAX) || (safi >= SAFI_MAX)) if (!bgp || (afi >= AFI_MAX) || (safi >= SAFI_MAX))
return -1; return -1;
switch (peertype) switch (peertype) {
{
case BGP_PEER_IBGP: case BGP_PEER_IBGP:
bgp->maxpaths[afi][safi].maxpaths_ibgp = multipath_num; bgp->maxpaths[afi][safi].maxpaths_ibgp = multipath_num;
bgp->maxpaths[afi][safi].ibgp_flags = 0; bgp->maxpaths[afi][safi].ibgp_flags = 0;
@ -103,53 +99,50 @@ bgp_maximum_paths_unset (struct bgp *bgp, afi_t afi, safi_t safi,
* or greater than zero if bi1 is respectively less than, equal to, * or greater than zero if bi1 is respectively less than, equal to,
* or greater than bi2. * or greater than bi2.
*/ */
int int bgp_info_nexthop_cmp(struct bgp_info *bi1, struct bgp_info *bi2)
bgp_info_nexthop_cmp (struct bgp_info *bi1, struct bgp_info *bi2)
{ {
struct attr_extra *ae1, *ae2;
int compare; int compare;
ae1 = bi1->attr->extra;
ae2 = bi2->attr->extra;
compare = IPV4_ADDR_CMP(&bi1->attr->nexthop, &bi2->attr->nexthop); compare = IPV4_ADDR_CMP(&bi1->attr->nexthop, &bi2->attr->nexthop);
if (!compare && ae1 && ae2) if (!compare) {
{ if (bi1->attr->mp_nexthop_len == bi2->attr->mp_nexthop_len) {
if (ae1->mp_nexthop_len == ae2->mp_nexthop_len) switch (bi1->attr->mp_nexthop_len) {
{
switch (ae1->mp_nexthop_len)
{
case BGP_ATTR_NHLEN_IPV4: case BGP_ATTR_NHLEN_IPV4:
case BGP_ATTR_NHLEN_VPNV4: case BGP_ATTR_NHLEN_VPNV4:
compare = IPV4_ADDR_CMP (&ae1->mp_nexthop_global_in, compare = IPV4_ADDR_CMP(
&ae2->mp_nexthop_global_in); &bi1->attr->mp_nexthop_global_in,
&bi2->attr->mp_nexthop_global_in);
break; break;
case BGP_ATTR_NHLEN_IPV6_GLOBAL: case BGP_ATTR_NHLEN_IPV6_GLOBAL:
case BGP_ATTR_NHLEN_VPNV6_GLOBAL: case BGP_ATTR_NHLEN_VPNV6_GLOBAL:
compare = IPV6_ADDR_CMP (&ae1->mp_nexthop_global, compare = IPV6_ADDR_CMP(
&ae2->mp_nexthop_global); &bi1->attr->mp_nexthop_global,
&bi2->attr->mp_nexthop_global);
break; break;
case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL: case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL:
compare = IPV6_ADDR_CMP (&ae1->mp_nexthop_global, compare = IPV6_ADDR_CMP(
&ae2->mp_nexthop_global); &bi1->attr->mp_nexthop_global,
&bi2->attr->mp_nexthop_global);
if (!compare) if (!compare)
compare = IPV6_ADDR_CMP (&ae1->mp_nexthop_local, compare = IPV6_ADDR_CMP(
&ae2->mp_nexthop_local); &bi1->attr->mp_nexthop_local,
&bi2->attr->mp_nexthop_local);
break; break;
} }
} }
/* This can happen if one IPv6 peer sends you global and link-local /* This can happen if one IPv6 peer sends you global and
* link-local
* nexthops but another IPv6 peer only sends you global * nexthops but another IPv6 peer only sends you global
*/ */
else if (ae1->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL || else if (bi1->attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL
ae1->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) || bi1->attr->mp_nexthop_len
{ == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
compare = IPV6_ADDR_CMP (&ae1->mp_nexthop_global, compare = IPV6_ADDR_CMP(&bi1->attr->mp_nexthop_global,
&ae2->mp_nexthop_global); &bi2->attr->mp_nexthop_global);
if (!compare) if (!compare) {
{ if (bi1->attr->mp_nexthop_len
if (ae1->mp_nexthop_len < ae2->mp_nexthop_len) < bi2->attr->mp_nexthop_len)
compare = -1; compare = -1;
else else
compare = 1; compare = 1;
@ -172,8 +165,7 @@ bgp_info_nexthop_cmp (struct bgp_info *bi1, struct bgp_info *bi2)
* The order of paths is determined first by received nexthop, and then * The order of paths is determined first by received nexthop, and then
* by peer address if the nexthops are the same. * by peer address if the nexthops are the same.
*/ */
static int static int bgp_info_mpath_cmp(void *val1, void *val2)
bgp_info_mpath_cmp (void *val1, void *val2)
{ {
struct bgp_info *bi1, *bi2; struct bgp_info *bi1, *bi2;
int compare; int compare;
@ -183,8 +175,7 @@ bgp_info_mpath_cmp (void *val1, void *val2)
compare = bgp_info_nexthop_cmp(bi1, bi2); compare = bgp_info_nexthop_cmp(bi1, bi2);
if (!compare) if (!compare) {
{
if (!bi1->peer->su_remote && !bi2->peer->su_remote) if (!bi1->peer->su_remote && !bi2->peer->su_remote)
compare = 0; compare = 0;
else if (!bi1->peer->su_remote) else if (!bi1->peer->su_remote)
@ -192,7 +183,8 @@ bgp_info_mpath_cmp (void *val1, void *val2)
else if (!bi2->peer->su_remote) else if (!bi2->peer->su_remote)
compare = -1; compare = -1;
else else
compare = sockunion_cmp (bi1->peer->su_remote, bi2->peer->su_remote); compare = sockunion_cmp(bi1->peer->su_remote,
bi2->peer->su_remote);
} }
return compare; return compare;
@ -204,8 +196,7 @@ bgp_info_mpath_cmp (void *val1, void *val2)
* Initialize the mp_list, which holds the list of multipaths * Initialize the mp_list, which holds the list of multipaths
* selected by bgp_best_selection * selected by bgp_best_selection
*/ */
void void bgp_mp_list_init(struct list *mp_list)
bgp_mp_list_init (struct list *mp_list)
{ {
assert(mp_list); assert(mp_list);
memset(mp_list, 0, sizeof(struct list)); memset(mp_list, 0, sizeof(struct list));
@ -217,8 +208,7 @@ bgp_mp_list_init (struct list *mp_list)
* *
* Clears all entries out of the mp_list * Clears all entries out of the mp_list
*/ */
void void bgp_mp_list_clear(struct list *mp_list)
bgp_mp_list_clear (struct list *mp_list)
{ {
assert(mp_list); assert(mp_list);
list_delete_all_node(mp_list); list_delete_all_node(mp_list);
@ -229,8 +219,7 @@ bgp_mp_list_clear (struct list *mp_list)
* *
* Adds a multipath entry to the mp_list * Adds a multipath entry to the mp_list
*/ */
void void bgp_mp_list_add(struct list *mp_list, struct bgp_info *mpinfo)
bgp_mp_list_add (struct list *mp_list, struct bgp_info *mpinfo)
{ {
assert(mp_list && mpinfo); assert(mp_list && mpinfo);
listnode_add_sort(mp_list, mpinfo); listnode_add_sort(mp_list, mpinfo);
@ -241,11 +230,11 @@ bgp_mp_list_add (struct list *mp_list, struct bgp_info *mpinfo)
* *
* Allocate and zero memory for a new bgp_info_mpath element * Allocate and zero memory for a new bgp_info_mpath element
*/ */
static struct bgp_info_mpath * static struct bgp_info_mpath *bgp_info_mpath_new(void)
bgp_info_mpath_new (void)
{ {
struct bgp_info_mpath *new_mpath; struct bgp_info_mpath *new_mpath;
new_mpath = XCALLOC (MTYPE_BGP_MPATH_INFO, sizeof (struct bgp_info_mpath)); new_mpath =
XCALLOC(MTYPE_BGP_MPATH_INFO, sizeof(struct bgp_info_mpath));
return new_mpath; return new_mpath;
} }
@ -254,11 +243,9 @@ bgp_info_mpath_new (void)
* *
* Release resources for a bgp_info_mpath element and zero out pointer * Release resources for a bgp_info_mpath element and zero out pointer
*/ */
void void bgp_info_mpath_free(struct bgp_info_mpath **mpath)
bgp_info_mpath_free (struct bgp_info_mpath **mpath)
{
if (mpath && *mpath)
{ {
if (mpath && *mpath) {
if ((*mpath)->mp_attr) if ((*mpath)->mp_attr)
bgp_attr_unintern(&(*mpath)->mp_attr); bgp_attr_unintern(&(*mpath)->mp_attr);
XFREE(MTYPE_BGP_MPATH_INFO, *mpath); XFREE(MTYPE_BGP_MPATH_INFO, *mpath);
@ -272,12 +259,10 @@ bgp_info_mpath_free (struct bgp_info_mpath **mpath)
* Fetch the mpath element for the given bgp_info. Used for * Fetch the mpath element for the given bgp_info. Used for
* doing lazy allocation. * doing lazy allocation.
*/ */
static struct bgp_info_mpath * static struct bgp_info_mpath *bgp_info_mpath_get(struct bgp_info *binfo)
bgp_info_mpath_get (struct bgp_info *binfo)
{ {
struct bgp_info_mpath *mpath; struct bgp_info_mpath *mpath;
if (!binfo->mpath) if (!binfo->mpath) {
{
mpath = bgp_info_mpath_new(); mpath = bgp_info_mpath_new();
if (!mpath) if (!mpath)
return NULL; return NULL;
@ -293,8 +278,8 @@ bgp_info_mpath_get (struct bgp_info *binfo)
* Enqueue a path onto the multipath list given the previous multipath * Enqueue a path onto the multipath list given the previous multipath
* list entry * list entry
*/ */
static void static void bgp_info_mpath_enqueue(struct bgp_info *prev_info,
bgp_info_mpath_enqueue (struct bgp_info *prev_info, struct bgp_info *binfo) struct bgp_info *binfo)
{ {
struct bgp_info_mpath *prev, *mpath; struct bgp_info_mpath *prev, *mpath;
@ -317,8 +302,7 @@ bgp_info_mpath_enqueue (struct bgp_info *prev_info, struct bgp_info *binfo)
* *
* Remove a path from the multipath list * Remove a path from the multipath list
*/ */
void void bgp_info_mpath_dequeue(struct bgp_info *binfo)
bgp_info_mpath_dequeue (struct bgp_info *binfo)
{ {
struct bgp_info_mpath *mpath = binfo->mpath; struct bgp_info_mpath *mpath = binfo->mpath;
if (!mpath) if (!mpath)
@ -336,8 +320,7 @@ bgp_info_mpath_dequeue (struct bgp_info *binfo)
* *
* Given a bgp_info, return the next multipath entry * Given a bgp_info, return the next multipath entry
*/ */
struct bgp_info * struct bgp_info *bgp_info_mpath_next(struct bgp_info *binfo)
bgp_info_mpath_next (struct bgp_info *binfo)
{ {
if (!binfo->mpath || !binfo->mpath->mp_next) if (!binfo->mpath || !binfo->mpath->mp_next)
return NULL; return NULL;
@ -349,8 +332,7 @@ bgp_info_mpath_next (struct bgp_info *binfo)
* *
* Given bestpath bgp_info, return the first multipath entry. * Given bestpath bgp_info, return the first multipath entry.
*/ */
struct bgp_info * struct bgp_info *bgp_info_mpath_first(struct bgp_info *binfo)
bgp_info_mpath_first (struct bgp_info *binfo)
{ {
return bgp_info_mpath_next(binfo); return bgp_info_mpath_next(binfo);
} }
@ -360,8 +342,7 @@ bgp_info_mpath_first (struct bgp_info *binfo)
* *
* Given the bestpath bgp_info, return the number of multipath entries * Given the bestpath bgp_info, return the number of multipath entries
*/ */
u_int32_t u_int32_t bgp_info_mpath_count(struct bgp_info *binfo)
bgp_info_mpath_count (struct bgp_info *binfo)
{ {
if (!binfo->mpath) if (!binfo->mpath)
return 0; return 0;
@ -373,8 +354,7 @@ bgp_info_mpath_count (struct bgp_info *binfo)
* *
* Sets the count of multipaths into bestpath's mpath element * Sets the count of multipaths into bestpath's mpath element
*/ */
static void static void bgp_info_mpath_count_set(struct bgp_info *binfo, u_int32_t count)
bgp_info_mpath_count_set (struct bgp_info *binfo, u_int32_t count)
{ {
struct bgp_info_mpath *mpath; struct bgp_info_mpath *mpath;
if (!count && !binfo->mpath) if (!count && !binfo->mpath)
@ -391,8 +371,7 @@ bgp_info_mpath_count_set (struct bgp_info *binfo, u_int32_t count)
* Given bestpath bgp_info, return aggregated attribute set used * Given bestpath bgp_info, return aggregated attribute set used
* for advertising the multipath route * for advertising the multipath route
*/ */
struct attr * struct attr *bgp_info_mpath_attr(struct bgp_info *binfo)
bgp_info_mpath_attr (struct bgp_info *binfo)
{ {
if (!binfo->mpath) if (!binfo->mpath)
return NULL; return NULL;
@ -404,8 +383,7 @@ bgp_info_mpath_attr (struct bgp_info *binfo)
* *
* Sets the aggregated attribute into bestpath's mpath element * Sets the aggregated attribute into bestpath's mpath element
*/ */
static void static void bgp_info_mpath_attr_set(struct bgp_info *binfo, struct attr *attr)
bgp_info_mpath_attr_set (struct bgp_info *binfo, struct attr *attr)
{ {
struct bgp_info_mpath *mpath; struct bgp_info_mpath *mpath;
if (!attr && !binfo->mpath) if (!attr && !binfo->mpath)
@ -422,8 +400,7 @@ bgp_info_mpath_attr_set (struct bgp_info *binfo, struct attr *attr)
* Compare and sync up the multipath list with the mp_list generated by * Compare and sync up the multipath list with the mp_list generated by
* bgp_best_selection * bgp_best_selection
*/ */
void void bgp_info_mpath_update(struct bgp_node *rn, struct bgp_info *new_best,
bgp_info_mpath_update (struct bgp_node *rn, struct bgp_info *new_best,
struct bgp_info *old_best, struct list *mp_list, struct bgp_info *old_best, struct list *mp_list,
struct bgp_maxpaths_cfg *mpath_cfg) struct bgp_maxpaths_cfg *mpath_cfg)
{ {
@ -446,17 +423,16 @@ bgp_info_mpath_update (struct bgp_node *rn, struct bgp_info *new_best,
if (debug) if (debug)
prefix2str(&rn->p, pfx_buf, sizeof(pfx_buf)); prefix2str(&rn->p, pfx_buf, sizeof(pfx_buf));
if (new_best) if (new_best) {
{
mpath_count++; mpath_count++;
if (new_best != old_best) if (new_best != old_best)
bgp_info_mpath_dequeue(new_best); bgp_info_mpath_dequeue(new_best);
maxpaths = (new_best->peer->sort == BGP_PEER_IBGP) ? maxpaths = (new_best->peer->sort == BGP_PEER_IBGP)
mpath_cfg->maxpaths_ibgp : mpath_cfg->maxpaths_ebgp; ? mpath_cfg->maxpaths_ibgp
: mpath_cfg->maxpaths_ebgp;
} }
if (old_best) if (old_best) {
{
cur_mpath = bgp_info_mpath_first(old_best); cur_mpath = bgp_info_mpath_first(old_best);
old_mpath_count = bgp_info_mpath_count(old_best); old_mpath_count = bgp_info_mpath_count(old_best);
bgp_info_mpath_count_set(old_best, 0); bgp_info_mpath_count_set(old_best, 0);
@ -464,7 +440,8 @@ bgp_info_mpath_update (struct bgp_node *rn, struct bgp_info *new_best,
} }
if (debug) if (debug)
zlog_debug("%s: starting mpath update, newbest %s num candidates %d old-mpath-count %d", zlog_debug(
"%s: starting mpath update, newbest %s num candidates %d old-mpath-count %d",
pfx_buf, new_best ? new_best->peer->host : "NONE", pfx_buf, new_best ? new_best->peer->host : "NONE",
listcount(mp_list), old_mpath_count); listcount(mp_list), old_mpath_count);
@ -479,8 +456,7 @@ bgp_info_mpath_update (struct bgp_node *rn, struct bgp_info *new_best,
* Note that new_best might be somewhere in the mp_list, so we need * Note that new_best might be somewhere in the mp_list, so we need
* to skip over it * to skip over it
*/ */
while (mp_node || cur_mpath) while (mp_node || cur_mpath) {
{
struct bgp_info *tmp_info; struct bgp_info *tmp_info;
/* /*
@ -496,41 +472,44 @@ bgp_info_mpath_update (struct bgp_node *rn, struct bgp_info *new_best,
tmp_info = mp_node ? listgetdata(mp_node) : NULL; tmp_info = mp_node ? listgetdata(mp_node) : NULL;
if (debug) if (debug)
zlog_debug("%s: comparing candidate %s with existing mpath %s", zlog_debug(
pfx_buf, tmp_info ? tmp_info->peer->host : "NONE", "%s: comparing candidate %s with existing mpath %s",
pfx_buf,
tmp_info ? tmp_info->peer->host : "NONE",
cur_mpath ? cur_mpath->peer->host : "NONE"); cur_mpath ? cur_mpath->peer->host : "NONE");
/* /*
* If equal, the path was a multipath and is still a multipath. * If equal, the path was a multipath and is still a multipath.
* Insert onto new multipath list if maxpaths allows. * Insert onto new multipath list if maxpaths allows.
*/ */
if (mp_node && (listgetdata (mp_node) == cur_mpath)) if (mp_node && (listgetdata(mp_node) == cur_mpath)) {
{
list_delete_node(mp_list, mp_node); list_delete_node(mp_list, mp_node);
bgp_info_mpath_dequeue(cur_mpath); bgp_info_mpath_dequeue(cur_mpath);
if ((mpath_count < maxpaths) && if ((mpath_count < maxpaths)
bgp_info_nexthop_cmp (prev_mpath, cur_mpath)) && bgp_info_nexthop_cmp(prev_mpath, cur_mpath)) {
{
bgp_info_mpath_enqueue(prev_mpath, cur_mpath); bgp_info_mpath_enqueue(prev_mpath, cur_mpath);
prev_mpath = cur_mpath; prev_mpath = cur_mpath;
mpath_count++; mpath_count++;
if (debug) if (debug) {
{ bgp_info_path_with_addpath_rx_str(
bgp_info_path_with_addpath_rx_str(cur_mpath, path_buf); cur_mpath, path_buf);
zlog_debug("%s: %s is still multipath, cur count %d", zlog_debug(
"%s: %s is still multipath, cur count %d",
pfx_buf, path_buf, mpath_count); pfx_buf, path_buf, mpath_count);
} }
} } else {
else
{
mpath_changed = 1; mpath_changed = 1;
if (debug) if (debug) {
{ bgp_info_path_with_addpath_rx_str(
bgp_info_path_with_addpath_rx_str(cur_mpath, path_buf); cur_mpath, path_buf);
zlog_debug ("%s: remove mpath %s nexthop %s, cur count %d", zlog_debug(
"%s: remove mpath %s nexthop %s, cur count %d",
pfx_buf, path_buf, pfx_buf, path_buf,
inet_ntop (AF_INET, &cur_mpath->attr->nexthop, inet_ntop(AF_INET,
nh_buf[0], sizeof (nh_buf[0])), &cur_mpath->attr
->nexthop,
nh_buf[0],
sizeof(nh_buf[0])),
mpath_count); mpath_count);
} }
} }
@ -539,47 +518,54 @@ bgp_info_mpath_update (struct bgp_node *rn, struct bgp_info *new_best,
continue; continue;
} }
if (cur_mpath && (!mp_node || if (cur_mpath
(bgp_info_mpath_cmp (cur_mpath, && (!mp_node
listgetdata (mp_node)) < 0))) || (bgp_info_mpath_cmp(cur_mpath, listgetdata(mp_node))
{ < 0))) {
/* /*
* If here, we have an old multipath and either the mp_list * If here, we have an old multipath and either the
* mp_list
* is finished or the next mp_node points to a later * is finished or the next mp_node points to a later
* multipath, so we need to purge this path from the * multipath, so we need to purge this path from the
* multipath list * multipath list
*/ */
bgp_info_mpath_dequeue(cur_mpath); bgp_info_mpath_dequeue(cur_mpath);
mpath_changed = 1; mpath_changed = 1;
if (debug) if (debug) {
{ bgp_info_path_with_addpath_rx_str(cur_mpath,
bgp_info_path_with_addpath_rx_str(cur_mpath, path_buf); path_buf);
zlog_debug ("%s: remove mpath %s nexthop %s, cur count %d", zlog_debug(
"%s: remove mpath %s nexthop %s, cur count %d",
pfx_buf, path_buf, pfx_buf, path_buf,
inet_ntop (AF_INET, &cur_mpath->attr->nexthop, inet_ntop(AF_INET,
&cur_mpath->attr->nexthop,
nh_buf[0], sizeof(nh_buf[0])), nh_buf[0], sizeof(nh_buf[0])),
mpath_count); mpath_count);
} }
cur_mpath = next_mpath; cur_mpath = next_mpath;
} } else {
else
{
/* /*
* If here, we have a path on the mp_list that was not previously * If here, we have a path on the mp_list that was not
* a multipath (due to non-equivalance or maxpaths exceeded), * previously
* or the matching multipath is sorted later in the multipath * a multipath (due to non-equivalance or maxpaths
* list. Before we enqueue the path on the new multipath list, * exceeded),
* make sure its not on the old_best multipath list or referenced * or the matching multipath is sorted later in the
* multipath
* list. Before we enqueue the path on the new multipath
* list,
* make sure its not on the old_best multipath list or
* referenced
* via next_mpath: * via next_mpath:
* - If next_mpath points to this new path, update next_mpath to * - If next_mpath points to this new path, update
* next_mpath to
* point to the multipath after this one * point to the multipath after this one
* - Dequeue the path from the multipath list just to make sure * - Dequeue the path from the multipath list just to
* make sure
*/ */
new_mpath = listgetdata(mp_node); new_mpath = listgetdata(mp_node);
list_delete_node(mp_list, mp_node); list_delete_node(mp_list, mp_node);
if ((mpath_count < maxpaths) && (new_mpath != new_best) && if ((mpath_count < maxpaths) && (new_mpath != new_best)
bgp_info_nexthop_cmp (prev_mpath, new_mpath)) && bgp_info_nexthop_cmp(prev_mpath, new_mpath)) {
{
if (new_mpath == next_mpath) if (new_mpath == next_mpath)
bgp_info_mpath_next(new_mpath); bgp_info_mpath_next(new_mpath);
bgp_info_mpath_dequeue(new_mpath); bgp_info_mpath_dequeue(new_mpath);
@ -588,13 +574,17 @@ bgp_info_mpath_update (struct bgp_node *rn, struct bgp_info *new_best,
prev_mpath = new_mpath; prev_mpath = new_mpath;
mpath_changed = 1; mpath_changed = 1;
mpath_count++; mpath_count++;
if (debug) if (debug) {
{ bgp_info_path_with_addpath_rx_str(
bgp_info_path_with_addpath_rx_str(new_mpath, path_buf); new_mpath, path_buf);
zlog_debug ("%s: add mpath %s nexthop %s, cur count %d", zlog_debug(
"%s: add mpath %s nexthop %s, cur count %d",
pfx_buf, path_buf, pfx_buf, path_buf,
inet_ntop (AF_INET, &new_mpath->attr->nexthop, inet_ntop(AF_INET,
nh_buf[0], sizeof (nh_buf[0])), &new_mpath->attr
->nexthop,
nh_buf[0],
sizeof(nh_buf[0])),
mpath_count); mpath_count);
} }
} }
@ -602,14 +592,16 @@ bgp_info_mpath_update (struct bgp_node *rn, struct bgp_info *new_best,
} }
} }
if (new_best) if (new_best) {
{
if (debug) if (debug)
zlog_debug("%s: New mpath count (incl newbest) %d mpath-change %s", zlog_debug(
pfx_buf, mpath_count, mpath_changed ? "YES" : "NO"); "%s: New mpath count (incl newbest) %d mpath-change %s",
pfx_buf, mpath_count,
mpath_changed ? "YES" : "NO");
bgp_info_mpath_count_set(new_best, mpath_count - 1); bgp_info_mpath_count_set(new_best, mpath_count - 1);
if (mpath_changed || (bgp_info_mpath_count (new_best) != old_mpath_count)) if (mpath_changed
|| (bgp_info_mpath_count(new_best) != old_mpath_count))
SET_FLAG(new_best->flags, BGP_INFO_MULTIPATH_CHG); SET_FLAG(new_best->flags, BGP_INFO_MULTIPATH_CHG);
} }
} }
@ -620,16 +612,15 @@ bgp_info_mpath_update (struct bgp_node *rn, struct bgp_info *new_best,
* Clean up multipath information for BGP_INFO_DMED_SELECTED path that * Clean up multipath information for BGP_INFO_DMED_SELECTED path that
* is not selected as best path * is not selected as best path
*/ */
void void bgp_mp_dmed_deselect(struct bgp_info *dmed_best)
bgp_mp_dmed_deselect (struct bgp_info *dmed_best)
{ {
struct bgp_info *mpinfo, *mpnext; struct bgp_info *mpinfo, *mpnext;
if (!dmed_best) if (!dmed_best)
return; return;
for (mpinfo = bgp_info_mpath_first (dmed_best); mpinfo; mpinfo = mpnext) for (mpinfo = bgp_info_mpath_first(dmed_best); mpinfo;
{ mpinfo = mpnext) {
mpnext = bgp_info_mpath_next(mpinfo); mpnext = bgp_info_mpath_next(mpinfo);
bgp_info_mpath_dequeue(mpinfo); bgp_info_mpath_dequeue(mpinfo);
} }
@ -651,8 +642,7 @@ bgp_mp_dmed_deselect (struct bgp_info *dmed_best)
* is no change in multipath selection and no attribute change in * is no change in multipath selection and no attribute change in
* any multipath. * any multipath.
*/ */
void void bgp_info_mpath_aggregate_update(struct bgp_info *new_best,
bgp_info_mpath_aggregate_update (struct bgp_info *new_best,
struct bgp_info *old_best) struct bgp_info *old_best)
{ {
struct bgp_info *mpinfo; struct bgp_info *mpinfo;
@ -663,12 +653,10 @@ bgp_info_mpath_aggregate_update (struct bgp_info *new_best,
struct community *community, *commerge; struct community *community, *commerge;
struct ecommunity *ecomm, *ecommerge; struct ecommunity *ecomm, *ecommerge;
struct lcommunity *lcomm, *lcommerge; struct lcommunity *lcomm, *lcommerge;
struct attr_extra *ae;
struct attr attr = {0}; struct attr attr = {0};
if (old_best && (old_best != new_best) && if (old_best && (old_best != new_best)
(old_attr = bgp_info_mpath_attr (old_best))) && (old_attr = bgp_info_mpath_attr(old_best))) {
{
bgp_attr_unintern(&old_attr); bgp_attr_unintern(&old_attr);
bgp_info_mpath_attr_set(old_best, NULL); bgp_info_mpath_attr_set(old_best, NULL);
} }
@ -676,10 +664,8 @@ bgp_info_mpath_aggregate_update (struct bgp_info *new_best,
if (!new_best) if (!new_best)
return; return;
if (!bgp_info_mpath_count (new_best)) if (!bgp_info_mpath_count(new_best)) {
{ if ((new_attr = bgp_info_mpath_attr(new_best))) {
if ((new_attr = bgp_info_mpath_attr (new_best)))
{
bgp_attr_unintern(&new_attr); bgp_attr_unintern(&new_attr);
bgp_info_mpath_attr_set(new_best, NULL); bgp_info_mpath_attr_set(new_best, NULL);
SET_FLAG(new_best->flags, BGP_INFO_ATTR_CHANGED); SET_FLAG(new_best->flags, BGP_INFO_ATTR_CHANGED);
@ -689,97 +675,91 @@ bgp_info_mpath_aggregate_update (struct bgp_info *new_best,
bgp_attr_dup(&attr, new_best->attr); bgp_attr_dup(&attr, new_best->attr);
if (new_best->peer && if (new_best->peer && bgp_flag_check(new_best->peer->bgp,
bgp_flag_check (new_best->peer->bgp, BGP_FLAG_MULTIPATH_RELAX_AS_SET)) BGP_FLAG_MULTIPATH_RELAX_AS_SET)) {
{
/* aggregate attribute from multipath constituents */ /* aggregate attribute from multipath constituents */
aspath = aspath_dup(attr.aspath); aspath = aspath_dup(attr.aspath);
origin = attr.origin; origin = attr.origin;
community = attr.community ? community_dup (attr.community) : NULL; community =
ae = attr.extra; attr.community ? community_dup(attr.community) : NULL;
ecomm = (ae && ae->ecommunity) ? ecommunity_dup (ae->ecommunity) : NULL; ecomm = (attr.ecommunity) ? ecommunity_dup(attr.ecommunity)
lcomm = (ae && ae->lcommunity) ? lcommunity_dup (ae->lcommunity) : NULL; : NULL;
lcomm = (attr.lcommunity) ? lcommunity_dup(attr.lcommunity)
: NULL;
for (mpinfo = bgp_info_mpath_first(new_best); mpinfo; for (mpinfo = bgp_info_mpath_first(new_best); mpinfo;
mpinfo = bgp_info_mpath_next (mpinfo)) mpinfo = bgp_info_mpath_next(mpinfo)) {
{ asmerge =
asmerge = aspath_aggregate (aspath, mpinfo->attr->aspath); aspath_aggregate(aspath, mpinfo->attr->aspath);
aspath_free(aspath); aspath_free(aspath);
aspath = asmerge; aspath = asmerge;
if (origin < mpinfo->attr->origin) if (origin < mpinfo->attr->origin)
origin = mpinfo->attr->origin; origin = mpinfo->attr->origin;
if (mpinfo->attr->community) if (mpinfo->attr->community) {
{ if (community) {
if (community) commerge = community_merge(
{ community,
commerge = community_merge (community, mpinfo->attr->community); mpinfo->attr->community);
community = community_uniq_sort (commerge); community =
community_uniq_sort(commerge);
community_free(commerge); community_free(commerge);
} } else
else community = community_dup(
community = community_dup (mpinfo->attr->community); mpinfo->attr->community);
} }
ae = mpinfo->attr->extra; if (mpinfo->attr->ecommunity) {
if (ae && ae->ecommunity) if (ecomm) {
{ ecommerge = ecommunity_merge(
if (ecomm) ecomm,
{ mpinfo->attr->ecommunity);
ecommerge = ecommunity_merge (ecomm, ae->ecommunity);
ecomm = ecommunity_uniq_sort(ecommerge); ecomm = ecommunity_uniq_sort(ecommerge);
ecommunity_free(&ecommerge); ecommunity_free(&ecommerge);
} else
ecomm = ecommunity_dup(
mpinfo->attr->ecommunity);
} }
else if (mpinfo->attr->lcommunity) {
ecomm = ecommunity_dup (ae->ecommunity); if (lcomm) {
} lcommerge = lcommunity_merge(
if (ae && ae->lcommunity) lcomm,
{ mpinfo->attr->lcommunity);
if (lcomm)
{
lcommerge = lcommunity_merge (lcomm, ae->lcommunity);
lcomm = lcommunity_uniq_sort(lcommerge); lcomm = lcommunity_uniq_sort(lcommerge);
lcommunity_free(&lcommerge); lcommunity_free(&lcommerge);
} } else
else lcomm = lcommunity_dup(
lcomm = lcommunity_dup (ae->lcommunity); mpinfo->attr->lcommunity);
} }
} }
attr.aspath = aspath; attr.aspath = aspath;
attr.origin = origin; attr.origin = origin;
if (community) if (community) {
{
attr.community = community; attr.community = community;
attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES); attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES);
} }
if (ecomm) if (ecomm) {
{ attr.ecommunity = ecomm;
ae = bgp_attr_extra_get (&attr);
ae->ecommunity = ecomm;
attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES); attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES);
} }
/* Zap multipath attr nexthop so we set nexthop to self */ /* Zap multipath attr nexthop so we set nexthop to self */
attr.nexthop.s_addr = 0; attr.nexthop.s_addr = 0;
if (attr.extra) memset(&attr.mp_nexthop_global, 0, sizeof(struct in6_addr));
memset (&attr.extra->mp_nexthop_global, 0, sizeof (struct in6_addr));
/* TODO: should we set ATOMIC_AGGREGATE and AGGREGATOR? */ /* TODO: should we set ATOMIC_AGGREGATE and AGGREGATOR? */
} }
new_attr = bgp_attr_intern(&attr); new_attr = bgp_attr_intern(&attr);
bgp_attr_extra_free (&attr);
if (new_attr != bgp_info_mpath_attr (new_best)) if (new_attr != bgp_info_mpath_attr(new_best)) {
{
if ((old_attr = bgp_info_mpath_attr(new_best))) if ((old_attr = bgp_info_mpath_attr(new_best)))
bgp_attr_unintern(&old_attr); bgp_attr_unintern(&old_attr);
bgp_info_mpath_attr_set(new_best, new_attr); bgp_info_mpath_attr_set(new_best, new_attr);
SET_FLAG(new_best->flags, BGP_INFO_ATTR_CHANGED); SET_FLAG(new_best->flags, BGP_INFO_ATTR_CHANGED);
} } else
else
bgp_attr_unintern(&new_attr); bgp_attr_unintern(&new_attr);
} }

View File

@ -25,8 +25,7 @@
/* 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;

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,15 +22,7 @@
#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
@ -56,66 +48,31 @@ typedef enum {
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" " Network Next Hop EthTag Overlay Index RouterMac\n"
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 *);
extern void encode_rd_type (u_int16_t, u_char *);
extern void bgp_mplsvpn_init(void); extern void bgp_mplsvpn_init(void);
extern int bgp_nlri_parse_vpn(struct peer *, struct attr *, struct bgp_nlri *); extern int bgp_nlri_parse_vpn(struct peer *, struct attr *, struct bgp_nlri *);
extern u_int32_t decode_label (u_char *); extern u_int32_t decode_label(mpls_label_t *);
extern void encode_label(u_int32_t, u_char *); extern void encode_label(mpls_label_t, mpls_label_t *);
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 extern int argv_find_and_parse_vpnvx(struct cmd_token **argv, int argc,
argv_find_and_parse_vpnvx(struct cmd_token **argv, int argc, int *index, afi_t *afi); int *index, afi_t *afi);
extern int bgp_show_mpls_vpn(struct vty *vty, afi_t afi, struct prefix_rd *prd, 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); enum bgp_show_type type, void *output_arg,
int tags, u_char use_json);
#endif /* _QUAGGA_BGP_MPLSVPN_H */ #endif /* _QUAGGA_BGP_MPLSVPN_H */

View File

@ -47,8 +47,7 @@ extern struct zebra_privs_t bgpd_privs;
static int bgp_bind(struct peer *); static int bgp_bind(struct peer *);
/* BGP listening socket. */ /* BGP listening socket. */
struct bgp_listener struct bgp_listener {
{
int fd; int fd;
union sockunion su; union sockunion su;
struct thread *thread; struct thread *thread;
@ -58,8 +57,8 @@ struct bgp_listener
* Set MD5 key for the socket, for the given IPv4 peer address. * Set MD5 key for the socket, for the given IPv4 peer address.
* If the password is NULL or zero-length, the option will be disabled. * If the password is NULL or zero-length, the option will be disabled.
*/ */
static int static int bgp_md5_set_socket(int socket, union sockunion *su,
bgp_md5_set_socket (int socket, union sockunion *su, const char *password) const char *password)
{ {
int ret = -1; int ret = -1;
int en = ENOSYS; int en = ENOSYS;
@ -81,20 +80,20 @@ bgp_md5_set_socket (int socket, union sockunion *su, const char *password)
#endif /* HAVE_TCP_MD5SIG */ #endif /* HAVE_TCP_MD5SIG */
if (ret < 0) if (ret < 0)
zlog_warn ("can't set TCP_MD5SIG option on socket %d: %s", socket, safe_strerror (en)); zlog_warn("can't set TCP_MD5SIG option on socket %d: %s",
socket, safe_strerror(en));
return ret; return ret;
} }
/* Helper for bgp_connect */ /* Helper for bgp_connect */
static int static int bgp_md5_set_connect(int socket, union sockunion *su,
bgp_md5_set_connect (int socket, union sockunion *su, const char *password) const char *password)
{ {
int ret = -1; int ret = -1;
#if HAVE_DECL_TCP_MD5SIG #if HAVE_DECL_TCP_MD5SIG
if ( bgpd_privs.change (ZPRIVS_RAISE) ) if (bgpd_privs.change(ZPRIVS_RAISE)) {
{
zlog_err("%s: could not raise privs", __func__); zlog_err("%s: could not raise privs", __func__);
return ret; return ret;
} }
@ -108,26 +107,25 @@ bgp_md5_set_connect (int socket, union sockunion *su, const char *password)
return ret; return ret;
} }
static int static int bgp_md5_set_password(struct peer *peer, const char *password)
bgp_md5_set_password (struct peer *peer, const char *password)
{ {
struct listnode *node; struct listnode *node;
int ret = 0; int ret = 0;
struct bgp_listener *listener; struct bgp_listener *listener;
if ( bgpd_privs.change (ZPRIVS_RAISE) ) if (bgpd_privs.change(ZPRIVS_RAISE)) {
{
zlog_err("%s: could not raise privs", __func__); zlog_err("%s: could not raise privs", __func__);
return -1; return -1;
} }
/* Set or unset the password on the listen socket(s). Outbound connections /* Set or unset the password on the listen socket(s). Outbound
* connections
* are taken care of in bgp_connect() below. * are taken care of in bgp_connect() below.
*/ */
for (ALL_LIST_ELEMENTS_RO(bm->listen_sockets, node, listener)) for (ALL_LIST_ELEMENTS_RO(bm->listen_sockets, node, listener))
if (listener->su.sa.sa_family == peer->su.sa.sa_family) if (listener->su.sa.sa_family == peer->su.sa.sa_family) {
{ ret = bgp_md5_set_socket(listener->fd, &peer->su,
ret = bgp_md5_set_socket (listener->fd, &peer->su, password); password);
break; break;
} }
@ -137,60 +135,55 @@ bgp_md5_set_password (struct peer *peer, const char *password)
return ret; return ret;
} }
int int bgp_md5_set(struct peer *peer)
bgp_md5_set (struct peer *peer)
{ {
/* Set the password from listen socket. */ /* Set the password from listen socket. */
return bgp_md5_set_password(peer, peer->password); return bgp_md5_set_password(peer, peer->password);
} }
int int bgp_md5_unset(struct peer *peer)
bgp_md5_unset (struct peer *peer)
{ {
/* Unset the password from listen socket. */ /* Unset the password from listen socket. */
return bgp_md5_set_password(peer, NULL); return bgp_md5_set_password(peer, NULL);
} }
int int bgp_set_socket_ttl(struct peer *peer, int bgp_sock)
bgp_set_socket_ttl (struct peer *peer, int bgp_sock)
{ {
char buf[INET_ADDRSTRLEN]; char buf[INET_ADDRSTRLEN];
int ret = 0; int ret = 0;
/* In case of peer is EBGP, we should set TTL for this connection. */ /* In case of peer is EBGP, we should set TTL for this connection. */
if (!peer->gtsm_hops && (peer_sort (peer) == BGP_PEER_EBGP)) if (!peer->gtsm_hops && (peer_sort(peer) == BGP_PEER_EBGP)) {
{
ret = sockopt_ttl(peer->su.sa.sa_family, bgp_sock, peer->ttl); ret = sockopt_ttl(peer->su.sa.sa_family, bgp_sock, peer->ttl);
if (ret) if (ret) {
{ zlog_err(
zlog_err ("%s: Can't set TxTTL on peer (rtrid %s) socket, err = %d", "%s: Can't set TxTTL on peer (rtrid %s) socket, err = %d",
__func__, __func__, inet_ntop(AF_INET, &peer->remote_id,
inet_ntop (AF_INET, &peer->remote_id, buf, sizeof(buf)), buf, sizeof(buf)),
errno); errno);
return ret; return ret;
} }
} } else if (peer->gtsm_hops) {
else if (peer->gtsm_hops) /* On Linux, setting minttl without setting ttl seems to mess
{ with the
/* On Linux, setting minttl without setting ttl seems to mess with the
outgoing ttl. Therefore setting both. outgoing ttl. Therefore setting both.
*/ */
ret = sockopt_ttl(peer->su.sa.sa_family, bgp_sock, MAXTTL); ret = sockopt_ttl(peer->su.sa.sa_family, bgp_sock, MAXTTL);
if (ret) if (ret) {
{ zlog_err(
zlog_err ("%s: Can't set TxTTL on peer (rtrid %s) socket, err = %d", "%s: Can't set TxTTL on peer (rtrid %s) socket, err = %d",
__func__, __func__, inet_ntop(AF_INET, &peer->remote_id,
inet_ntop (AF_INET, &peer->remote_id, buf, sizeof(buf)), buf, sizeof(buf)),
errno); errno);
return ret; return ret;
} }
ret = sockopt_minttl(peer->su.sa.sa_family, bgp_sock, ret = sockopt_minttl(peer->su.sa.sa_family, bgp_sock,
MAXTTL + 1 - peer->gtsm_hops); MAXTTL + 1 - peer->gtsm_hops);
if (ret) if (ret) {
{ zlog_err(
zlog_err ("%s: Can't set MinTTL on peer (rtrid %s) socket, err = %d", "%s: Can't set MinTTL on peer (rtrid %s) socket, err = %d",
__func__, __func__, inet_ntop(AF_INET, &peer->remote_id,
inet_ntop (AF_INET, &peer->remote_id, buf, sizeof(buf)), buf, sizeof(buf)),
errno); errno);
return ret; return ret;
} }
@ -206,13 +199,13 @@ bgp_set_socket_ttl (struct peer *peer, int bgp_sock)
* which the incoming connection is bound to. This could either be a VRF * which the incoming connection is bound to. This could either be a VRF
* or it could be an interface, which in turn determines the VRF. * or it could be an interface, which in turn determines the VRF.
*/ */
static int static int bgp_get_instance_for_inc_conn(int sock, struct bgp **bgp_inst)
bgp_get_instance_for_inc_conn (int sock, struct bgp **bgp_inst)
{ {
#ifndef SO_BINDTODEVICE #ifndef SO_BINDTODEVICE
/* only Linux has SO_BINDTODEVICE, but we're in Linux-specific code here /* only Linux has SO_BINDTODEVICE, but we're in Linux-specific code here
* anyway since the assumption is that the interface name returned by * anyway since the assumption is that the interface name returned by
* getsockopt() is useful in identifying the VRF, particularly with Linux's * getsockopt() is useful in identifying the VRF, particularly with
* Linux's
* VRF l3master device. The whole mechanism is specific to Linux, so... * VRF l3master device. The whole mechanism is specific to Linux, so...
* when other platforms add VRF support, this will need handling here as * when other platforms add VRF support, this will need handling here as
* well. (or, some restructuring) */ * well. (or, some restructuring) */
@ -229,8 +222,7 @@ bgp_get_instance_for_inc_conn (int sock, struct bgp **bgp_inst)
*bgp_inst = NULL; *bgp_inst = NULL;
name[0] = '\0'; name[0] = '\0';
rc = getsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, name, &name_len); rc = getsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, name, &name_len);
if (rc != 0) if (rc != 0) {
{
#if defined(HAVE_CUMULUS) #if defined(HAVE_CUMULUS)
zlog_err("[Error] BGP SO_BINDTODEVICE get failed (%s), sock %d", zlog_err("[Error] BGP SO_BINDTODEVICE get failed (%s), sock %d",
safe_strerror(errno), sock); safe_strerror(errno), sock);
@ -238,16 +230,14 @@ bgp_get_instance_for_inc_conn (int sock, struct bgp **bgp_inst)
#endif #endif
} }
if (!strlen(name)) if (!strlen(name)) {
{
*bgp_inst = bgp_get_default(); *bgp_inst = bgp_get_default();
return 0; /* default instance. */ return 0; /* default instance. */
} }
/* First try match to instance; if that fails, check for interfaces. */ /* First try match to instance; if that fails, check for interfaces. */
bgp = bgp_lookup_by_name(name); bgp = bgp_lookup_by_name(name);
if (bgp) if (bgp) {
{
if (!bgp->vrf_id) // unexpected if (!bgp->vrf_id) // unexpected
return -1; return -1;
*bgp_inst = bgp; *bgp_inst = bgp;
@ -255,16 +245,14 @@ bgp_get_instance_for_inc_conn (int sock, struct bgp **bgp_inst)
} }
/* TODO - This will be optimized once interfaces move into the NS */ /* TODO - This will be optimized once interfaces move into the NS */
for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp)) for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
{
struct interface *ifp; struct interface *ifp;
if (bgp->inst_type == BGP_INSTANCE_TYPE_VIEW) if (bgp->inst_type == BGP_INSTANCE_TYPE_VIEW)
continue; continue;
ifp = if_lookup_by_name(name, bgp->vrf_id); ifp = if_lookup_by_name(name, bgp->vrf_id);
if (ifp) if (ifp) {
{
*bgp_inst = bgp; *bgp_inst = bgp;
return 0; return 0;
} }
@ -276,8 +264,7 @@ bgp_get_instance_for_inc_conn (int sock, struct bgp **bgp_inst)
} }
/* Accept bgp connection. */ /* Accept bgp connection. */
static int static int bgp_accept(struct thread *thread)
bgp_accept (struct thread *thread)
{ {
int bgp_sock; int bgp_sock;
int accept_sock; int accept_sock;
@ -292,8 +279,7 @@ bgp_accept (struct thread *thread)
/* Register accept thread. */ /* Register accept thread. */
accept_sock = THREAD_FD(thread); accept_sock = THREAD_FD(thread);
if (accept_sock < 0) if (accept_sock < 0) {
{
zlog_err("accept_sock is nevative value %d", accept_sock); zlog_err("accept_sock is nevative value %d", accept_sock);
return -1; return -1;
} }
@ -303,18 +289,18 @@ bgp_accept (struct thread *thread)
/* Accept client connection. */ /* Accept client connection. */
bgp_sock = sockunion_accept(accept_sock, &su); bgp_sock = sockunion_accept(accept_sock, &su);
if (bgp_sock < 0) if (bgp_sock < 0) {
{ zlog_err("[Error] BGP socket accept failed (%s)",
zlog_err ("[Error] BGP socket accept failed (%s)", safe_strerror (errno)); safe_strerror(errno));
return -1; return -1;
} }
set_nonblocking(bgp_sock); set_nonblocking(bgp_sock);
/* Obtain BGP instance this connection is meant for. */ /* Obtain BGP instance this connection is meant for. */
if (bgp_get_instance_for_inc_conn (bgp_sock, &bgp)) if (bgp_get_instance_for_inc_conn(bgp_sock, &bgp)) {
{
if (bgp_debug_neighbor_events(NULL)) if (bgp_debug_neighbor_events(NULL))
zlog_debug ("[Event] Could not get instance for incoming conn from %s", zlog_debug(
"[Event] Could not get instance for incoming conn from %s",
inet_sutop(&su, buf)); inet_sutop(&su, buf));
close(bgp_sock); close(bgp_sock);
return -1; return -1;
@ -326,15 +312,14 @@ bgp_accept (struct thread *thread)
/* Check remote IP address */ /* Check remote IP address */
peer1 = peer_lookup(bgp, &su); peer1 = peer_lookup(bgp, &su);
if (! peer1) if (!peer1) {
{
peer1 = peer_lookup_dynamic_neighbor(bgp, &su); peer1 = peer_lookup_dynamic_neighbor(bgp, &su);
if (peer1) if (peer1) {
{
/* Dynamic neighbor has been created, let it proceed */ /* Dynamic neighbor has been created, let it proceed */
peer1->fd = bgp_sock; peer1->fd = bgp_sock;
bgp_fsm_change_status(peer1, Active); bgp_fsm_change_status(peer1, Active);
BGP_TIMER_OFF(peer1->t_start); /* created in peer_create() */ BGP_TIMER_OFF(
peer1->t_start); /* created in peer_create() */
if (peer_active(peer1)) if (peer_active(peer1))
BGP_EVENT_ADD(peer1, TCP_connection_open); BGP_EVENT_ADD(peer1, TCP_connection_open);
@ -343,11 +328,10 @@ bgp_accept (struct thread *thread)
} }
} }
if (! peer1) if (!peer1) {
{ if (bgp_debug_neighbor_events(NULL)) {
if (bgp_debug_neighbor_events(NULL)) zlog_debug(
{ "[Event] %s connection rejected - not configured"
zlog_debug ("[Event] %s connection rejected - not configured"
" and not valid for dynamic", " and not valid for dynamic",
inet_sutop(&su, buf)); inet_sutop(&su, buf));
} }
@ -355,10 +339,10 @@ bgp_accept (struct thread *thread)
return -1; return -1;
} }
if (CHECK_FLAG(peer1->flags, PEER_FLAG_SHUTDOWN)) if (CHECK_FLAG(peer1->flags, PEER_FLAG_SHUTDOWN)) {
{
if (bgp_debug_neighbor_events(peer1)) if (bgp_debug_neighbor_events(peer1))
zlog_debug ("[Event] connection from %s rejected due to admin shutdown", zlog_debug(
"[Event] connection from %s rejected due to admin shutdown",
inet_sutop(&su, buf)); inet_sutop(&su, buf));
close(bgp_sock); close(bgp_sock);
return -1; return -1;
@ -370,20 +354,20 @@ bgp_accept (struct thread *thread)
* Established and then the Clearing_Completed event is generated. Also, * Established and then the Clearing_Completed event is generated. Also,
* block incoming connection in Deleted state. * block incoming connection in Deleted state.
*/ */
if (peer1->status == Clearing || peer1->status == Deleted) if (peer1->status == Clearing || peer1->status == Deleted) {
{
if (bgp_debug_neighbor_events(peer1)) if (bgp_debug_neighbor_events(peer1))
zlog_debug("[Event] Closing incoming conn for %s (%p) state %d", zlog_debug(
"[Event] Closing incoming conn for %s (%p) state %d",
peer1->host, peer1, peer1->status); peer1->host, peer1, peer1->status);
close(bgp_sock); close(bgp_sock);
return -1; return -1;
} }
/* Check that at least one AF is activated for the peer. */ /* Check that at least one AF is activated for the peer. */
if (!peer_active (peer1)) if (!peer_active(peer1)) {
{
if (bgp_debug_neighbor_events(peer1)) if (bgp_debug_neighbor_events(peer1))
zlog_debug ("%s - incoming conn rejected - no AF activated for peer", zlog_debug(
"%s - incoming conn rejected - no AF activated for peer",
peer1->host); peer1->host);
close(bgp_sock); close(bgp_sock);
return -1; return -1;
@ -393,20 +377,22 @@ bgp_accept (struct thread *thread)
zlog_debug("[Event] BGP connection from host %s fd %d", zlog_debug("[Event] BGP connection from host %s fd %d",
inet_sutop(&su, buf), bgp_sock); inet_sutop(&su, buf), bgp_sock);
if (peer1->doppelganger) if (peer1->doppelganger) {
{
/* We have an existing connection. Kill the existing one and run /* We have an existing connection. Kill the existing one and run
with this one. with this one.
*/ */
if (bgp_debug_neighbor_events(peer1)) if (bgp_debug_neighbor_events(peer1))
zlog_debug ("[Event] New active connection from peer %s, Killing" zlog_debug(
" previous active connection", peer1->host); "[Event] New active connection from peer %s, Killing"
" previous active connection",
peer1->host);
peer_delete(peer1->doppelganger); peer_delete(peer1->doppelganger);
} }
if (bgp_set_socket_ttl(peer1, bgp_sock) < 0) if (bgp_set_socket_ttl(peer1, bgp_sock) < 0)
if (bgp_debug_neighbor_events(peer1)) if (bgp_debug_neighbor_events(peer1))
zlog_debug ("[Event] Unable to set min/max TTL on peer %s, Continuing", zlog_debug(
"[Event] Unable to set min/max TTL on peer %s, Continuing",
peer1->host); peer1->host);
peer = peer_create(&su, peer1->conf_if, peer1->bgp, peer1->local_as, peer = peer_create(&su, peer1->conf_if, peer1->bgp, peer1->local_as,
@ -428,11 +414,12 @@ bgp_accept (struct thread *thread)
SET_FLAG(peer->sflags, PEER_STATUS_ACCEPT_PEER); SET_FLAG(peer->sflags, PEER_STATUS_ACCEPT_PEER);
/* Make dummy peer until read Open packet. */ /* Make dummy peer until read Open packet. */
if (peer1->status == Established && if (peer1->status == Established
CHECK_FLAG (peer1->sflags, PEER_STATUS_NSF_MODE)) && CHECK_FLAG(peer1->sflags, PEER_STATUS_NSF_MODE)) {
{ /* If we have an existing established connection with graceful
/* If we have an existing established connection with graceful restart * restart
* capability announced with one or more address families, then drop * capability announced with one or more address families, then
* drop
* existing established connection and move state to connect. * existing established connection and move state to connect.
*/ */
peer1->last_reset = PEER_DOWN_NSF_CLOSE_SESSION; peer1->last_reset = PEER_DOWN_NSF_CLOSE_SESSION;
@ -440,8 +427,7 @@ bgp_accept (struct thread *thread)
bgp_event_update(peer1, TCP_connection_closed); bgp_event_update(peer1, TCP_connection_closed);
} }
if (peer_active (peer)) if (peer_active(peer)) {
{
BGP_EVENT_ADD(peer, TCP_connection_open); BGP_EVENT_ADD(peer, TCP_connection_open);
} }
@ -449,8 +435,7 @@ bgp_accept (struct thread *thread)
} }
/* BGP socket bind. */ /* BGP socket bind. */
static int static int bgp_bind(struct peer *peer)
bgp_bind (struct peer *peer)
{ {
#ifdef SO_BINDTODEVICE #ifdef SO_BINDTODEVICE
int ret; int ret;
@ -461,8 +446,8 @@ bgp_bind (struct peer *peer)
if (!peer->bgp->vrf_id && !peer->ifname && !peer->conf_if) if (!peer->bgp->vrf_id && !peer->ifname && !peer->conf_if)
return 0; return 0;
if (peer->su.sa.sa_family != AF_INET && if (peer->su.sa.sa_family != AF_INET
peer->su.sa.sa_family != AF_INET6) && peer->su.sa.sa_family != AF_INET6)
return 0; // unexpected return 0; // unexpected
/* For IPv6 peering, interface (unnumbered or link-local with interface) /* For IPv6 peering, interface (unnumbered or link-local with interface)
@ -470,8 +455,9 @@ bgp_bind (struct peer *peer)
* VRF are the situations to bind. * VRF are the situations to bind.
*/ */
if (peer->su.sa.sa_family == AF_INET6) if (peer->su.sa.sa_family == AF_INET6)
name = (peer->conf_if ? peer->conf_if : \ name = (peer->conf_if ? peer->conf_if
(peer->ifname ? peer->ifname : peer->bgp->name)); : (peer->ifname ? peer->ifname
: peer->bgp->name));
else else
name = peer->ifname ? peer->ifname : peer->bgp->name; name = peer->ifname ? peer->ifname : peer->bgp->name;
@ -484,25 +470,24 @@ bgp_bind (struct peer *peer)
if (bgpd_privs.change(ZPRIVS_RAISE)) if (bgpd_privs.change(ZPRIVS_RAISE))
zlog_err("bgp_bind: could not raise privs"); zlog_err("bgp_bind: could not raise privs");
ret = setsockopt (peer->fd, SOL_SOCKET, SO_BINDTODEVICE, ret = setsockopt(peer->fd, SOL_SOCKET, SO_BINDTODEVICE, name,
name, strlen(name)); strlen(name));
myerrno = errno; myerrno = errno;
if (bgpd_privs.change(ZPRIVS_LOWER)) if (bgpd_privs.change(ZPRIVS_LOWER))
zlog_err("bgp_bind: could not lower privs"); zlog_err("bgp_bind: could not lower privs");
if (ret < 0) if (ret < 0) {
{
if (bgp_debug_neighbor_events(peer)) if (bgp_debug_neighbor_events(peer))
zlog_debug ("bind to interface %s failed, errno=%d", name, myerrno); zlog_debug("bind to interface %s failed, errno=%d",
name, myerrno);
return ret; return ret;
} }
#endif /* SO_BINDTODEVICE */ #endif /* SO_BINDTODEVICE */
return 0; return 0;
} }
static int static int bgp_update_address(struct interface *ifp, const union sockunion *dst,
bgp_update_address (struct interface *ifp, const union sockunion *dst,
union sockunion *addr) union sockunion *addr)
{ {
struct prefix *p, *sel, d; struct prefix *p, *sel, d;
@ -514,13 +499,11 @@ bgp_update_address (struct interface *ifp, const union sockunion *dst,
sel = NULL; sel = NULL;
common = -1; common = -1;
for (ALL_LIST_ELEMENTS_RO (ifp->connected, node, connected)) for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, connected)) {
{
p = connected->address; p = connected->address;
if (p->family != d.family) if (p->family != d.family)
continue; continue;
if (prefix_common_bits (p, &d) > common) if (prefix_common_bits(p, &d) > common) {
{
sel = p; sel = p;
common = prefix_common_bits(sel, &d); common = prefix_common_bits(sel, &d);
} }
@ -534,8 +517,7 @@ bgp_update_address (struct interface *ifp, const union sockunion *dst,
} }
/* Update source selection. */ /* Update source selection. */
static int static int bgp_update_source(struct peer *peer)
bgp_update_source (struct peer *peer)
{ {
struct interface *ifp; struct interface *ifp;
union sockunion addr; union sockunion addr;
@ -544,8 +526,7 @@ bgp_update_source (struct peer *peer)
sockunion_init(&addr); sockunion_init(&addr);
/* Source is specified with interface name. */ /* Source is specified with interface name. */
if (peer->update_if) if (peer->update_if) {
{
ifp = if_lookup_by_name(peer->update_if, peer->bgp->vrf_id); ifp = if_lookup_by_name(peer->update_if, peer->bgp->vrf_id);
if (!ifp) if (!ifp)
return -1; return -1;
@ -558,7 +539,8 @@ bgp_update_source (struct peer *peer)
/* Source is specified with IP address. */ /* Source is specified with IP address. */
if (peer->update_source) if (peer->update_source)
ret = sockunion_bind (peer->fd, peer->update_source, 0, peer->update_source); ret = sockunion_bind(peer->fd, peer->update_source, 0,
peer->update_source);
return ret; return ret;
} }
@ -566,13 +548,11 @@ bgp_update_source (struct peer *peer)
#define DATAPLANE_MARK 254 /* main table ID */ #define DATAPLANE_MARK 254 /* main table ID */
/* BGP try to connect to the peer. */ /* BGP try to connect to the peer. */
int int bgp_connect(struct peer *peer)
bgp_connect (struct peer *peer)
{ {
ifindex_t ifindex = 0; ifindex_t ifindex = 0;
if (peer->conf_if && BGP_PEER_SU_UNSPEC(peer)) if (peer->conf_if && BGP_PEER_SU_UNSPEC(peer)) {
{
zlog_debug("Peer address not learnt: Returning from connect"); zlog_debug("Peer address not learnt: Returning from connect");
return 0; return 0;
} }
@ -592,8 +572,8 @@ bgp_connect (struct peer *peer)
sockopt_reuseaddr(peer->fd); sockopt_reuseaddr(peer->fd);
sockopt_reuseport(peer->fd); sockopt_reuseport(peer->fd);
if (sockopt_mark_default(peer->fd, DATAPLANE_MARK, &bgpd_privs) < 0) if (sockopt_mark_default(peer->fd, DATAPLANE_MARK, &bgpd_privs) < 0)
zlog_warn("Unable to set mark on FD for peer %s, err=%s", peer->host, zlog_warn("Unable to set mark on FD for peer %s, err=%s",
safe_strerror(errno)); peer->host, safe_strerror(errno));
#ifdef IPTOS_PREC_INTERNETCONTROL #ifdef IPTOS_PREC_INTERNETCONTROL
if (bgpd_privs.change(ZPRIVS_RAISE)) if (bgpd_privs.change(ZPRIVS_RAISE))
@ -613,48 +593,49 @@ bgp_connect (struct peer *peer)
bgp_bind(peer); bgp_bind(peer);
/* Update source bind. */ /* Update source bind. */
if (bgp_update_source (peer) < 0) if (bgp_update_source(peer) < 0) {
{
return connect_error; return connect_error;
} }
if (peer->conf_if || peer->ifname) if (peer->conf_if || peer->ifname)
ifindex = ifname2ifindex (peer->conf_if ? peer->conf_if : peer->ifname, peer->bgp->vrf_id); ifindex = ifname2ifindex(peer->conf_if ? peer->conf_if
: peer->ifname,
peer->bgp->vrf_id);
if (bgp_debug_neighbor_events(peer)) if (bgp_debug_neighbor_events(peer))
zlog_debug ("%s [Event] Connect start to %s fd %d", zlog_debug("%s [Event] Connect start to %s fd %d", peer->host,
peer->host, peer->host, peer->fd); peer->host, peer->fd);
/* Connect to the remote peer. */ /* Connect to the remote peer. */
return sockunion_connect (peer->fd, &peer->su, htons (peer->port), ifindex); return sockunion_connect(peer->fd, &peer->su, htons(peer->port),
ifindex);
} }
/* After TCP connection is established. Get local address and port. */ /* After TCP connection is established. Get local address and port. */
int int bgp_getsockname(struct peer *peer)
bgp_getsockname (struct peer *peer)
{
if (peer->su_local)
{ {
if (peer->su_local) {
sockunion_free(peer->su_local); sockunion_free(peer->su_local);
peer->su_local = NULL; peer->su_local = NULL;
} }
if (peer->su_remote) if (peer->su_remote) {
{
sockunion_free(peer->su_remote); sockunion_free(peer->su_remote);
peer->su_remote = NULL; peer->su_remote = NULL;
} }
peer->su_local = sockunion_getsockname(peer->fd); peer->su_local = sockunion_getsockname(peer->fd);
if (!peer->su_local) return -1; if (!peer->su_local)
return -1;
peer->su_remote = sockunion_getpeername(peer->fd); peer->su_remote = sockunion_getpeername(peer->fd);
if (!peer->su_remote) return -1; if (!peer->su_remote)
return -1;
if (bgp_nexthop_set (peer->su_local, peer->su_remote, if (bgp_nexthop_set(peer->su_local, peer->su_remote, &peer->nexthop,
&peer->nexthop, peer)) peer)) {
{
#if defined(HAVE_CUMULUS) #if defined(HAVE_CUMULUS)
zlog_err ("%s: nexthop_set failed, resetting connection - intf %p", zlog_err(
"%s: nexthop_set failed, resetting connection - intf %p",
peer->host, peer->nexthop.ifp); peer->host, peer->nexthop.ifp);
return -1; return -1;
#endif #endif
@ -664,8 +645,7 @@ bgp_getsockname (struct peer *peer)
} }
static int static int bgp_listener(int sock, struct sockaddr *sa, socklen_t salen)
bgp_listener (int sock, struct sockaddr *sa, socklen_t salen)
{ {
struct bgp_listener *listener; struct bgp_listener *listener;
int ret, en; int ret, en;
@ -690,15 +670,13 @@ bgp_listener (int sock, struct sockaddr *sa, socklen_t salen)
if (bgpd_privs.change(ZPRIVS_LOWER)) if (bgpd_privs.change(ZPRIVS_LOWER))
zlog_err("%s: could not lower privs", __func__); zlog_err("%s: could not lower privs", __func__);
if (ret < 0) if (ret < 0) {
{
zlog_err("bind: %s", safe_strerror(en)); zlog_err("bind: %s", safe_strerror(en));
return ret; return ret;
} }
ret = listen(sock, 3); ret = listen(sock, 3);
if (ret < 0) if (ret < 0) {
{
zlog_err("listen: %s", safe_strerror(errno)); zlog_err("listen: %s", safe_strerror(errno));
return ret; return ret;
} }
@ -707,15 +685,15 @@ bgp_listener (int sock, struct sockaddr *sa, socklen_t salen)
listener->fd = sock; listener->fd = sock;
memcpy(&listener->su, sa, salen); memcpy(&listener->su, sa, salen);
listener->thread = NULL; listener->thread = NULL;
thread_add_read(bm->master, bgp_accept, listener, sock, &listener->thread); thread_add_read(bm->master, bgp_accept, listener, sock,
&listener->thread);
listnode_add(bm->listen_sockets, listener); listnode_add(bm->listen_sockets, listener);
return 0; return 0;
} }
/* IPv6 supported version of BGP server socket setup. */ /* IPv6 supported version of BGP server socket setup. */
int int bgp_socket(unsigned short port, const char *address)
bgp_socket (unsigned short port, const char *address)
{ {
struct addrinfo *ainfo; struct addrinfo *ainfo;
struct addrinfo *ainfo_save; struct addrinfo *ainfo_save;
@ -731,28 +709,27 @@ bgp_socket (unsigned short port, const char *address)
port_str[sizeof(port_str) - 1] = '\0'; port_str[sizeof(port_str) - 1] = '\0';
ret = getaddrinfo(address, port_str, &req, &ainfo_save); ret = getaddrinfo(address, port_str, &req, &ainfo_save);
if (ret != 0) if (ret != 0) {
{
zlog_err("getaddrinfo: %s", gai_strerror(ret)); zlog_err("getaddrinfo: %s", gai_strerror(ret));
return -1; return -1;
} }
count = 0; count = 0;
for (ainfo = ainfo_save; ainfo; ainfo = ainfo->ai_next) for (ainfo = ainfo_save; ainfo; ainfo = ainfo->ai_next) {
{
int sock; int sock;
if (ainfo->ai_family != AF_INET && ainfo->ai_family != AF_INET6) if (ainfo->ai_family != AF_INET && ainfo->ai_family != AF_INET6)
continue; continue;
sock = socket (ainfo->ai_family, ainfo->ai_socktype, ainfo->ai_protocol); sock = socket(ainfo->ai_family, ainfo->ai_socktype,
if (sock < 0) ainfo->ai_protocol);
{ if (sock < 0) {
zlog_err("socket: %s", safe_strerror(errno)); zlog_err("socket: %s", safe_strerror(errno));
continue; continue;
} }
/* if we intend to implement ttl-security, this socket needs ttl=255 */ /* if we intend to implement ttl-security, this socket needs
* ttl=255 */
sockopt_ttl(ainfo->ai_family, sock, MAXTTL); sockopt_ttl(ainfo->ai_family, sock, MAXTTL);
ret = bgp_listener(sock, ainfo->ai_addr, ainfo->ai_addrlen); ret = bgp_listener(sock, ainfo->ai_addr, ainfo->ai_addrlen);
@ -762,8 +739,7 @@ bgp_socket (unsigned short port, const char *address)
close(sock); close(sock);
} }
freeaddrinfo(ainfo_save); freeaddrinfo(ainfo_save);
if (count == 0) if (count == 0) {
{
zlog_err("%s: no usable addresses", __func__); zlog_err("%s: no usable addresses", __func__);
return -1; return -1;
} }
@ -771,8 +747,7 @@ bgp_socket (unsigned short port, const char *address)
return 0; return 0;
} }
void void bgp_close(void)
bgp_close (void)
{ {
struct listnode *node, *next; struct listnode *node, *next;
struct bgp_listener *listener; struct bgp_listener *listener;
@ -780,8 +755,7 @@ bgp_close (void)
if (bm->listen_sockets == NULL) if (bm->listen_sockets == NULL)
return; return;
for (ALL_LIST_ELEMENTS (bm->listen_sockets, node, next, listener)) for (ALL_LIST_ELEMENTS(bm->listen_sockets, node, next, listener)) {
{
thread_cancel(listener->thread); thread_cancel(listener->thread);
close(listener->fd); close(listener->fd);
listnode_delete(bm->listen_sockets, listener); listnode_delete(bm->listen_sockets, listener);

View File

@ -47,46 +47,41 @@
#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,
sizeof(struct bgp_nexthop_cache));
LIST_INIT(&(bnc->paths)); LIST_INIT(&(bnc->paths));
return bnc; 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);
@ -94,14 +89,12 @@ bgp_nexthop_cache_reset (struct bgp_table *table)
} }
/* 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;
@ -113,22 +106,19 @@ bgp_address_hash_alloc (void *p)
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;
@ -136,15 +126,13 @@ bgp_address_hash_cmp (const void *p1, const void *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;
@ -153,8 +141,7 @@ bgp_address_destroy (struct bgp *bgp)
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;
@ -168,8 +155,7 @@ bgp_address_add (struct bgp *bgp, struct prefix *p)
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;
@ -183,21 +169,18 @@ bgp_address_del (struct bgp *bgp, struct prefix *p)
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;
@ -209,8 +192,7 @@ bgp_connected_add (struct bgp *bgp, struct connected *ifc)
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))
@ -218,33 +200,30 @@ bgp_connected_add (struct bgp *bgp, struct connected *ifc)
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) {
else if (addr->family == AF_INET6)
{
apply_mask_ipv6((struct prefix_ipv6 *)&p); apply_mask_ipv6((struct prefix_ipv6 *)&p);
if (IN6_IS_ADDR_UNSPECIFIED(&p.u.prefix6)) if (IN6_IS_ADDR_UNSPECIFIED(&p.u.prefix6))
@ -253,23 +232,21 @@ bgp_connected_add (struct bgp *bgp, struct connected *ifc)
if (IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6)) if (IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6))
return; return;
rn = bgp_node_get (bgp->connected_table[AFI_IP6], (struct prefix *) &p); rn = bgp_node_get(bgp->connected_table[AFI_IP6],
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;
} }
} }
} }
void void bgp_connected_delete(struct bgp *bgp, struct connected *ifc)
bgp_connected_delete (struct bgp *bgp, struct connected *ifc)
{ {
struct prefix p; struct prefix p;
struct prefix *addr; struct prefix *addr;
@ -279,8 +256,7 @@ bgp_connected_delete (struct bgp *bgp, struct connected *ifc)
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))
@ -294,16 +270,13 @@ bgp_connected_delete (struct bgp *bgp, struct connected *ifc)
bc = rn->info; bc = rn->info;
bc->refcnt--; bc->refcnt--;
if (bc->refcnt == 0) if (bc->refcnt == 0) {
{
XFREE(MTYPE_BGP_CONN, bc); XFREE(MTYPE_BGP_CONN, bc);
rn->info = NULL; rn->info = NULL;
} }
bgp_unlock_node(rn); bgp_unlock_node(rn);
bgp_unlock_node(rn); bgp_unlock_node(rn);
} } else if (addr->family == AF_INET6) {
else if (addr->family == AF_INET6)
{
apply_mask_ipv6((struct prefix_ipv6 *)&p); apply_mask_ipv6((struct prefix_ipv6 *)&p);
if (IN6_IS_ADDR_UNSPECIFIED(&p.u.prefix6)) if (IN6_IS_ADDR_UNSPECIFIED(&p.u.prefix6))
@ -312,14 +285,14 @@ bgp_connected_delete (struct bgp *bgp, struct connected *ifc)
if (IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6)) if (IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6))
return; return;
rn = bgp_node_lookup (bgp->connected_table[AFI_IP6], (struct prefix *) &p); rn = bgp_node_lookup(bgp->connected_table[AFI_IP6],
(struct prefix *)&p);
if (!rn) if (!rn)
return; return;
bc = rn->info; bc = rn->info;
bc->refcnt--; bc->refcnt--;
if (bc->refcnt == 0) if (bc->refcnt == 0) {
{
XFREE(MTYPE_BGP_CONN, bc); XFREE(MTYPE_BGP_CONN, bc);
rn->info = NULL; rn->info = NULL;
} }
@ -328,12 +301,11 @@ bgp_connected_delete (struct bgp *bgp, struct connected *ifc)
} }
} }
int int bgp_nexthop_self(struct bgp *bgp, struct in_addr nh_addr)
bgp_nexthop_self (struct bgp *bgp, struct attr *attr)
{ {
struct bgp_addr tmp, *addr; struct bgp_addr tmp, *addr;
tmp.addr = attr->nexthop; tmp.addr = nh_addr;
addr = hash_lookup(bgp->address_hash, &tmp); addr = hash_lookup(bgp->address_hash, &tmp);
if (addr) if (addr)
@ -342,8 +314,7 @@ bgp_nexthop_self (struct bgp *bgp, struct attr *attr)
return 0; return 0;
} }
int int bgp_multiaccess_check_v4(struct in_addr nexthop, struct peer *peer)
bgp_multiaccess_check_v4 (struct in_addr nexthop, struct peer *peer)
{ {
struct bgp_node *rn1; struct bgp_node *rn1;
struct bgp_node *rn2; struct bgp_node *rn2;
@ -363,8 +334,7 @@ bgp_multiaccess_check_v4 (struct in_addr nexthop, struct peer *peer)
p.u.prefix4 = peer->su.sin.sin_addr; p.u.prefix4 = peer->su.sin.sin_addr;
rn2 = bgp_node_match(peer->bgp->connected_table[AFI_IP], &p); rn2 = bgp_node_match(peer->bgp->connected_table[AFI_IP], &p);
if (!rn2) if (!rn2) {
{
bgp_unlock_node(rn1); bgp_unlock_node(rn1);
return 0; return 0;
} }
@ -377,8 +347,7 @@ bgp_multiaccess_check_v4 (struct in_addr nexthop, struct peer *peer)
return (ret); return (ret);
} }
static void static void bgp_show_nexthops(struct vty *vty, struct bgp *bgp, int detail)
bgp_show_nexthops (struct vty *vty, struct bgp *bgp, int detail)
{ {
struct bgp_node *rn; struct bgp_node *rn;
struct bgp_nexthop_cache *bnc; struct bgp_nexthop_cache *bnc;
@ -387,71 +356,105 @@ bgp_show_nexthops (struct vty *vty, struct bgp *bgp, int detail)
time_t tbuf; time_t tbuf;
afi_t afi; afi_t afi;
vty_outln (vty, "Current BGP nexthop cache:"); vty_out(vty, "Current BGP nexthop cache:\n");
for (afi = AFI_IP ; afi < AFI_MAX ; afi++) for (afi = AFI_IP; afi < AFI_MAX; afi++) {
{
if (!bgp->nexthop_cache_table[afi]) if (!bgp->nexthop_cache_table[afi])
continue; continue;
for (rn = bgp_table_top (bgp->nexthop_cache_table[afi]); rn; rn = bgp_route_next (rn)) for (rn = bgp_table_top(bgp->nexthop_cache_table[afi]); rn;
{ rn = bgp_route_next(rn)) {
if ((bnc = rn->info) != NULL) if ((bnc = rn->info) != NULL) {
{ if (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_VALID)) {
if (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_VALID)) vty_out(vty,
{ " %s valid [IGP metric %d], #paths %d\n",
vty_outln (vty, " %s valid [IGP metric %d], #paths %d", inet_ntop(rn->p.family,
inet_ntop (rn->p.family, &rn->p.u.prefix, buf, sizeof (buf)), &rn->p.u.prefix, buf,
sizeof(buf)),
bnc->metric, bnc->path_count); bnc->metric, bnc->path_count);
if (detail) if (detail)
for (nexthop = bnc->nexthop; nexthop; nexthop = nexthop->next) for (nexthop = bnc->nexthop;
switch (nexthop->type) nexthop;
{ nexthop = nexthop->next)
switch (nexthop->type) {
case NEXTHOP_TYPE_IPV6: case NEXTHOP_TYPE_IPV6:
vty_outln (vty, " gate %s", vty_out(vty,
inet_ntop(AF_INET6, &nexthop->gate.ipv6, buf, sizeof(buf))); " gate %s\n",
inet_ntop(
AF_INET6,
&nexthop->gate
.ipv6,
buf,
sizeof(buf)));
break; break;
case NEXTHOP_TYPE_IPV6_IFINDEX: case NEXTHOP_TYPE_IPV6_IFINDEX:
vty_outln (vty, " gate %s, if %s", vty_out(vty,
inet_ntop(AF_INET6, &nexthop->gate.ipv6, buf, " gate %s, if %s\n",
inet_ntop(
AF_INET6,
&nexthop->gate
.ipv6,
buf,
sizeof(buf)), sizeof(buf)),
ifindex2ifname(nexthop->ifindex, bgp->vrf_id)); ifindex2ifname(
nexthop->ifindex,
bgp->vrf_id));
break; break;
case NEXTHOP_TYPE_IPV4: case NEXTHOP_TYPE_IPV4:
vty_outln (vty, " gate %s", vty_out(vty,
inet_ntop(AF_INET, &nexthop->gate.ipv4, buf, sizeof(buf))); " gate %s\n",
inet_ntop(
AF_INET,
&nexthop->gate
.ipv4,
buf,
sizeof(buf)));
break; break;
case NEXTHOP_TYPE_IFINDEX: case NEXTHOP_TYPE_IFINDEX:
vty_outln (vty, " if %s", vty_out(vty,
ifindex2ifname(nexthop->ifindex, bgp->vrf_id)); " if %s\n",
ifindex2ifname(
nexthop->ifindex,
bgp->vrf_id));
break; break;
case NEXTHOP_TYPE_IPV4_IFINDEX: case NEXTHOP_TYPE_IPV4_IFINDEX:
vty_outln (vty, " gate %s, if %s", vty_out(vty,
inet_ntop(AF_INET, &nexthop->gate.ipv4, buf, " gate %s, if %s\n",
inet_ntop(
AF_INET,
&nexthop->gate
.ipv4,
buf,
sizeof(buf)), sizeof(buf)),
ifindex2ifname(nexthop->ifindex, bgp->vrf_id)); ifindex2ifname(
nexthop->ifindex,
bgp->vrf_id));
break; break;
default: default:
vty_outln (vty, " invalid nexthop type %u", vty_out(vty,
" invalid nexthop type %u\n",
nexthop->type); 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");
} }
else tbuf = time(NULL)
{ - (bgp_clock() - bnc->last_update);
vty_outln (vty, " %s invalid",
inet_ntop(rn->p.family, &rn->p.u.prefix, buf, sizeof(buf)));
if (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_CONNECTED))
vty_outln (vty, " Must be Connected");
}
tbuf = time(NULL) - (bgp_clock() - bnc->last_update);
vty_out(vty, " Last update: %s", ctime(&tbuf)); vty_out(vty, " Last update: %s", ctime(&tbuf));
vty_out (vty, VTYNL); vty_out(vty, "\n");
} }
} }
} }
} }
static int static int show_ip_bgp_nexthop_table(struct vty *vty, const char *name,
show_ip_bgp_nexthop_table (struct vty *vty, const char *name, int detail) int detail)
{ {
struct bgp *bgp; struct bgp *bgp;
@ -459,9 +462,8 @@ show_ip_bgp_nexthop_table (struct vty *vty, const char *name, int detail)
bgp = bgp_lookup_by_name(name); bgp = bgp_lookup_by_name(name);
else else
bgp = bgp_get_default(); bgp = bgp_get_default();
if (!bgp) if (!bgp) {
{ vty_out(vty, "%% No such BGP instance exist\n");
vty_outln (vty, "%% No such BGP instance exist");
return CMD_WARNING; return CMD_WARNING;
} }
@ -470,17 +472,16 @@ show_ip_bgp_nexthop_table (struct vty *vty, const char *name, int detail)
return CMD_SUCCESS; return CMD_SUCCESS;
} }
static void static void bgp_show_all_instances_nexthops_vty(struct vty *vty)
bgp_show_all_instances_nexthops_vty (struct vty *vty)
{ {
struct listnode *node, *nnode; struct listnode *node, *nnode;
struct bgp *bgp; struct bgp *bgp;
for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp)) for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
{ vty_out(vty, "\nInstance %s:\n",
vty_outln (vty, "%sInstance %s:", (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
VTYNL, ? "Default"
(bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) ? "Default" : bgp->name); : bgp->name);
bgp_show_nexthops(vty, bgp, 0); bgp_show_nexthops(vty, bgp, 0);
} }
} }
@ -514,33 +515,30 @@ DEFUN (show_ip_bgp_instance_all_nexthop,
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]);

View File

@ -25,20 +25,18 @@
#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;
@ -74,7 +72,7 @@ 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);

View File

@ -53,15 +53,13 @@ static int make_prefix(int afi, struct bgp_info *ri, struct prefix *p);
static void path_nh_map(struct bgp_info *path, struct bgp_nexthop_cache *bnc, static void path_nh_map(struct bgp_info *path, struct bgp_nexthop_cache *bnc,
int keep); int keep);
static int static int bgp_isvalid_nexthop(struct bgp_nexthop_cache *bnc)
bgp_isvalid_nexthop (struct bgp_nexthop_cache *bnc)
{ {
return (bgp_zebra_num_connects() == 0 || return (bgp_zebra_num_connects() == 0
(bnc && CHECK_FLAG(bnc->flags, BGP_NEXTHOP_VALID))); || (bnc && CHECK_FLAG(bnc->flags, BGP_NEXTHOP_VALID)));
} }
int int bgp_find_nexthop(struct bgp_info *path, int connected)
bgp_find_nexthop (struct bgp_info *path, int connected)
{ {
struct bgp_nexthop_cache *bnc = path->nexthop; struct bgp_nexthop_cache *bnc = path->nexthop;
@ -82,18 +80,16 @@ bgp_find_nexthop (struct bgp_info *path, int connected)
return (bgp_isvalid_nexthop(bnc)); return (bgp_isvalid_nexthop(bnc));
} }
static void static void bgp_unlink_nexthop_check(struct bgp_nexthop_cache *bnc)
bgp_unlink_nexthop_check (struct bgp_nexthop_cache *bnc)
{
if (LIST_EMPTY(&(bnc->paths)) && !bnc->nht_info)
{
if (BGP_DEBUG(nht, NHT))
{ {
if (LIST_EMPTY(&(bnc->paths)) && !bnc->nht_info) {
if (BGP_DEBUG(nht, NHT)) {
char buf[PREFIX2STR_BUFFER]; char buf[PREFIX2STR_BUFFER];
zlog_debug("bgp_unlink_nexthop: freeing bnc %s", zlog_debug("bgp_unlink_nexthop: freeing bnc %s",
bnc_str(bnc, buf, PREFIX2STR_BUFFER)); bnc_str(bnc, buf, PREFIX2STR_BUFFER));
} }
unregister_zebra_rnh(bnc, CHECK_FLAG(bnc->flags, BGP_STATIC_ROUTE)); unregister_zebra_rnh(bnc,
CHECK_FLAG(bnc->flags, BGP_STATIC_ROUTE));
bnc->node->info = NULL; bnc->node->info = NULL;
bgp_unlock_node(bnc->node); bgp_unlock_node(bnc->node);
bnc->node = NULL; bnc->node = NULL;
@ -101,8 +97,7 @@ bgp_unlink_nexthop_check (struct bgp_nexthop_cache *bnc)
} }
} }
void void bgp_unlink_nexthop(struct bgp_info *path)
bgp_unlink_nexthop (struct bgp_info *path)
{ {
struct bgp_nexthop_cache *bnc = path->nexthop; struct bgp_nexthop_cache *bnc = path->nexthop;
@ -114,8 +109,7 @@ bgp_unlink_nexthop (struct bgp_info *path)
bgp_unlink_nexthop_check(bnc); bgp_unlink_nexthop_check(bnc);
} }
void void bgp_unlink_nexthop_by_peer(struct peer *peer)
bgp_unlink_nexthop_by_peer (struct peer *peer)
{ {
struct prefix p; struct prefix p;
struct bgp_node *rn; struct bgp_node *rn;
@ -138,8 +132,7 @@ bgp_unlink_nexthop_by_peer (struct peer *peer)
bgp_unlink_nexthop_check(bnc); bgp_unlink_nexthop_check(bnc);
} }
int int bgp_find_or_add_nexthop(struct bgp *bgp, afi_t afi, struct bgp_info *ri,
bgp_find_or_add_nexthop (struct bgp *bgp, afi_t afi, struct bgp_info *ri,
struct peer *peer, int connected) struct peer *peer, int connected)
{ {
struct bgp_node *rn; struct bgp_node *rn;
@ -147,37 +140,38 @@ bgp_find_or_add_nexthop (struct bgp *bgp, afi_t afi, struct bgp_info *ri,
struct prefix p; struct prefix p;
int is_bgp_static_route = 0; int is_bgp_static_route = 0;
if (ri) if (ri) {
{ is_bgp_static_route = ((ri->type == ZEBRA_ROUTE_BGP)
is_bgp_static_route = ((ri->type == ZEBRA_ROUTE_BGP) && && (ri->sub_type == BGP_ROUTE_STATIC))
(ri->sub_type == BGP_ROUTE_STATIC)) ? 1 : 0; ? 1
: 0;
/* Since Extended Next-hop Encoding (RFC5549) support, we want to derive /* Since Extended Next-hop Encoding (RFC5549) support, we want
to derive
address-family from the next-hop. */ address-family from the next-hop. */
if (!is_bgp_static_route) if (!is_bgp_static_route)
afi = BGP_ATTR_NEXTHOP_AFI_IP6(ri->attr) ? AFI_IP6 : AFI_IP; afi = BGP_ATTR_NEXTHOP_AFI_IP6(ri->attr) ? AFI_IP6
: AFI_IP;
/* This will return TRUE if the global IPv6 NH is a link local addr */ /* This will return TRUE if the global IPv6 NH is a link local
* addr */
if (make_prefix(afi, ri, &p) < 0) if (make_prefix(afi, ri, &p) < 0)
return 1; return 1;
} } else if (peer) {
else if (peer)
{
/* Don't register link local NH */ /* Don't register link local NH */
if (afi == AFI_IP6 && IN6_IS_ADDR_LINKLOCAL (&peer->su.sin6.sin6_addr)) if (afi == AFI_IP6
&& IN6_IS_ADDR_LINKLOCAL(&peer->su.sin6.sin6_addr))
return 1; return 1;
if (! sockunion2hostprefix (&peer->su, &p)) if (!sockunion2hostprefix(&peer->su, &p)) {
{ if (BGP_DEBUG(nht, NHT)) {
if (BGP_DEBUG(nht, NHT)) zlog_debug(
{ "%s: Attempting to register with unknown AFI %d (not %d or %d)",
zlog_debug("%s: Attempting to register with unknown AFI %d (not %d or %d)",
__FUNCTION__, afi, AFI_IP, AFI_IP6); __FUNCTION__, afi, AFI_IP, AFI_IP6);
} }
return 0; return 0;
} }
} } else
else
return 0; return 0;
if (is_bgp_static_route) if (is_bgp_static_route)
@ -185,15 +179,13 @@ bgp_find_or_add_nexthop (struct bgp *bgp, afi_t afi, struct bgp_info *ri,
else else
rn = bgp_node_get(bgp->nexthop_cache_table[afi], &p); rn = bgp_node_get(bgp->nexthop_cache_table[afi], &p);
if (!rn->info) if (!rn->info) {
{
bnc = bnc_new(); bnc = bnc_new();
rn->info = bnc; rn->info = bnc;
bnc->node = rn; bnc->node = rn;
bnc->bgp = bgp; bnc->bgp = bgp;
bgp_lock_node(rn); bgp_lock_node(rn);
if (BGP_DEBUG(nht, NHT)) if (BGP_DEBUG(nht, NHT)) {
{
char buf[PREFIX2STR_BUFFER]; char buf[PREFIX2STR_BUFFER];
zlog_debug("Allocated bnc %s peer %p", zlog_debug("Allocated bnc %s peer %p",
@ -203,58 +195,54 @@ bgp_find_or_add_nexthop (struct bgp *bgp, afi_t afi, struct bgp_info *ri,
bnc = rn->info; bnc = rn->info;
bgp_unlock_node(rn); bgp_unlock_node(rn);
if (is_bgp_static_route) if (is_bgp_static_route) {
{
SET_FLAG(bnc->flags, BGP_STATIC_ROUTE); SET_FLAG(bnc->flags, BGP_STATIC_ROUTE);
/* If we're toggling the type, re-register */ /* If we're toggling the type, re-register */
if ((bgp_flag_check(bgp, BGP_FLAG_IMPORT_CHECK)) && if ((bgp_flag_check(bgp, BGP_FLAG_IMPORT_CHECK))
!CHECK_FLAG(bnc->flags, BGP_STATIC_ROUTE_EXACT_MATCH)) && !CHECK_FLAG(bnc->flags, BGP_STATIC_ROUTE_EXACT_MATCH)) {
{
SET_FLAG(bnc->flags, BGP_STATIC_ROUTE_EXACT_MATCH); SET_FLAG(bnc->flags, BGP_STATIC_ROUTE_EXACT_MATCH);
UNSET_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED); UNSET_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED);
UNSET_FLAG(bnc->flags, BGP_NEXTHOP_VALID); UNSET_FLAG(bnc->flags, BGP_NEXTHOP_VALID);
} } else if ((!bgp_flag_check(bgp, BGP_FLAG_IMPORT_CHECK))
else if ((!bgp_flag_check(bgp, BGP_FLAG_IMPORT_CHECK)) && && CHECK_FLAG(bnc->flags,
CHECK_FLAG(bnc->flags, BGP_STATIC_ROUTE_EXACT_MATCH)) BGP_STATIC_ROUTE_EXACT_MATCH)) {
{
UNSET_FLAG(bnc->flags, BGP_STATIC_ROUTE_EXACT_MATCH); UNSET_FLAG(bnc->flags, BGP_STATIC_ROUTE_EXACT_MATCH);
UNSET_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED); UNSET_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED);
UNSET_FLAG(bnc->flags, BGP_NEXTHOP_VALID); UNSET_FLAG(bnc->flags, BGP_NEXTHOP_VALID);
} }
} }
/* When nexthop is already known, but now requires 'connected' resolution, /* When nexthop is already known, but now requires 'connected'
* re-register it. The reverse scenario where the nexthop currently requires * resolution,
* re-register it. The reverse scenario where the nexthop currently
* requires
* 'connected' resolution does not need a re-register (i.e., we treat * 'connected' resolution does not need a re-register (i.e., we treat
* 'connected-required' as an override) except in the scenario where this * 'connected-required' as an override) except in the scenario where
* this
* is actually a case of tracking a peer for connectivity (e.g., after * is actually a case of tracking a peer for connectivity (e.g., after
* disable connected-check). * disable connected-check).
* NOTE: We don't track the number of paths separately for 'connected- * NOTE: We don't track the number of paths separately for 'connected-
* required' vs 'connected-not-required' as this change is not a common * required' vs 'connected-not-required' as this change is not a common
* scenario. * scenario.
*/ */
else if (connected && ! CHECK_FLAG(bnc->flags, BGP_NEXTHOP_CONNECTED)) else if (connected && !CHECK_FLAG(bnc->flags, BGP_NEXTHOP_CONNECTED)) {
{
SET_FLAG(bnc->flags, BGP_NEXTHOP_CONNECTED); SET_FLAG(bnc->flags, BGP_NEXTHOP_CONNECTED);
UNSET_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED); UNSET_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED);
UNSET_FLAG(bnc->flags, BGP_NEXTHOP_VALID); UNSET_FLAG(bnc->flags, BGP_NEXTHOP_VALID);
} } else if (peer && !connected
else if (peer && !connected && CHECK_FLAG(bnc->flags, BGP_NEXTHOP_CONNECTED)) && CHECK_FLAG(bnc->flags, BGP_NEXTHOP_CONNECTED)) {
{
UNSET_FLAG(bnc->flags, BGP_NEXTHOP_CONNECTED); UNSET_FLAG(bnc->flags, BGP_NEXTHOP_CONNECTED);
UNSET_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED); UNSET_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED);
UNSET_FLAG(bnc->flags, BGP_NEXTHOP_VALID); UNSET_FLAG(bnc->flags, BGP_NEXTHOP_VALID);
} }
if (bgp->inst_type == BGP_INSTANCE_TYPE_VIEW) if (bgp->inst_type == BGP_INSTANCE_TYPE_VIEW) {
{
bnc->flags |= BGP_NEXTHOP_REGISTERED; bnc->flags |= BGP_NEXTHOP_REGISTERED;
bnc->flags |= BGP_NEXTHOP_VALID; bnc->flags |= BGP_NEXTHOP_VALID;
} } else if (!CHECK_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED))
else if (!CHECK_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED))
register_zebra_rnh(bnc, is_bgp_static_route); register_zebra_rnh(bnc, is_bgp_static_route);
if (ri && ri->nexthop != bnc) if (ri && ri->nexthop != bnc) {
{ /* Unlink from existing nexthop cache, if any. This will also
/* Unlink from existing nexthop cache, if any. This will also free * free
* the nexthop cache entry, if appropriate. * the nexthop cache entry, if appropriate.
*/ */
bgp_unlink_nexthop(ri); bgp_unlink_nexthop(ri);
@ -265,8 +253,7 @@ bgp_find_or_add_nexthop (struct bgp *bgp, afi_t afi, struct bgp_info *ri,
(bgp_info_extra_get(ri))->igpmetric = bnc->metric; (bgp_info_extra_get(ri))->igpmetric = bnc->metric;
else if (ri->extra) else if (ri->extra)
ri->extra->igpmetric = 0; ri->extra->igpmetric = 0;
} } else if (peer)
else if (peer)
bnc->nht_info = (void *)peer; /* NHT peer reference */ bnc->nht_info = (void *)peer; /* NHT peer reference */
/* /*
@ -280,8 +267,7 @@ bgp_find_or_add_nexthop (struct bgp *bgp, afi_t afi, struct bgp_info *ri,
return (bgp_isvalid_nexthop(bnc)); return (bgp_isvalid_nexthop(bnc));
} }
void void bgp_delete_connected_nexthop(afi_t afi, struct peer *peer)
bgp_delete_connected_nexthop (afi_t afi, struct peer *peer)
{ {
struct bgp_node *rn; struct bgp_node *rn;
struct bgp_nexthop_cache *bnc; struct bgp_nexthop_cache *bnc;
@ -297,11 +283,12 @@ bgp_delete_connected_nexthop (afi_t afi, struct peer *peer)
if (!sockunion2hostprefix(&peer->su, &p)) if (!sockunion2hostprefix(&peer->su, &p))
return; return;
rn = bgp_node_lookup(peer->bgp->nexthop_cache_table[family2afi(p.family)], &p); rn = bgp_node_lookup(
if (!rn || !rn->info) peer->bgp->nexthop_cache_table[family2afi(p.family)], &p);
{ if (!rn || !rn->info) {
if (BGP_DEBUG(nht, NHT)) if (BGP_DEBUG(nht, NHT))
zlog_debug("Cannot find connected NHT node for peer %s", peer->host); zlog_debug("Cannot find connected NHT node for peer %s",
peer->host);
if (rn) if (rn)
bgp_unlock_node(rn); bgp_unlock_node(rn);
return; return;
@ -310,18 +297,17 @@ bgp_delete_connected_nexthop (afi_t afi, struct peer *peer)
bnc = rn->info; bnc = rn->info;
bgp_unlock_node(rn); bgp_unlock_node(rn);
if (bnc->nht_info != peer) if (bnc->nht_info != peer) {
{
if (BGP_DEBUG(nht, NHT)) if (BGP_DEBUG(nht, NHT))
zlog_debug("Connected NHT %p node for peer %s points to %p", zlog_debug(
"Connected NHT %p node for peer %s points to %p",
bnc, peer->host, bnc->nht_info); bnc, peer->host, bnc->nht_info);
return; return;
} }
bnc->nht_info = NULL; bnc->nht_info = NULL;
if (LIST_EMPTY(&(bnc->paths))) if (LIST_EMPTY(&(bnc->paths))) {
{
if (BGP_DEBUG(nht, NHT)) if (BGP_DEBUG(nht, NHT))
zlog_debug("Freeing connected NHT node %p for peer %s", zlog_debug("Freeing connected NHT node %p for peer %s",
bnc, peer->host); bnc, peer->host);
@ -332,8 +318,7 @@ bgp_delete_connected_nexthop (afi_t afi, struct peer *peer)
} }
} }
void void bgp_parse_nexthop_update(int command, vrf_id_t vrf_id)
bgp_parse_nexthop_update (int command, vrf_id_t vrf_id)
{ {
struct stream *s; struct stream *s;
struct bgp_node *rn = NULL; struct bgp_node *rn = NULL;
@ -349,9 +334,10 @@ bgp_parse_nexthop_update (int command, vrf_id_t vrf_id)
struct bgp *bgp; struct bgp *bgp;
bgp = bgp_lookup_by_vrf_id(vrf_id); bgp = bgp_lookup_by_vrf_id(vrf_id);
if (!bgp) if (!bgp) {
{ zlog_err(
zlog_err("parse nexthop update: instance not found for vrf_id %d", vrf_id); "parse nexthop update: instance not found for vrf_id %d",
vrf_id);
return; return;
} }
@ -360,8 +346,7 @@ bgp_parse_nexthop_update (int command, vrf_id_t vrf_id)
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);
switch (p.family) switch (p.family) {
{
case AF_INET: case AF_INET:
p.u.prefix4.s_addr = stream_get_ipv4(s); p.u.prefix4.s_addr = stream_get_ipv4(s);
break; break;
@ -373,17 +358,18 @@ bgp_parse_nexthop_update (int command, vrf_id_t vrf_id)
} }
if (command == ZEBRA_NEXTHOP_UPDATE) if (command == ZEBRA_NEXTHOP_UPDATE)
rn = bgp_node_lookup(bgp->nexthop_cache_table[family2afi(p.family)], &p); rn = bgp_node_lookup(
bgp->nexthop_cache_table[family2afi(p.family)], &p);
else if (command == ZEBRA_IMPORT_CHECK_UPDATE) else if (command == ZEBRA_IMPORT_CHECK_UPDATE)
rn = bgp_node_lookup(bgp->import_check_table[family2afi(p.family)], &p); rn = bgp_node_lookup(
bgp->import_check_table[family2afi(p.family)], &p);
if (!rn || !rn->info) if (!rn || !rn->info) {
{ if (BGP_DEBUG(nht, NHT)) {
if (BGP_DEBUG(nht, NHT))
{
char buf[PREFIX2STR_BUFFER]; char buf[PREFIX2STR_BUFFER];
prefix2str(&p, buf, sizeof(buf)); prefix2str(&p, buf, sizeof(buf));
zlog_debug("parse nexthop update(%s): rn not found", buf); zlog_debug("parse nexthop update(%s): rn not found",
buf);
} }
if (rn) if (rn)
bgp_unlock_node(rn); bgp_unlock_node(rn);
@ -399,13 +385,13 @@ bgp_parse_nexthop_update (int command, vrf_id_t vrf_id)
nexthop_num = stream_getc(s); nexthop_num = stream_getc(s);
/* debug print the input */ /* debug print the input */
if (BGP_DEBUG(nht, NHT)) if (BGP_DEBUG(nht, NHT)) {
{
char buf[PREFIX2STR_BUFFER]; char buf[PREFIX2STR_BUFFER];
prefix2str(&p, buf, sizeof(buf)); prefix2str(&p, buf, sizeof(buf));
zlog_debug("%d: Rcvd NH update %s - metric %d/%d #nhops %d/%d flags 0x%x", zlog_debug(
vrf_id, buf, metric, bnc->metric, nexthop_num, bnc->nexthop_num, "%d: Rcvd NH update %s - metric %d/%d #nhops %d/%d flags 0x%x",
bnc->flags); vrf_id, buf, metric, bnc->metric, nexthop_num,
bnc->nexthop_num, bnc->flags);
} }
if (metric != bnc->metric) if (metric != bnc->metric)
@ -414,8 +400,7 @@ bgp_parse_nexthop_update (int command, vrf_id_t vrf_id)
if (nexthop_num != bnc->nexthop_num) if (nexthop_num != bnc->nexthop_num)
bnc->change_flags |= BGP_NEXTHOP_CHANGED; bnc->change_flags |= BGP_NEXTHOP_CHANGED;
if (nexthop_num) if (nexthop_num) {
{
/* notify bgp fsm if nbr ip goes from invalid->valid */ /* notify bgp fsm if nbr ip goes from invalid->valid */
if (!bnc->nexthop_num) if (!bnc->nexthop_num)
UNSET_FLAG(bnc->flags, BGP_NEXTHOP_PEER_NOTIFIED); UNSET_FLAG(bnc->flags, BGP_NEXTHOP_PEER_NOTIFIED);
@ -424,12 +409,10 @@ bgp_parse_nexthop_update (int command, vrf_id_t vrf_id)
bnc->metric = metric; bnc->metric = metric;
bnc->nexthop_num = nexthop_num; bnc->nexthop_num = nexthop_num;
for (i = 0; i < nexthop_num; i++) for (i = 0; i < nexthop_num; i++) {
{
nexthop = nexthop_new(); nexthop = nexthop_new();
nexthop->type = stream_getc(s); nexthop->type = stream_getc(s);
switch (nexthop->type) switch (nexthop->type) {
{
case NEXTHOP_TYPE_IPV4: case NEXTHOP_TYPE_IPV4:
nexthop->gate.ipv4.s_addr = stream_get_ipv4(s); nexthop->gate.ipv4.s_addr = stream_get_ipv4(s);
nexthop->ifindex = stream_getl(s); nexthop->ifindex = stream_getl(s);
@ -454,25 +437,23 @@ bgp_parse_nexthop_update (int command, vrf_id_t vrf_id)
break; break;
} }
if (BGP_DEBUG(nht, NHT)) if (BGP_DEBUG(nht, NHT)) {
{
char buf[NEXTHOP_STRLEN]; char buf[NEXTHOP_STRLEN];
zlog_debug(" nhop via %s", zlog_debug(
" nhop via %s",
nexthop2str(nexthop, buf, sizeof(buf))); nexthop2str(nexthop, buf, sizeof(buf)));
} }
if (nhlist_tail) if (nhlist_tail) {
{
nhlist_tail->next = nexthop; nhlist_tail->next = nexthop;
nhlist_tail = nexthop; nhlist_tail = nexthop;
} } else {
else
{
nhlist_tail = nexthop; nhlist_tail = nexthop;
nhlist_head = nexthop; nhlist_head = nexthop;
} }
/* No need to evaluate the nexthop if we have already determined /* No need to evaluate the nexthop if we have already
* determined
* that there has been a change. * that there has been a change.
*/ */
if (bnc->change_flags & BGP_NEXTHOP_CHANGED) if (bnc->change_flags & BGP_NEXTHOP_CHANGED)
@ -487,9 +468,7 @@ bgp_parse_nexthop_update (int command, vrf_id_t vrf_id)
} }
bnc_nexthop_free(bnc); bnc_nexthop_free(bnc);
bnc->nexthop = nhlist_head; bnc->nexthop = nhlist_head;
} } else {
else
{
bnc->flags &= ~BGP_NEXTHOP_VALID; bnc->flags &= ~BGP_NEXTHOP_VALID;
bnc->nexthop_num = nexthop_num; bnc->nexthop_num = nexthop_num;
@ -507,52 +486,46 @@ bgp_parse_nexthop_update (int command, vrf_id_t vrf_id)
* make_prefix - make a prefix structure from the path (essentially * make_prefix - make a prefix structure from the path (essentially
* path's node. * path's node.
*/ */
static int static int make_prefix(int afi, struct bgp_info *ri, struct prefix *p)
make_prefix (int afi, struct bgp_info *ri, struct prefix *p)
{ {
int is_bgp_static = ((ri->type == ZEBRA_ROUTE_BGP) && int is_bgp_static = ((ri->type == ZEBRA_ROUTE_BGP)
(ri->sub_type == BGP_ROUTE_STATIC)) ? 1 : 0; && (ri->sub_type == BGP_ROUTE_STATIC))
? 1
: 0;
memset(p, 0, sizeof(struct prefix)); memset(p, 0, sizeof(struct prefix));
switch (afi) switch (afi) {
{
case AFI_IP: case AFI_IP:
p->family = AF_INET; p->family = AF_INET;
if (is_bgp_static) if (is_bgp_static) {
{
p->u.prefix4 = ri->net->p.u.prefix4; p->u.prefix4 = ri->net->p.u.prefix4;
p->prefixlen = ri->net->p.prefixlen; p->prefixlen = ri->net->p.prefixlen;
} } else {
else
{
p->u.prefix4 = ri->attr->nexthop; p->u.prefix4 = ri->attr->nexthop;
p->prefixlen = IPV4_MAX_BITLEN; p->prefixlen = IPV4_MAX_BITLEN;
} }
break; break;
case AFI_IP6: case AFI_IP6:
/* We don't register link local NH */ /* We don't register link local NH */
if (ri->attr->extra->mp_nexthop_len != BGP_ATTR_NHLEN_IPV6_GLOBAL if (ri->attr->mp_nexthop_len != BGP_ATTR_NHLEN_IPV6_GLOBAL
|| IN6_IS_ADDR_LINKLOCAL (&ri->attr->extra->mp_nexthop_global)) || IN6_IS_ADDR_LINKLOCAL(&ri->attr->mp_nexthop_global))
return -1; return -1;
p->family = AF_INET6; p->family = AF_INET6;
if (is_bgp_static) if (is_bgp_static) {
{
p->u.prefix6 = ri->net->p.u.prefix6; p->u.prefix6 = ri->net->p.u.prefix6;
p->prefixlen = ri->net->p.prefixlen; p->prefixlen = ri->net->p.prefixlen;
} } else {
else p->u.prefix6 = ri->attr->mp_nexthop_global;
{
p->u.prefix6 = ri->attr->extra->mp_nexthop_global;
p->prefixlen = IPV6_MAX_BITLEN; p->prefixlen = IPV6_MAX_BITLEN;
} }
break; break;
default: default:
if (BGP_DEBUG(nht, NHT)) if (BGP_DEBUG(nht, NHT)) {
{ zlog_debug(
zlog_debug("%s: Attempting to make prefix with unknown AFI %d (not %d or %d)", "%s: Attempting to make prefix with unknown AFI %d (not %d or %d)",
__FUNCTION__, afi, AFI_IP, AFI_IP6); __FUNCTION__, afi, AFI_IP, AFI_IP6);
} }
break; break;
@ -569,8 +542,7 @@ make_prefix (int afi, struct bgp_info *ri, struct prefix *p)
* RETURNS: * RETURNS:
* void. * void.
*/ */
static void static void sendmsg_zebra_rnh(struct bgp_nexthop_cache *bnc, int command)
sendmsg_zebra_rnh (struct bgp_nexthop_cache *bnc, int command)
{ {
struct stream *s; struct stream *s;
struct prefix *p; struct prefix *p;
@ -588,16 +560,15 @@ sendmsg_zebra_rnh (struct bgp_nexthop_cache *bnc, int command)
s = zclient->obuf; s = zclient->obuf;
stream_reset(s); stream_reset(s);
zclient_create_header(s, command, bnc->bgp->vrf_id); zclient_create_header(s, command, bnc->bgp->vrf_id);
if (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_CONNECTED) || if (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_CONNECTED)
CHECK_FLAG(bnc->flags, BGP_STATIC_ROUTE_EXACT_MATCH)) || CHECK_FLAG(bnc->flags, BGP_STATIC_ROUTE_EXACT_MATCH))
stream_putc(s, 1); stream_putc(s, 1);
else else
stream_putc(s, 0); stream_putc(s, 0);
stream_putw(s, PREFIX_FAMILY(p)); stream_putw(s, PREFIX_FAMILY(p));
stream_putc(s, p->prefixlen); stream_putc(s, p->prefixlen);
switch (PREFIX_FAMILY(p)) switch (PREFIX_FAMILY(p)) {
{
case AF_INET: case AF_INET:
stream_put_in_addr(s, &p->u.prefix4); stream_put_in_addr(s, &p->u.prefix4);
break; break;
@ -614,11 +585,11 @@ sendmsg_zebra_rnh (struct bgp_nexthop_cache *bnc, int command)
if (ret < 0) if (ret < 0)
zlog_warn("sendmsg_nexthop: zclient_send_message() failed"); zlog_warn("sendmsg_nexthop: zclient_send_message() failed");
if ((command == ZEBRA_NEXTHOP_REGISTER) || if ((command == ZEBRA_NEXTHOP_REGISTER)
(command == ZEBRA_IMPORT_ROUTE_REGISTER)) || (command == ZEBRA_IMPORT_ROUTE_REGISTER))
SET_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED); SET_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED);
else if ((command == ZEBRA_NEXTHOP_UNREGISTER) || else if ((command == ZEBRA_NEXTHOP_UNREGISTER)
(command == ZEBRA_IMPORT_ROUTE_UNREGISTER)) || (command == ZEBRA_IMPORT_ROUTE_UNREGISTER))
UNSET_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED); UNSET_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED);
return; return;
} }
@ -631,8 +602,8 @@ sendmsg_zebra_rnh (struct bgp_nexthop_cache *bnc, int command)
* RETURNS: * RETURNS:
* void. * void.
*/ */
static void static void register_zebra_rnh(struct bgp_nexthop_cache *bnc,
register_zebra_rnh (struct bgp_nexthop_cache *bnc, int is_bgp_import_route) int is_bgp_import_route)
{ {
/* Check if we have already registered */ /* Check if we have already registered */
if (bnc->flags & BGP_NEXTHOP_REGISTERED) if (bnc->flags & BGP_NEXTHOP_REGISTERED)
@ -650,8 +621,8 @@ register_zebra_rnh (struct bgp_nexthop_cache *bnc, int is_bgp_import_route)
* RETURNS: * RETURNS:
* void. * void.
*/ */
static void static void unregister_zebra_rnh(struct bgp_nexthop_cache *bnc,
unregister_zebra_rnh (struct bgp_nexthop_cache *bnc, int is_bgp_import_route) int is_bgp_import_route)
{ {
/* Check if we have already registered */ /* Check if we have already registered */
if (!CHECK_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED)) if (!CHECK_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED))
@ -670,8 +641,7 @@ unregister_zebra_rnh (struct bgp_nexthop_cache *bnc, int is_bgp_import_route)
* RETURNS: * RETURNS:
* void. * void.
*/ */
static void static void evaluate_paths(struct bgp_nexthop_cache *bnc)
evaluate_paths (struct bgp_nexthop_cache *bnc)
{ {
struct bgp_node *rn; struct bgp_node *rn;
struct bgp_info *path; struct bgp_info *path;
@ -681,19 +651,19 @@ evaluate_paths (struct bgp_nexthop_cache *bnc)
struct bgp_table *table; struct bgp_table *table;
safi_t safi; safi_t safi;
if (BGP_DEBUG(nht, NHT)) if (BGP_DEBUG(nht, NHT)) {
{
char buf[PREFIX2STR_BUFFER]; char buf[PREFIX2STR_BUFFER];
bnc_str(bnc, buf, PREFIX2STR_BUFFER); bnc_str(bnc, buf, PREFIX2STR_BUFFER);
zlog_debug("NH update for %s - flags 0x%x chgflags 0x%x - evaluate paths", zlog_debug(
"NH update for %s - flags 0x%x chgflags 0x%x - evaluate paths",
buf, bnc->flags, bnc->change_flags); buf, bnc->flags, bnc->change_flags);
} }
LIST_FOREACH(path, &(bnc->paths), nh_thread) LIST_FOREACH(path, &(bnc->paths), nh_thread)
{ {
if (!(path->type == ZEBRA_ROUTE_BGP && if (!(path->type == ZEBRA_ROUTE_BGP
((path->sub_type == BGP_ROUTE_NORMAL) || && ((path->sub_type == BGP_ROUTE_NORMAL)
(path->sub_type == BGP_ROUTE_STATIC)))) || (path->sub_type == BGP_ROUTE_STATIC))))
continue; continue;
rn = path->net; rn = path->net;
@ -705,38 +675,37 @@ evaluate_paths (struct bgp_nexthop_cache *bnc)
/* Path becomes valid/invalid depending on whether the nexthop /* Path becomes valid/invalid depending on whether the nexthop
* reachable/unreachable. * reachable/unreachable.
*/ */
if ((CHECK_FLAG(path->flags, BGP_INFO_VALID) ? 1 : 0) != if ((CHECK_FLAG(path->flags, BGP_INFO_VALID) ? 1 : 0)
(bgp_isvalid_nexthop(bnc) ? 1 : 0)) != (bgp_isvalid_nexthop(bnc) ? 1 : 0)) {
{ if (CHECK_FLAG(path->flags, BGP_INFO_VALID)) {
if (CHECK_FLAG (path->flags, BGP_INFO_VALID)) bgp_aggregate_decrement(bgp, &rn->p, path, afi,
{ safi);
bgp_aggregate_decrement (bgp, &rn->p, path, afi, safi);
bgp_info_unset_flag(rn, path, BGP_INFO_VALID); bgp_info_unset_flag(rn, path, BGP_INFO_VALID);
} } else {
else
{
bgp_info_set_flag(rn, path, BGP_INFO_VALID); bgp_info_set_flag(rn, path, BGP_INFO_VALID);
bgp_aggregate_increment (bgp, &rn->p, path, afi, safi); bgp_aggregate_increment(bgp, &rn->p, path, afi,
safi);
} }
} }
/* Copy the metric to the path. Will be used for bestpath computation */ /* Copy the metric to the path. Will be used for bestpath
* computation */
if (bgp_isvalid_nexthop(bnc) && bnc->metric) if (bgp_isvalid_nexthop(bnc) && bnc->metric)
(bgp_info_extra_get(path))->igpmetric = bnc->metric; (bgp_info_extra_get(path))->igpmetric = bnc->metric;
else if (path->extra) else if (path->extra)
path->extra->igpmetric = 0; path->extra->igpmetric = 0;
if (CHECK_FLAG(bnc->change_flags, BGP_NEXTHOP_METRIC_CHANGED) || if (CHECK_FLAG(bnc->change_flags, BGP_NEXTHOP_METRIC_CHANGED)
CHECK_FLAG(bnc->change_flags, BGP_NEXTHOP_CHANGED)) || CHECK_FLAG(bnc->change_flags, BGP_NEXTHOP_CHANGED))
SET_FLAG(path->flags, BGP_INFO_IGP_CHANGED); SET_FLAG(path->flags, BGP_INFO_IGP_CHANGED);
bgp_process(bgp, rn, afi, safi); bgp_process(bgp, rn, afi, safi);
} }
if (peer && !CHECK_FLAG(bnc->flags, BGP_NEXTHOP_PEER_NOTIFIED)) if (peer && !CHECK_FLAG(bnc->flags, BGP_NEXTHOP_PEER_NOTIFIED)) {
{
if (BGP_DEBUG(nht, NHT)) if (BGP_DEBUG(nht, NHT))
zlog_debug("%s: Updating peer (%s) status with NHT", __FUNCTION__, peer->host); zlog_debug("%s: Updating peer (%s) status with NHT",
__FUNCTION__, peer->host);
bgp_fsm_nht_update(peer, bgp_isvalid_nexthop(bnc)); bgp_fsm_nht_update(peer, bgp_isvalid_nexthop(bnc));
SET_FLAG(bnc->flags, BGP_NEXTHOP_PEER_NOTIFIED); SET_FLAG(bnc->flags, BGP_NEXTHOP_PEER_NOTIFIED);
} }
@ -752,17 +721,15 @@ evaluate_paths (struct bgp_nexthop_cache *bnc)
* make - if set, make the association. if unset, just break the existing * make - if set, make the association. if unset, just break the existing
* association. * association.
*/ */
static void static void path_nh_map(struct bgp_info *path, struct bgp_nexthop_cache *bnc,
path_nh_map (struct bgp_info *path, struct bgp_nexthop_cache *bnc, int make) int make)
{
if (path->nexthop)
{ {
if (path->nexthop) {
LIST_REMOVE(path, nh_thread); LIST_REMOVE(path, nh_thread);
path->nexthop->path_count--; path->nexthop->path_count--;
path->nexthop = NULL; path->nexthop = NULL;
} }
if (make) if (make) {
{
LIST_INSERT_HEAD(&(bnc->paths), path, nh_thread); LIST_INSERT_HEAD(&(bnc->paths), path, nh_thread);
path->nexthop = bnc; path->nexthop = bnc;
path->nexthop->path_count++; path->nexthop->path_count++;

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.

File diff suppressed because it is too large Load Diff

View File

@ -22,34 +22,29 @@
#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[];
}; };
@ -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
@ -101,7 +95,8 @@ struct capability_gr
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,
json_object *);
extern as_t peek_for_as4_capability(struct peer *, u_char); 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

@ -47,15 +47,17 @@ 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,
int);
extern void bgp_capability_send(struct peer *, afi_t, safi_t, int, int); extern void bgp_capability_send(struct peer *, afi_t, safi_t, int, int);
extern void bgp_default_update_send (struct peer *, struct attr *, extern void bgp_default_update_send(struct peer *, struct attr *, afi_t, safi_t,
afi_t, safi_t, struct peer *); struct peer *);
extern void bgp_default_withdraw_send(struct peer *, afi_t, safi_t); 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 *);

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,8 +35,7 @@
(^|[,{}() ]|$) */ (^|[,{}() ]|$) */
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;
@ -54,14 +53,12 @@ bgp_regcomp (const char *regstr)
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
else
magic_str[j++] = regstr[i]; magic_str[j++] = regstr[i];
} }
magic_str[j] = '\0'; magic_str[j] = '\0';
@ -72,8 +69,7 @@ bgp_regcomp (const char *regstr)
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;
} }
@ -81,14 +77,12 @@ bgp_regcomp (const char *regstr)
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);

File diff suppressed because it is too large Load Diff

View File

@ -27,8 +27,7 @@
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,
@ -52,18 +51,18 @@ enum bgp_show_type
}; };
#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;
@ -74,35 +73,45 @@ struct bgp_info_extra
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 */
struct list *local_nexthops; /* optional, for static
routes */
} export; } 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 */
u_char un_family; /* family of cached un address, 0 if
unset */
union { union {
struct in_addr addr4; struct in_addr addr4;
struct in6_addr addr6; struct in6_addr addr6;
} un; /* cached un address */ } un; /* cached un address */
time_t create_time; time_t create_time;
struct prefix aux_prefix; /* AFI_L2VPN: the IP addr, if family set */ struct
prefix
aux_prefix; /* AFI_L2VPN: the IP addr,
if family set */
} import; } 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;
@ -171,12 +180,16 @@ struct bgp_info
/* 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;
@ -197,8 +210,7 @@ struct bgp_static
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;
@ -207,7 +219,7 @@ struct bgp_static
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;
@ -217,13 +229,13 @@ struct bgp_static
}; };
#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))
@ -265,25 +277,17 @@ 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;
} }
@ -309,44 +313,50 @@ extern struct bgp_node *bgp_afi_node_get (struct bgp_table *table, afi_t afi,
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_reap(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_delete(struct bgp_node *rn, struct bgp_info *ri);
extern struct bgp_info_extra *bgp_info_extra_get(struct bgp_info *); extern struct bgp_info_extra *bgp_info_extra_get(struct bgp_info *);
extern void bgp_info_set_flag(struct bgp_node *, struct bgp_info *, u_int32_t); extern void bgp_info_set_flag(struct bgp_node *, struct bgp_info *, u_int32_t);
extern void bgp_info_unset_flag (struct bgp_node *, struct bgp_info *, u_int32_t); extern void bgp_info_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 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 in_addr *,
const struct in6_addr *, unsigned int ifindex, const struct in6_addr *, unsigned int ifindex,
u_int32_t, u_char, u_short, route_tag_t); u_int32_t, u_char, u_short, route_tag_t);
extern void bgp_redistribute_delete (struct bgp *, struct prefix *, u_char, 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_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 prefix_rd *, mpls_label_t *,
struct bgp_route_evpn *); struct bgp_route_evpn *);
/* for bgp_nexthop and bgp_damp */ /* for bgp_nexthop and bgp_damp */
@ -359,28 +369,37 @@ extern void bgp_process (struct bgp *, struct bgp_node *, afi_t, safi_t);
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 *);
extern void route_vty_out_tag(struct vty *, struct prefix *, struct bgp_info *,
int, safi_t, json_object *);
extern void route_vty_out_tmp(struct vty *, struct prefix *, struct attr *,
safi_t, u_char, json_object *);
extern void route_vty_out_overlay(struct vty *vty, struct prefix *p,
struct bgp_info *binfo, int display,
json_object *json);
extern int subgroup_process_announce_selected(struct update_subgroup *subgrp,
struct bgp_info *selected, struct bgp_info *selected,
struct bgp_node *rn, struct bgp_node *rn,
u_int32_t addpath_tx_id); u_int32_t addpath_tx_id);
@ -393,13 +412,32 @@ 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,
safi_t safi, struct prefix *p,
struct prefix_rd *prd);
extern struct bgp_info *bgp_info_new(void); extern struct bgp_info *bgp_info_new(void);
extern void bgp_info_restore(struct bgp_node *, struct bgp_info *); 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

View File

@ -125,126 +125,199 @@ static oid bgp_trap_oid [] = { BGP4MIB, 0 };
static struct in_addr bgp_empty_addr = {.s_addr = 0}; static struct in_addr bgp_empty_addr = {.s_addr = 0};
/* Hook functions. */ /* Hook functions. */
static u_char *bgpVersion (struct variable *, oid [], size_t *, int, static u_char *bgpVersion(struct variable *, oid[], size_t *, int, size_t *,
WriteMethod **);
static u_char *bgpLocalAs(struct variable *, oid[], size_t *, int, size_t *,
WriteMethod **);
static u_char *bgpPeerTable(struct variable *, oid[], size_t *, int, size_t *,
WriteMethod **);
static u_char *bgpRcvdPathAttrTable(struct variable *, oid[], size_t *, int,
size_t *, WriteMethod **);
static u_char *bgpIdentifier(struct variable *, oid[], size_t *, int, size_t *,
WriteMethod **);
static u_char *bgp4PathAttrTable(struct variable *, oid[], size_t *, int,
size_t *, WriteMethod **); size_t *, WriteMethod **);
static u_char *bgpLocalAs (struct variable *, oid [], size_t *,
int, size_t *, WriteMethod **);
static u_char *bgpPeerTable (struct variable *, oid [], size_t *,
int, size_t *, WriteMethod **);
static u_char *bgpRcvdPathAttrTable (struct variable *, oid [], size_t *,
int, size_t *, WriteMethod **);
static u_char *bgpIdentifier (struct variable *, oid [], size_t *,
int, size_t *, WriteMethod **);
static u_char *bgp4PathAttrTable (struct variable *, oid [], size_t *,
int, size_t *, WriteMethod **);
/* static u_char *bgpTraps (); */ /* static u_char *bgpTraps (); */
static struct variable bgp_variables[] = static struct variable bgp_variables[] = {
{
/* BGP version. */ /* BGP version. */
{BGPVERSION, OCTET_STRING, RONLY, bgpVersion, {BGPVERSION, OCTET_STRING, RONLY, bgpVersion, 1, {1}},
1, {1}},
/* BGP local AS. */ /* BGP local AS. */
{BGPLOCALAS, INTEGER, RONLY, bgpLocalAs, {BGPLOCALAS, INTEGER, RONLY, bgpLocalAs, 1, {2}},
1, {2}},
/* BGP peer table. */ /* BGP peer table. */
{BGPPEERIDENTIFIER, IPADDRESS, RONLY, bgpPeerTable, {BGPPEERIDENTIFIER, IPADDRESS, RONLY, bgpPeerTable, 3, {3, 1, 1}},
3, {3, 1, 1}}, {BGPPEERSTATE, INTEGER, RONLY, bgpPeerTable, 3, {3, 1, 2}},
{BGPPEERSTATE, INTEGER, RONLY, bgpPeerTable, {BGPPEERADMINSTATUS, INTEGER, RWRITE, bgpPeerTable, 3, {3, 1, 3}},
3, {3, 1, 2}}, {BGPPEERNEGOTIATEDVERSION,
{BGPPEERADMINSTATUS, INTEGER, RWRITE, bgpPeerTable, INTEGER32,
3, {3, 1, 3}}, RONLY,
{BGPPEERNEGOTIATEDVERSION, INTEGER32, RONLY, bgpPeerTable, bgpPeerTable,
3, {3, 1, 4}}, 3,
{BGPPEERLOCALADDR, IPADDRESS, RONLY, bgpPeerTable, {3, 1, 4}},
3, {3, 1, 5}}, {BGPPEERLOCALADDR, IPADDRESS, RONLY, bgpPeerTable, 3, {3, 1, 5}},
{BGPPEERLOCALPORT, INTEGER, RONLY, bgpPeerTable, {BGPPEERLOCALPORT, INTEGER, RONLY, bgpPeerTable, 3, {3, 1, 6}},
3, {3, 1, 6}}, {BGPPEERREMOTEADDR, IPADDRESS, RONLY, bgpPeerTable, 3, {3, 1, 7}},
{BGPPEERREMOTEADDR, IPADDRESS, RONLY, bgpPeerTable, {BGPPEERREMOTEPORT, INTEGER, RONLY, bgpPeerTable, 3, {3, 1, 8}},
3, {3, 1, 7}}, {BGPPEERREMOTEAS, INTEGER, RONLY, bgpPeerTable, 3, {3, 1, 9}},
{BGPPEERREMOTEPORT, INTEGER, RONLY, bgpPeerTable, {BGPPEERINUPDATES, COUNTER32, RONLY, bgpPeerTable, 3, {3, 1, 10}},
3, {3, 1, 8}}, {BGPPEEROUTUPDATES, COUNTER32, RONLY, bgpPeerTable, 3, {3, 1, 11}},
{BGPPEERREMOTEAS, INTEGER, RONLY, bgpPeerTable, {BGPPEERINTOTALMESSAGES, COUNTER32, RONLY, bgpPeerTable, 3, {3, 1, 12}},
3, {3, 1, 9}}, {BGPPEEROUTTOTALMESSAGES,
{BGPPEERINUPDATES, COUNTER32, RONLY, bgpPeerTable, COUNTER32,
3, {3, 1, 10}}, RONLY,
{BGPPEEROUTUPDATES, COUNTER32, RONLY, bgpPeerTable, bgpPeerTable,
3, {3, 1, 11}}, 3,
{BGPPEERINTOTALMESSAGES, COUNTER32, RONLY, bgpPeerTable, {3, 1, 13}},
3, {3, 1, 12}}, {BGPPEERLASTERROR, OCTET_STRING, RONLY, bgpPeerTable, 3, {3, 1, 14}},
{BGPPEEROUTTOTALMESSAGES, COUNTER32, RONLY, bgpPeerTable, {BGPPEERFSMESTABLISHEDTRANSITIONS,
3, {3, 1, 13}}, COUNTER32,
{BGPPEERLASTERROR, OCTET_STRING, RONLY, bgpPeerTable, RONLY,
3, {3, 1, 14}}, bgpPeerTable,
{BGPPEERFSMESTABLISHEDTRANSITIONS, COUNTER32, RONLY, bgpPeerTable, 3,
3, {3, 1, 15}}, {3, 1, 15}},
{BGPPEERFSMESTABLISHEDTIME, GAUGE32, RONLY, bgpPeerTable, {BGPPEERFSMESTABLISHEDTIME,
3, {3, 1, 16}}, GAUGE32,
{BGPPEERCONNECTRETRYINTERVAL, INTEGER, RWRITE, bgpPeerTable, RONLY,
3, {3, 1, 17}}, bgpPeerTable,
{BGPPEERHOLDTIME, INTEGER, RONLY, bgpPeerTable, 3,
3, {3, 1, 18}}, {3, 1, 16}},
{BGPPEERKEEPALIVE, INTEGER, RONLY, bgpPeerTable, {BGPPEERCONNECTRETRYINTERVAL,
3, {3, 1, 19}}, INTEGER,
{BGPPEERHOLDTIMECONFIGURED, INTEGER, RWRITE, bgpPeerTable, RWRITE,
3, {3, 1, 20}}, bgpPeerTable,
{BGPPEERKEEPALIVECONFIGURED, INTEGER, RWRITE, bgpPeerTable, 3,
3, {3, 1, 21}}, {3, 1, 17}},
{BGPPEERMINROUTEADVERTISEMENTINTERVAL, INTEGER, RWRITE, bgpPeerTable, {BGPPEERHOLDTIME, INTEGER, RONLY, bgpPeerTable, 3, {3, 1, 18}},
3, {3, 1, 23}}, {BGPPEERKEEPALIVE, INTEGER, RONLY, bgpPeerTable, 3, {3, 1, 19}},
{BGPPEERINUPDATEELAPSEDTIME, GAUGE32, RONLY, bgpPeerTable, {BGPPEERHOLDTIMECONFIGURED,
3, {3, 1, 24}}, INTEGER,
RWRITE,
bgpPeerTable,
3,
{3, 1, 20}},
{BGPPEERKEEPALIVECONFIGURED,
INTEGER,
RWRITE,
bgpPeerTable,
3,
{3, 1, 21}},
{BGPPEERMINROUTEADVERTISEMENTINTERVAL,
INTEGER,
RWRITE,
bgpPeerTable,
3,
{3, 1, 23}},
{BGPPEERINUPDATEELAPSEDTIME,
GAUGE32,
RONLY,
bgpPeerTable,
3,
{3, 1, 24}},
/* BGP identifier. */ /* BGP identifier. */
{BGPIDENTIFIER, IPADDRESS, RONLY, bgpIdentifier, {BGPIDENTIFIER, IPADDRESS, RONLY, bgpIdentifier, 1, {4}},
1, {4}},
/* BGP received path attribute table. */ /* BGP received path attribute table. */
{BGPPATHATTRPEER, IPADDRESS, RONLY, bgpRcvdPathAttrTable, {BGPPATHATTRPEER, IPADDRESS, RONLY, bgpRcvdPathAttrTable, 3, {5, 1, 1}},
3, {5, 1, 1}}, {BGPPATHATTRDESTNETWORK,
{BGPPATHATTRDESTNETWORK, IPADDRESS, RONLY, bgpRcvdPathAttrTable, IPADDRESS,
3, {5, 1, 2}}, RONLY,
{BGPPATHATTRORIGIN, INTEGER, RONLY, bgpRcvdPathAttrTable, bgpRcvdPathAttrTable,
3, {5, 1, 3}}, 3,
{BGPPATHATTRASPATH, OCTET_STRING, RONLY, bgpRcvdPathAttrTable, {5, 1, 2}},
3, {5, 1, 4}}, {BGPPATHATTRORIGIN, INTEGER, RONLY, bgpRcvdPathAttrTable, 3, {5, 1, 3}},
{BGPPATHATTRNEXTHOP, IPADDRESS, RONLY, bgpRcvdPathAttrTable, {BGPPATHATTRASPATH,
3, {5, 1, 5}}, OCTET_STRING,
{BGPPATHATTRINTERASMETRIC, INTEGER32, RONLY, bgpRcvdPathAttrTable, RONLY,
3, {5, 1, 6}}, bgpRcvdPathAttrTable,
3,
{5, 1, 4}},
{BGPPATHATTRNEXTHOP,
IPADDRESS,
RONLY,
bgpRcvdPathAttrTable,
3,
{5, 1, 5}},
{BGPPATHATTRINTERASMETRIC,
INTEGER32,
RONLY,
bgpRcvdPathAttrTable,
3,
{5, 1, 6}},
/* BGP-4 received path attribute table. */ /* BGP-4 received path attribute table. */
{BGP4PATHATTRPEER, IPADDRESS, RONLY, bgp4PathAttrTable, {BGP4PATHATTRPEER, IPADDRESS, RONLY, bgp4PathAttrTable, 3, {6, 1, 1}},
3, {6, 1, 1}}, {BGP4PATHATTRIPADDRPREFIXLEN,
{BGP4PATHATTRIPADDRPREFIXLEN, INTEGER, RONLY, bgp4PathAttrTable, INTEGER,
3, {6, 1, 2}}, RONLY,
{BGP4PATHATTRIPADDRPREFIX, IPADDRESS, RONLY, bgp4PathAttrTable, bgp4PathAttrTable,
3, {6, 1, 3}}, 3,
{BGP4PATHATTRORIGIN, INTEGER, RONLY, bgp4PathAttrTable, {6, 1, 2}},
3, {6, 1, 4}}, {BGP4PATHATTRIPADDRPREFIX,
{BGP4PATHATTRASPATHSEGMENT, OCTET_STRING, RONLY, bgp4PathAttrTable, IPADDRESS,
3, {6, 1, 5}}, RONLY,
{BGP4PATHATTRNEXTHOP, IPADDRESS, RONLY, bgp4PathAttrTable, bgp4PathAttrTable,
3, {6, 1, 6}}, 3,
{BGP4PATHATTRMULTIEXITDISC, INTEGER, RONLY, bgp4PathAttrTable, {6, 1, 3}},
3, {6, 1, 7}}, {BGP4PATHATTRORIGIN, INTEGER, RONLY, bgp4PathAttrTable, 3, {6, 1, 4}},
{BGP4PATHATTRLOCALPREF, INTEGER, RONLY, bgp4PathAttrTable, {BGP4PATHATTRASPATHSEGMENT,
3, {6, 1, 8}}, OCTET_STRING,
{BGP4PATHATTRATOMICAGGREGATE, INTEGER, RONLY, bgp4PathAttrTable, RONLY,
3, {6, 1, 9}}, bgp4PathAttrTable,
{BGP4PATHATTRAGGREGATORAS, INTEGER, RONLY, bgp4PathAttrTable, 3,
3, {6, 1, 10}}, {6, 1, 5}},
{BGP4PATHATTRAGGREGATORADDR, IPADDRESS, RONLY, bgp4PathAttrTable, {BGP4PATHATTRNEXTHOP,
3, {6, 1, 11}}, IPADDRESS,
{BGP4PATHATTRCALCLOCALPREF, INTEGER, RONLY, bgp4PathAttrTable, RONLY,
3, {6, 1, 12}}, bgp4PathAttrTable,
{BGP4PATHATTRBEST, INTEGER, RONLY, bgp4PathAttrTable, 3,
3, {6, 1, 13}}, {6, 1, 6}},
{BGP4PATHATTRUNKNOWN, OCTET_STRING, RONLY, bgp4PathAttrTable, {BGP4PATHATTRMULTIEXITDISC,
3, {6, 1, 14}}, INTEGER,
RONLY,
bgp4PathAttrTable,
3,
{6, 1, 7}},
{BGP4PATHATTRLOCALPREF,
INTEGER,
RONLY,
bgp4PathAttrTable,
3,
{6, 1, 8}},
{BGP4PATHATTRATOMICAGGREGATE,
INTEGER,
RONLY,
bgp4PathAttrTable,
3,
{6, 1, 9}},
{BGP4PATHATTRAGGREGATORAS,
INTEGER,
RONLY,
bgp4PathAttrTable,
3,
{6, 1, 10}},
{BGP4PATHATTRAGGREGATORADDR,
IPADDRESS,
RONLY,
bgp4PathAttrTable,
3,
{6, 1, 11}},
{BGP4PATHATTRCALCLOCALPREF,
INTEGER,
RONLY,
bgp4PathAttrTable,
3,
{6, 1, 12}},
{BGP4PATHATTRBEST, INTEGER, RONLY, bgp4PathAttrTable, 3, {6, 1, 13}},
{BGP4PATHATTRUNKNOWN,
OCTET_STRING,
RONLY,
bgp4PathAttrTable,
3,
{6, 1, 14}},
}; };
static u_char * static u_char *bgpVersion(struct variable *v, oid name[], size_t *length,
bgpVersion (struct variable *v, oid name[], size_t *length, int exact, int exact, size_t *var_len,
size_t *var_len, WriteMethod **write_method) WriteMethod **write_method)
{ {
static u_char version; static u_char version;
@ -260,9 +333,9 @@ bgpVersion (struct variable *v, oid name[], size_t *length, int exact,
return (u_char *)&version; return (u_char *)&version;
} }
static u_char * static u_char *bgpLocalAs(struct variable *v, oid name[], size_t *length,
bgpLocalAs (struct variable *v, oid name[], size_t *length, int exact, size_t *var_len,
int exact, size_t *var_len, WriteMethod **write_method) WriteMethod **write_method)
{ {
struct bgp *bgp; struct bgp *bgp;
@ -278,8 +351,7 @@ bgpLocalAs (struct variable *v, oid name[], size_t *length,
return SNMP_INTEGER(bgp->as); return SNMP_INTEGER(bgp->as);
} }
static struct peer * static struct peer *peer_lookup_addr_ipv4(struct in_addr *src)
peer_lookup_addr_ipv4 (struct in_addr *src)
{ {
struct bgp *bgp; struct bgp *bgp;
struct peer *peer; struct peer *peer;
@ -291,11 +363,9 @@ peer_lookup_addr_ipv4 (struct in_addr *src)
if (!bgp) if (!bgp)
return NULL; return NULL;
for (ALL_LIST_ELEMENTS_RO (bgp->peer, node, peer)) for (ALL_LIST_ELEMENTS_RO(bgp->peer, node, peer)) {
{
ret = inet_pton(AF_INET, peer->host, &addr); ret = inet_pton(AF_INET, peer->host, &addr);
if (ret > 0) if (ret > 0) {
{
if (IPV4_ADDR_SAME(&addr, src)) if (IPV4_ADDR_SAME(&addr, src))
return peer; return peer;
} }
@ -303,8 +373,7 @@ peer_lookup_addr_ipv4 (struct in_addr *src)
return NULL; return NULL;
} }
static struct peer * static struct peer *bgp_peer_lookup_next(struct in_addr *src)
bgp_peer_lookup_next (struct in_addr *src)
{ {
struct bgp *bgp; struct bgp *bgp;
struct peer *peer; struct peer *peer;
@ -319,15 +388,12 @@ bgp_peer_lookup_next (struct in_addr *src)
if (!bgp) if (!bgp)
return NULL; return NULL;
for (ALL_LIST_ELEMENTS_RO (bgp->peer, node, peer)) for (ALL_LIST_ELEMENTS_RO(bgp->peer, node, peer)) {
{
ret = inet_pton(AF_INET, peer->host, &su.sin.sin_addr); ret = inet_pton(AF_INET, peer->host, &su.sin.sin_addr);
if (ret > 0) if (ret > 0) {
{
p = &su.sin.sin_addr; p = &su.sin.sin_addr;
if (ntohl (p->s_addr) > ntohl (src->s_addr)) if (ntohl(p->s_addr) > ntohl(src->s_addr)) {
{
src->s_addr = p->s_addr; src->s_addr = p->s_addr;
return peer; return peer;
} }
@ -339,16 +405,15 @@ bgp_peer_lookup_next (struct in_addr *src)
/* 1.3.6.1.2.1.15.3.1.x = 10 */ /* 1.3.6.1.2.1.15.3.1.x = 10 */
#define PEERTAB_NAMELEN 10 #define PEERTAB_NAMELEN 10
static struct peer * static struct peer *bgpPeerTable_lookup(struct variable *v, oid name[],
bgpPeerTable_lookup (struct variable *v, oid name[], size_t *length, size_t *length, struct in_addr *addr,
struct in_addr *addr, int exact) int exact)
{ {
struct peer *peer = NULL; struct peer *peer = NULL;
size_t namelen = v ? v->namelen : PEERTAB_NAMELEN; size_t namelen = v ? v->namelen : PEERTAB_NAMELEN;
int len; int len;
if (exact) if (exact) {
{
/* Check the length. */ /* Check the length. */
if (*length - namelen != sizeof(struct in_addr)) if (*length - namelen != sizeof(struct in_addr))
return NULL; return NULL;
@ -357,11 +422,10 @@ bgpPeerTable_lookup (struct variable *v, oid name[], size_t *length,
peer = peer_lookup_addr_ipv4(addr); peer = peer_lookup_addr_ipv4(addr);
return peer; return peer;
} } else {
else
{
len = *length - namelen; len = *length - namelen;
if (len > 4) len = 4; if (len > 4)
len = 4;
oid2in_addr(name + namelen, len, addr); oid2in_addr(name + namelen, len, addr);
@ -379,21 +443,18 @@ bgpPeerTable_lookup (struct variable *v, oid name[], size_t *length,
} }
/* BGP write methods. */ /* BGP write methods. */
static int static int write_bgpPeerTable(int action, u_char *var_val, u_char var_val_type,
write_bgpPeerTable (int action, u_char *var_val, size_t var_val_len, u_char *statP, oid *name,
u_char var_val_type, size_t var_val_len, size_t length)
u_char *statP, oid *name, size_t length)
{ {
struct in_addr addr; struct in_addr addr;
struct peer *peer; struct peer *peer;
long intval; long intval;
if (var_val_type != ASN_INTEGER) if (var_val_type != ASN_INTEGER) {
{
return SNMP_ERR_WRONGTYPE; return SNMP_ERR_WRONGTYPE;
} }
if (var_val_len != sizeof (long)) if (var_val_len != sizeof(long)) {
{
return SNMP_ERR_WRONGLENGTH; return SNMP_ERR_WRONGLENGTH;
} }
@ -408,11 +469,10 @@ write_bgpPeerTable (int action, u_char *var_val,
if (action != SNMP_MSG_INTERNAL_SET_COMMIT) if (action != SNMP_MSG_INTERNAL_SET_COMMIT)
return SNMP_ERR_NOERROR; return SNMP_ERR_NOERROR;
zlog_info ("%s: SNMP write .%ld = %ld", zlog_info("%s: SNMP write .%ld = %ld", peer->host,
peer->host, (long)name[PEERTAB_NAMELEN - 1], intval); (long)name[PEERTAB_NAMELEN - 1], intval);
switch (name[PEERTAB_NAMELEN - 1]) switch (name[PEERTAB_NAMELEN - 1]) {
{
case BGPPEERADMINSTATUS: case BGPPEERADMINSTATUS:
#define BGP_PeerAdmin_stop 1 #define BGP_PeerAdmin_stop 1
#define BGP_PeerAdmin_start 2 #define BGP_PeerAdmin_start 2
@ -446,9 +506,9 @@ write_bgpPeerTable (int action, u_char *var_val,
return SNMP_ERR_NOERROR; return SNMP_ERR_NOERROR;
} }
static u_char * static u_char *bgpPeerTable(struct variable *v, oid name[], size_t *length,
bgpPeerTable (struct variable *v, oid name[], size_t *length, int exact, size_t *var_len,
int exact, size_t *var_len, WriteMethod **write_method) WriteMethod **write_method)
{ {
static struct in_addr addr; static struct in_addr addr;
struct peer *peer; struct peer *peer;
@ -462,8 +522,7 @@ bgpPeerTable (struct variable *v, oid name[], size_t *length,
if (!peer) if (!peer)
return NULL; return NULL;
switch (v->magic) switch (v->magic) {
{
case BGPPEERIDENTIFIER: case BGPPEERIDENTIFIER:
return SNMP_IPADDRESS(peer->remote_id); return SNMP_IPADDRESS(peer->remote_id);
break; break;
@ -490,7 +549,8 @@ bgpPeerTable (struct variable *v, oid name[], size_t *length,
break; break;
case BGPPEERLOCALPORT: case BGPPEERLOCALPORT:
if (peer->su_local) if (peer->su_local)
return SNMP_INTEGER (ntohs (peer->su_local->sin.sin_port)); return SNMP_INTEGER(
ntohs(peer->su_local->sin.sin_port));
else else
return SNMP_INTEGER(0); return SNMP_INTEGER(0);
break; break;
@ -502,7 +562,8 @@ bgpPeerTable (struct variable *v, oid name[], size_t *length,
break; break;
case BGPPEERREMOTEPORT: case BGPPEERREMOTEPORT:
if (peer->su_remote) if (peer->su_remote)
return SNMP_INTEGER (ntohs (peer->su_remote->sin.sin_port)); return SNMP_INTEGER(
ntohs(peer->su_remote->sin.sin_port));
else else
return SNMP_INTEGER(0); return SNMP_INTEGER(0);
break; break;
@ -523,17 +584,16 @@ bgpPeerTable (struct variable *v, oid name[], size_t *length,
case BGPPEEROUTTOTALMESSAGES: case BGPPEEROUTTOTALMESSAGES:
return SNMP_INTEGER(peer->open_out + peer->update_out return SNMP_INTEGER(peer->open_out + peer->update_out
+ peer->keepalive_out + peer->notify_out + peer->keepalive_out + peer->notify_out
+ peer->refresh_out + peer->dynamic_cap_out); + peer->refresh_out
+ peer->dynamic_cap_out);
break; break;
case BGPPEERLASTERROR: case BGPPEERLASTERROR: {
{
static u_char lasterror[2]; static u_char lasterror[2];
lasterror[0] = peer->notify.code; lasterror[0] = peer->notify.code;
lasterror[1] = peer->notify.subcode; lasterror[1] = peer->notify.subcode;
*var_len = 2; *var_len = 2;
return (u_char *)&lasterror; return (u_char *)&lasterror;
} } break;
break;
case BGPPEERFSMESTABLISHEDTRANSITIONS: case BGPPEERFSMESTABLISHEDTRANSITIONS:
return SNMP_INTEGER(peer->established); return SNMP_INTEGER(peer->established);
break; break;
@ -584,9 +644,9 @@ bgpPeerTable (struct variable *v, oid name[], size_t *length,
return NULL; return NULL;
} }
static u_char * static u_char *bgpIdentifier(struct variable *v, oid name[], size_t *length,
bgpIdentifier (struct variable *v, oid name[], size_t *length, int exact, size_t *var_len,
int exact, size_t *var_len, WriteMethod **write_method) WriteMethod **write_method)
{ {
struct bgp *bgp; struct bgp *bgp;
@ -601,9 +661,9 @@ bgpIdentifier (struct variable *v, oid name[], size_t *length,
return SNMP_IPADDRESS(bgp->router_id); return SNMP_IPADDRESS(bgp->router_id);
} }
static u_char * static u_char *bgpRcvdPathAttrTable(struct variable *v, oid name[],
bgpRcvdPathAttrTable (struct variable *v, oid name[], size_t *length, size_t *length, int exact, size_t *var_len,
int exact, size_t *var_len, WriteMethod **write_method) WriteMethod **write_method)
{ {
/* Received Path Attribute Table. This table contains, one entry /* Received Path Attribute Table. This table contains, one entry
per path to a network, path attributes received from all peers per path to a network, path attributes received from all peers
@ -612,9 +672,9 @@ bgpRcvdPathAttrTable (struct variable *v, oid name[], size_t *length,
return NULL; return NULL;
} }
static struct bgp_info * static struct bgp_info *bgp4PathAttrLookup(struct variable *v, oid name[],
bgp4PathAttrLookup (struct variable *v, oid name[], size_t *length, size_t *length, struct bgp *bgp,
struct bgp *bgp, struct prefix_ipv4 *addr, int exact) struct prefix_ipv4 *addr, int exact)
{ {
oid *offset; oid *offset;
int offsetlen; int offsetlen;
@ -627,11 +687,9 @@ bgp4PathAttrLookup (struct variable *v, oid name[], size_t *length,
sockunion_init(&su); sockunion_init(&su);
#define BGP_PATHATTR_ENTRY_OFFSET \ #define BGP_PATHATTR_ENTRY_OFFSET (IN_ADDR_SIZE + 1 + IN_ADDR_SIZE)
(IN_ADDR_SIZE + 1 + IN_ADDR_SIZE)
if (exact) if (exact) {
{
if (*length - v->namelen != BGP_PATHATTR_ENTRY_OFFSET) if (*length - v->namelen != BGP_PATHATTR_ENTRY_OFFSET)
return NULL; return NULL;
@ -651,25 +709,21 @@ bgp4PathAttrLookup (struct variable *v, oid name[], size_t *length,
/* Lookup node. */ /* Lookup node. */
rn = bgp_node_lookup(bgp->rib[AFI_IP][SAFI_UNICAST], rn = bgp_node_lookup(bgp->rib[AFI_IP][SAFI_UNICAST],
(struct prefix *)addr); (struct prefix *)addr);
if (rn) if (rn) {
{
bgp_unlock_node(rn); bgp_unlock_node(rn);
for (binfo = rn->info; binfo; binfo = binfo->next) for (binfo = rn->info; binfo; binfo = binfo->next)
if (sockunion_same(&binfo->peer->su, &su)) if (sockunion_same(&binfo->peer->su, &su))
return binfo; return binfo;
} }
} } else {
else
{
offset = name + v->namelen; offset = name + v->namelen;
offsetlen = *length - v->namelen; offsetlen = *length - v->namelen;
len = offsetlen; len = offsetlen;
if (offsetlen == 0) if (offsetlen == 0)
rn = bgp_table_top(bgp->rib[AFI_IP][SAFI_UNICAST]); rn = bgp_table_top(bgp->rib[AFI_IP][SAFI_UNICAST]);
else else {
{
if (len > IN_ADDR_SIZE) if (len > IN_ADDR_SIZE)
len = IN_ADDR_SIZE; len = IN_ADDR_SIZE;
@ -690,51 +744,52 @@ bgp4PathAttrLookup (struct variable *v, oid name[], size_t *length,
offsetlen--; offsetlen--;
} }
if (offsetlen > 0) if (offsetlen > 0) {
{
len = offsetlen; len = offsetlen;
if (len > IN_ADDR_SIZE) if (len > IN_ADDR_SIZE)
len = IN_ADDR_SIZE; len = IN_ADDR_SIZE;
oid2in_addr(offset, len, &paddr); oid2in_addr(offset, len, &paddr);
} } else
else
paddr.s_addr = 0; paddr.s_addr = 0;
if (!rn) if (!rn)
return NULL; return NULL;
do do {
{
min = NULL; min = NULL;
for (binfo = rn->info; binfo; binfo = binfo->next) for (binfo = rn->info; binfo; binfo = binfo->next) {
{
if (binfo->peer->su.sin.sin_family == AF_INET if (binfo->peer->su.sin.sin_family == AF_INET
&& ntohl(paddr.s_addr) && ntohl(paddr.s_addr)
< ntohl (binfo->peer->su.sin.sin_addr.s_addr)) < ntohl(binfo->peer->su.sin
{ .sin_addr
if (min) .s_addr)) {
{ if (min) {
if (ntohl (binfo->peer->su.sin.sin_addr.s_addr) if (ntohl(binfo->peer->su.sin
< ntohl (min->peer->su.sin.sin_addr.s_addr)) .sin_addr
.s_addr)
< ntohl(min->peer->su.sin
.sin_addr
.s_addr))
min = binfo; min = binfo;
} } else
else
min = binfo; min = binfo;
} }
} }
if (min) if (min) {
{ *length =
*length = v->namelen + BGP_PATHATTR_ENTRY_OFFSET; v->namelen + BGP_PATHATTR_ENTRY_OFFSET;
offset = name + v->namelen; offset = name + v->namelen;
oid_copy_addr (offset, &rn->p.u.prefix4, IN_ADDR_SIZE); oid_copy_addr(offset, &rn->p.u.prefix4,
IN_ADDR_SIZE);
offset += IN_ADDR_SIZE; offset += IN_ADDR_SIZE;
*offset = rn->p.prefixlen; *offset = rn->p.prefixlen;
offset++; offset++;
oid_copy_addr (offset, &min->peer->su.sin.sin_addr, oid_copy_addr(offset,
&min->peer->su.sin.sin_addr,
IN_ADDR_SIZE); IN_ADDR_SIZE);
addr->prefix = rn->p.u.prefix4; addr->prefix = rn->p.u.prefix4;
addr->prefixlen = rn->p.prefixlen; addr->prefixlen = rn->p.prefixlen;
@ -745,15 +800,14 @@ bgp4PathAttrLookup (struct variable *v, oid name[], size_t *length,
} }
paddr.s_addr = 0; paddr.s_addr = 0;
} } while ((rn = bgp_route_next(rn)) != NULL);
while ((rn = bgp_route_next (rn)) != NULL);
} }
return NULL; return NULL;
} }
static u_char * static u_char *bgp4PathAttrTable(struct variable *v, oid name[], size_t *length,
bgp4PathAttrTable (struct variable *v, oid name[], size_t *length, int exact, size_t *var_len,
int exact, size_t *var_len, WriteMethod **write_method) WriteMethod **write_method)
{ {
struct bgp *bgp; struct bgp *bgp;
struct bgp_info *binfo; struct bgp_info *binfo;
@ -772,8 +826,7 @@ bgp4PathAttrTable (struct variable *v, oid name[], size_t *length,
if (!binfo) if (!binfo)
return NULL; return NULL;
switch (v->magic) switch (v->magic) {
{
case BGP4PATHATTRPEER: /* 1 */ case BGP4PATHATTRPEER: /* 1 */
return SNMP_IPADDRESS(binfo->peer->su.sin.sin_addr); return SNMP_IPADDRESS(binfo->peer->su.sin.sin_addr);
break; break;
@ -802,21 +855,17 @@ bgp4PathAttrTable (struct variable *v, oid name[], size_t *length,
return SNMP_INTEGER(1); return SNMP_INTEGER(1);
break; break;
case BGP4PATHATTRAGGREGATORAS: /* 10 */ case BGP4PATHATTRAGGREGATORAS: /* 10 */
if (binfo->attr->extra) return SNMP_INTEGER(binfo->attr->aggregator_as);
return SNMP_INTEGER (binfo->attr->extra->aggregator_as);
else
return SNMP_INTEGER (0);
break; break;
case BGP4PATHATTRAGGREGATORADDR: /* 11 */ case BGP4PATHATTRAGGREGATORADDR: /* 11 */
if (binfo->attr->extra) return SNMP_IPADDRESS(binfo->attr->aggregator_addr);
return SNMP_IPADDRESS (binfo->attr->extra->aggregator_addr);
else
return SNMP_INTEGER (0);
break; break;
case BGP4PATHATTRCALCLOCALPREF: /* 12 */ case BGP4PATHATTRCALCLOCALPREF: /* 12 */
return SNMP_INTEGER(-1); return SNMP_INTEGER(-1);
break; break;
case BGP4PATHATTRBEST: /* 13 */ case BGP4PATHATTRBEST: /* 13 */
/* $FRR indent$ */
/* clang-format off */
#define BGP4_PathAttrBest_false 1 #define BGP4_PathAttrBest_false 1
#define BGP4_PathAttrBest_true 2 #define BGP4_PathAttrBest_true 2
if (CHECK_FLAG(binfo->flags, BGP_INFO_SELECTED)) if (CHECK_FLAG(binfo->flags, BGP_INFO_SELECTED))
@ -833,14 +882,10 @@ bgp4PathAttrTable (struct variable *v, oid name[], size_t *length,
} }
/* BGP Traps. */ /* BGP Traps. */
static struct trap_object bgpTrapList[] = static struct trap_object bgpTrapList[] = {{3, {3, 1, BGPPEERLASTERROR}},
{ {3, {3, 1, BGPPEERSTATE}}};
{3, {3, 1, BGPPEERLASTERROR}},
{3, {3, 1, BGPPEERSTATE}}
};
static int static int bgpTrapEstablished(struct peer *peer)
bgpTrapEstablished (struct peer *peer)
{ {
int ret; int ret;
struct in_addr addr; struct in_addr addr;
@ -853,16 +898,14 @@ bgpTrapEstablished (struct peer *peer)
oid_copy_addr(index, &addr, IN_ADDR_SIZE); oid_copy_addr(index, &addr, IN_ADDR_SIZE);
smux_trap(bgp_variables, sizeof bgp_variables / sizeof(struct variable), smux_trap(bgp_variables, sizeof bgp_variables / sizeof(struct variable),
bgp_trap_oid, sizeof bgp_trap_oid / sizeof (oid), bgp_trap_oid, sizeof bgp_trap_oid / sizeof(oid), bgp_oid,
bgp_oid, sizeof bgp_oid / sizeof (oid), sizeof bgp_oid / sizeof(oid), index, IN_ADDR_SIZE,
index, IN_ADDR_SIZE,
bgpTrapList, sizeof bgpTrapList / sizeof(struct trap_object), bgpTrapList, sizeof bgpTrapList / sizeof(struct trap_object),
BGPESTABLISHED); BGPESTABLISHED);
return 0; return 0;
} }
static int static int bgpTrapBackwardTransition(struct peer *peer)
bgpTrapBackwardTransition (struct peer *peer)
{ {
int ret; int ret;
struct in_addr addr; struct in_addr addr;
@ -875,24 +918,21 @@ bgpTrapBackwardTransition (struct peer *peer)
oid_copy_addr(index, &addr, IN_ADDR_SIZE); oid_copy_addr(index, &addr, IN_ADDR_SIZE);
smux_trap(bgp_variables, sizeof bgp_variables / sizeof(struct variable), smux_trap(bgp_variables, sizeof bgp_variables / sizeof(struct variable),
bgp_trap_oid, sizeof bgp_trap_oid / sizeof (oid), bgp_trap_oid, sizeof bgp_trap_oid / sizeof(oid), bgp_oid,
bgp_oid, sizeof bgp_oid / sizeof (oid), sizeof bgp_oid / sizeof(oid), index, IN_ADDR_SIZE,
index, IN_ADDR_SIZE,
bgpTrapList, sizeof bgpTrapList / sizeof(struct trap_object), bgpTrapList, sizeof bgpTrapList / sizeof(struct trap_object),
BGPBACKWARDTRANSITION); BGPBACKWARDTRANSITION);
return 0; return 0;
} }
static int static int bgp_snmp_init(struct thread_master *tm)
bgp_snmp_init (struct thread_master *tm)
{ {
smux_init(tm); smux_init(tm);
REGISTER_MIB("mibII/bgp", bgp_variables, variable, bgp_oid); REGISTER_MIB("mibII/bgp", bgp_variables, variable, bgp_oid);
return 0; return 0;
} }
static int static int bgp_snmp_module_init(void)
bgp_snmp_module_init (void)
{ {
hook_register(peer_established, bgpTrapEstablished); hook_register(peer_established, bgpTrapEstablished);
hook_register(peer_backward_transition, bgpTrapBackwardTransition); hook_register(peer_backward_transition, bgpTrapBackwardTransition);
@ -900,9 +940,6 @@ bgp_snmp_module_init (void)
return 0; return 0;
} }
FRR_MODULE_SETUP( FRR_MODULE_SETUP(.name = "bgpd_snmp", .version = FRR_VERSION,
.name = "bgpd_snmp",
.version = FRR_VERSION,
.description = "bgpd AgentX SNMP module", .description = "bgpd AgentX SNMP module",
.init = bgp_snmp_module_init .init = bgp_snmp_module_init)
)

View File

@ -30,20 +30,17 @@
#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;
} }
@ -53,11 +50,9 @@ bgp_table_unlock (struct bgp_table *rt)
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;
} }
@ -66,8 +61,8 @@ bgp_table_finish (struct bgp_table **rt)
/* /*
* 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));
@ -77,8 +72,7 @@ bgp_node_create (route_table_delegate_t *delegate, struct route_table *table)
/* /*
* 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;
@ -90,16 +84,13 @@ bgp_node_destroy (route_table_delegate_t *delegate,
* 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;

View File

@ -21,10 +21,10 @@
#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;
@ -35,8 +35,7 @@ struct bgp_table
uint64_t version; uint64_t version;
}; };
struct bgp_node struct bgp_node {
{
/* /*
* CAUTION * CAUTION
* *
@ -53,7 +52,7 @@ struct bgp_node
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;
@ -68,8 +67,7 @@ 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;
@ -85,8 +83,7 @@ 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,8 +93,7 @@ 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,8 +103,7 @@ 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,8 +113,7 @@ 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);
} }
@ -127,8 +121,7 @@ bgp_node_parent_nolock (struct bgp_node *node)
/* /*
* 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));
} }
@ -158,8 +151,7 @@ bgp_table_top (const struct bgp_table *const 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)));
} }
@ -167,8 +159,8 @@ bgp_route_next (struct bgp_node *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;
@ -180,8 +172,8 @@ bgp_route_next_until (struct bgp_node *node, struct bgp_node *limit)
/* /*
* 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));
} }
@ -198,8 +190,7 @@ bgp_node_lookup (const struct bgp_table *const table, struct prefix *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)));
} }
@ -207,8 +198,8 @@ bgp_lock_node (struct bgp_node *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));
} }
@ -219,8 +210,8 @@ bgp_node_match (const struct bgp_table *table, struct prefix *p)
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));
} }
/* /*
@ -229,12 +220,11 @@ bgp_node_match_ipv4 (const struct bgp_table *table, struct in_addr *addr)
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);
} }
@ -242,8 +232,8 @@ bgp_table_count (const struct bgp_table *const 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));
} }
@ -251,8 +241,8 @@ bgp_table_get_next (const struct bgp_table *table, struct prefix *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;
@ -262,8 +252,7 @@ bgp_table_iter_init (bgp_table_iter_t * iter, struct bgp_table *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));
} }
@ -271,8 +260,7 @@ bgp_table_iter_next (bgp_table_iter_t * 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);
@ -282,8 +270,7 @@ bgp_table_iter_cleanup (bgp_table_iter_t * iter)
/* /*
* 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);
} }
@ -291,8 +278,7 @@ bgp_table_iter_pause (bgp_table_iter_t * 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);
} }
@ -300,22 +286,19 @@ bgp_table_iter_is_done (bgp_table_iter_t * 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;
} }

File diff suppressed because it is too large Load Diff

View File

@ -31,44 +31,32 @@
#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;
@ -81,13 +69,11 @@ 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;
@ -100,8 +86,7 @@ struct bpacket
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
@ -116,8 +101,7 @@ struct bpacket_queue
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;
@ -169,11 +153,9 @@ struct update_group
/* /*
* 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;
@ -225,11 +207,11 @@ struct update_subgroup
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
* split
* from, if any. * 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;
@ -271,27 +253,25 @@ struct update_subgroup
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, \
value); \
} while (0) } 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;
@ -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)--)
@ -345,7 +324,8 @@ struct updwalk_context
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)
@ -364,30 +344,28 @@ struct updwalk_context
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 extern int update_subgroup_trigger_merge_check(struct update_subgroup *,
update_subgroup_check_merge (struct update_subgroup *, const char *);
extern int
update_subgroup_trigger_merge_check (struct update_subgroup *,
int force); int force);
extern void update_group_policy_update (struct bgp *bgp, extern void update_group_policy_update(struct bgp *bgp, bgp_policy_type_e ptype,
bgp_policy_type_e ptype, const char *pname, const char *pname, int route_update,
int route_update, int start_event); int start_event);
extern void update_group_af_walk(struct bgp *bgp, afi_t afi, safi_t safi, extern void update_group_af_walk(struct bgp *bgp, afi_t afi, safi_t safi,
updgrp_walkcb cb, void *ctx); updgrp_walkcb cb, void *ctx);
extern void update_group_walk(struct bgp *bgp, 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 void update_group_periodic_merge(struct bgp *bgp);
extern int update_group_refresh_default_originate_route_map (struct thread *thread); extern int
update_group_refresh_default_originate_route_map(struct thread *thread);
extern void update_group_start_advtimer(struct bgp *bgp); 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,
@ -401,8 +379,7 @@ 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);
@ -422,22 +399,18 @@ extern struct stream *bpacket_reformat_for_peer (struct bpacket *pkt,
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 stream *s, struct attr *attr);
struct attr *attr); extern void subgroup_default_update_packet(struct update_subgroup *subgrp,
extern void struct attr *attr,
subgroup_default_update_packet (struct update_subgroup *subgrp, struct peer *from);
struct attr *attr, struct peer *from);
extern void subgroup_default_withdraw_packet(struct update_subgroup *subgrp); 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,
safi_t safi, struct vty *vty,
uint64_t id);
extern void update_group_show_advertised(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);
@ -447,10 +420,9 @@ extern void update_group_show_packet_queue (struct bgp *bgp, afi_t afi,
extern void subgroup_announce_route(struct update_subgroup *subgrp); extern void subgroup_announce_route(struct update_subgroup *subgrp);
extern void subgroup_announce_all(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);
@ -462,23 +434,18 @@ extern struct bgp_adj_out *bgp_adj_out_alloc (struct update_subgroup *subgrp,
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 extern void bgp_adj_out_set_subgroup(struct bgp_node *rn,
bgp_adj_out_set_subgroup (struct bgp_node *rn,
struct update_subgroup *subgrp, struct update_subgroup *subgrp,
struct attr *attr, struct bgp_info *binfo); struct attr *attr, struct bgp_info *binfo);
extern void extern void bgp_adj_out_unset_subgroup(struct bgp_node *rn,
bgp_adj_out_unset_subgroup (struct bgp_node *rn,
struct update_subgroup *subgrp, struct update_subgroup *subgrp,
char withdraw, char withdraw, u_int32_t addpath_tx_id);
u_int32_t addpath_tx_id); void subgroup_announce_table(struct update_subgroup *subgrp,
void
subgroup_announce_table (struct update_subgroup *subgrp,
struct bgp_table *table); struct bgp_table *table);
extern void extern void subgroup_trigger_write(struct update_subgroup *subgrp);
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);
@ -492,8 +459,7 @@ 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)
{ {
/* /*
@ -511,8 +477,7 @@ 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,14 +487,12 @@ 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,14 +504,12 @@ 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);
@ -579,8 +540,8 @@ update_subgroup_set_needs_refresh (struct update_subgroup *subgrp, int value)
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;
@ -595,14 +556,12 @@ 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));
@ -612,13 +571,11 @@ bgp_announce_peer (struct peer *peer)
/** /**
* 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) ||
!BGP_ADV_FIFO_EMPTY (&subgrp->sync->withdraw) ||
!BGP_ADV_FIFO_EMPTY (&subgrp->sync->withdraw_low))
{ {
if (!BGP_ADV_FIFO_EMPTY(&subgrp->sync->update)
|| !BGP_ADV_FIFO_EMPTY(&subgrp->sync->withdraw)
|| !BGP_ADV_FIFO_EMPTY(&subgrp->sync->withdraw_low)) {
return 0; return 0;
} }

View File

@ -55,8 +55,8 @@
* PRIVATE FUNCTIONS * PRIVATE FUNCTIONS
********************/ ********************/
static inline struct bgp_adj_out * static inline struct bgp_adj_out *adj_lookup(struct bgp_node *rn,
adj_lookup (struct bgp_node *rn, struct update_subgroup *subgrp, struct update_subgroup *subgrp,
u_int32_t addpath_tx_id) u_int32_t addpath_tx_id)
{ {
struct bgp_adj_out *adj; struct bgp_adj_out *adj;
@ -75,19 +75,13 @@ adj_lookup (struct bgp_node *rn, struct update_subgroup *subgrp,
/* update-groups that do not support addpath will pass 0 for /* update-groups that do not support addpath will pass 0 for
* addpath_tx_id so do not both matching against it */ * addpath_tx_id so do not both matching against it */
for (adj = rn->adj_out; adj; adj = adj->next) for (adj = rn->adj_out; adj; adj = adj->next) {
{ if (adj->subgroup == subgrp) {
if (adj->subgroup == subgrp) if (addpath_capable) {
{ if (adj->addpath_tx_id == addpath_tx_id) {
if (addpath_capable)
{
if (adj->addpath_tx_id == addpath_tx_id)
{
break; break;
} }
} } else {
else
{
break; break;
} }
} }
@ -96,16 +90,14 @@ adj_lookup (struct bgp_node *rn, struct update_subgroup *subgrp,
return adj; return adj;
} }
static void static void adj_free(struct bgp_adj_out *adj)
adj_free (struct bgp_adj_out *adj)
{ {
TAILQ_REMOVE(&(adj->subgroup->adjq), adj, subgrp_adj_train); TAILQ_REMOVE(&(adj->subgroup->adjq), adj, subgrp_adj_train);
SUBGRP_DECR_STAT(adj->subgroup, adj_count); SUBGRP_DECR_STAT(adj->subgroup, adj_count);
XFREE(MTYPE_BGP_ADJ_OUT, adj); XFREE(MTYPE_BGP_ADJ_OUT, adj);
} }
static int static int group_announce_route_walkcb(struct update_group *updgrp, void *arg)
group_announce_route_walkcb (struct update_group *updgrp, void *arg)
{ {
struct updwalk_context *ctx = arg; struct updwalk_context *ctx = arg;
struct update_subgroup *subgrp; struct update_subgroup *subgrp;
@ -129,67 +121,74 @@ group_announce_route_walkcb (struct update_group *updgrp, void *arg)
* walk the entire prefix table for those subgroups when the * walk the entire prefix table for those subgroups when the
* coalesce timer fires. * coalesce timer fires.
*/ */
if (!subgrp->t_coalesce) if (!subgrp->t_coalesce) {
{
/* An update-group that uses addpath */ /* An update-group that uses addpath */
if (addpath_capable) if (addpath_capable) {
{ /* Look through all of the paths we have
/* Look through all of the paths we have advertised for this rn and * advertised for this rn and
* send a withdraw for the ones that are no longer present */ * send a withdraw for the ones that are no
for (adj = ctx->rn->adj_out; adj; adj = adj_next) * longer present */
{ for (adj = ctx->rn->adj_out; adj;
adj = adj_next) {
adj_next = adj->next; adj_next = adj->next;
if (adj->subgroup == subgrp) if (adj->subgroup == subgrp) {
{ for (ri = ctx->rn->info; ri;
for (ri = ctx->rn->info; ri; ri = ri->next) ri = ri->next) {
{ if (ri->addpath_tx_id
if (ri->addpath_tx_id == adj->addpath_tx_id) == adj->addpath_tx_id) {
{
break; break;
} }
} }
if (!ri) if (!ri) {
{ subgroup_process_announce_selected(
subgroup_process_announce_selected (subgrp, NULL, ctx->rn, adj->addpath_tx_id); subgrp, NULL,
ctx->rn,
adj->addpath_tx_id);
} }
} }
} }
for (ri = ctx->rn->info; ri; ri = ri->next) for (ri = ctx->rn->info; ri; ri = ri->next) {
{
/* Skip the bestpath for now */ /* Skip the bestpath for now */
if (ri == ctx->ri) if (ri == ctx->ri)
continue; continue;
subgroup_process_announce_selected (subgrp, ri, ctx->rn, ri->addpath_tx_id); subgroup_process_announce_selected(
subgrp, ri, ctx->rn,
ri->addpath_tx_id);
} }
/* Process the bestpath last so the "show [ip] bgp neighbor x.x.x.x advertised" /* Process the bestpath last so the "show [ip]
* output shows the attributes from the bestpath */ * bgp neighbor x.x.x.x advertised"
* output shows the attributes from the bestpath
*/
if (ctx->ri) if (ctx->ri)
subgroup_process_announce_selected (subgrp, ctx->ri, ctx->rn, ctx->ri->addpath_tx_id); subgroup_process_announce_selected(
subgrp, ctx->ri, ctx->rn,
ctx->ri->addpath_tx_id);
} }
/* An update-group that does not use addpath */ /* An update-group that does not use addpath */
else else {
{ if (ctx->ri) {
if (ctx->ri) subgroup_process_announce_selected(
{ subgrp, ctx->ri, ctx->rn,
subgroup_process_announce_selected (subgrp, ctx->ri, ctx->rn, ctx->ri->addpath_tx_id); ctx->ri->addpath_tx_id);
} } else {
else /* Find the addpath_tx_id of the path we
{ * had advertised and
/* Find the addpath_tx_id of the path we had advertised and
* send a withdraw */ * send a withdraw */
for (adj = ctx->rn->adj_out; adj; adj = adj_next) for (adj = ctx->rn->adj_out; adj;
{ adj = adj_next) {
adj_next = adj->next; adj_next = adj->next;
if (adj->subgroup == subgrp) if (adj->subgroup == subgrp) {
{ subgroup_process_announce_selected(
subgroup_process_announce_selected (subgrp, NULL, ctx->rn, adj->addpath_tx_id); subgrp, NULL,
ctx->rn,
adj->addpath_tx_id);
} }
} }
} }
@ -200,9 +199,8 @@ group_announce_route_walkcb (struct update_group *updgrp, void *arg)
return UPDWALK_CONTINUE; return UPDWALK_CONTINUE;
} }
static void static void subgrp_show_adjq_vty(struct update_subgroup *subgrp,
subgrp_show_adjq_vty (struct update_subgroup *subgrp, struct vty *vty, struct vty *vty, u_int8_t flags)
u_int8_t flags)
{ {
struct bgp_table *table; struct bgp_table *table;
struct bgp_adj_out *adj; struct bgp_adj_out *adj;
@ -222,40 +220,42 @@ subgrp_show_adjq_vty (struct update_subgroup *subgrp, struct vty *vty,
for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn))
for (adj = rn->adj_out; adj; adj = adj->next) for (adj = rn->adj_out; adj; adj = adj->next)
if (adj->subgroup == subgrp) if (adj->subgroup == subgrp) {
{ if (header1) {
if (header1) vty_out(vty,
{ "BGP table version is %" PRIu64
vty_outln (vty, ", local router ID is %s\n",
"BGP table version is %" PRIu64 ", local router ID is %s", table->version,
table->version,inet_ntoa(bgp->router_id)); inet_ntoa(bgp->router_id));
vty_outln (vty, BGP_SHOW_SCODE_HEADER, VTYNL); vty_out(vty, BGP_SHOW_SCODE_HEADER);
vty_outln (vty, BGP_SHOW_OCODE_HEADER, VTYNL); vty_out(vty, BGP_SHOW_OCODE_HEADER);
header1 = 0; header1 = 0;
} }
if (header2) if (header2) {
{ vty_out(vty, BGP_SHOW_HEADER);
vty_outln (vty, BGP_SHOW_HEADER);
header2 = 0; header2 = 0;
} }
if ((flags & UPDWALK_FLAGS_ADVQUEUE) && adj->adv && adj->adv->baa) if ((flags & UPDWALK_FLAGS_ADVQUEUE) && adj->adv
{ && adj->adv->baa) {
route_vty_out_tmp (vty, &rn->p, adj->adv->baa->attr, SUBGRP_SAFI (subgrp), 0, NULL); route_vty_out_tmp(vty, &rn->p,
adj->adv->baa->attr,
SUBGRP_SAFI(subgrp),
0, NULL);
output_count++; output_count++;
} }
if ((flags & UPDWALK_FLAGS_ADVERTISED) && adj->attr) if ((flags & UPDWALK_FLAGS_ADVERTISED)
{ && adj->attr) {
route_vty_out_tmp (vty, &rn->p, adj->attr, SUBGRP_SAFI (subgrp), 0, NULL); route_vty_out_tmp(
vty, &rn->p, adj->attr,
SUBGRP_SAFI(subgrp), 0, NULL);
output_count++; output_count++;
} }
} }
if (output_count != 0) if (output_count != 0)
vty_outln (vty, "%sTotal number of prefixes %ld", vty_out(vty, "\nTotal number of prefixes %ld\n", output_count);
VTYNL, output_count);
} }
static int static int updgrp_show_adj_walkcb(struct update_group *updgrp, void *arg)
updgrp_show_adj_walkcb (struct update_group *updgrp, void *arg)
{ {
struct updwalk_context *ctx = arg; struct updwalk_context *ctx = arg;
struct update_subgroup *subgrp; struct update_subgroup *subgrp;
@ -266,15 +266,14 @@ updgrp_show_adj_walkcb (struct update_group *updgrp, void *arg)
{ {
if (ctx->subgrp_id && (ctx->subgrp_id != subgrp->id)) if (ctx->subgrp_id && (ctx->subgrp_id != subgrp->id))
continue; continue;
vty_outln (vty, "update group %" PRIu64 ", subgroup %" PRIu64 "", updgrp->id, vty_out(vty, "update group %" PRIu64 ", subgroup %" PRIu64 "\n",
subgrp->id); updgrp->id, subgrp->id);
subgrp_show_adjq_vty(subgrp, vty, ctx->flags); subgrp_show_adjq_vty(subgrp, vty, ctx->flags);
} }
return UPDWALK_CONTINUE; return UPDWALK_CONTINUE;
} }
static void static void updgrp_show_adj(struct bgp *bgp, afi_t afi, safi_t safi,
updgrp_show_adj (struct bgp *bgp, afi_t afi, safi_t safi,
struct vty *vty, uint64_t id, u_int8_t flags) struct vty *vty, uint64_t id, u_int8_t flags)
{ {
struct updwalk_context ctx; struct updwalk_context ctx;
@ -286,27 +285,29 @@ updgrp_show_adj (struct bgp *bgp, afi_t afi, safi_t safi,
update_group_af_walk(bgp, afi, safi, updgrp_show_adj_walkcb, &ctx); update_group_af_walk(bgp, afi, safi, updgrp_show_adj_walkcb, &ctx);
} }
static int static int subgroup_coalesce_timer(struct thread *thread)
subgroup_coalesce_timer (struct thread *thread)
{ {
struct update_subgroup *subgrp; struct update_subgroup *subgrp;
subgrp = THREAD_ARG(thread); subgrp = THREAD_ARG(thread);
if (bgp_debug_update(NULL, NULL, subgrp->update_group, 0)) if (bgp_debug_update(NULL, NULL, subgrp->update_group, 0))
zlog_debug ("u%" PRIu64 ":s%" PRIu64 " announcing routes upon coalesce timer expiry", zlog_debug("u%" PRIu64 ":s%" PRIu64
" announcing routes upon coalesce timer expiry",
(SUBGRP_UPDGRP(subgrp))->id, subgrp->id); (SUBGRP_UPDGRP(subgrp))->id, subgrp->id);
subgrp->t_coalesce = NULL; subgrp->t_coalesce = NULL;
subgrp->v_coalesce = 0; subgrp->v_coalesce = 0;
subgroup_announce_route(subgrp); subgroup_announce_route(subgrp);
/* While the announce_route() may kick off the route advertisement timer for /* While the announce_route() may kick off the route advertisement timer
* the members of the subgroup, we'd like to send the initial updates much * for
* faster (i.e., without enforcing MRAI). Also, if there were no routes to * the members of the subgroup, we'd like to send the initial updates
* much
* faster (i.e., without enforcing MRAI). Also, if there were no routes
* to
* announce, this is the method currently employed to trigger the EOR. * announce, this is the method currently employed to trigger the EOR.
*/ */
if (!bgp_update_delay_active(SUBGRP_INST(subgrp))) if (!bgp_update_delay_active(SUBGRP_INST(subgrp))) {
{
struct peer_af *paf; struct peer_af *paf;
struct peer *peer; struct peer *peer;
@ -321,8 +322,7 @@ subgroup_coalesce_timer (struct thread *thread)
return 0; return 0;
} }
static int static int update_group_announce_walkcb(struct update_group *updgrp, void *arg)
update_group_announce_walkcb (struct update_group *updgrp, void *arg)
{ {
struct update_subgroup *subgrp; struct update_subgroup *subgrp;
@ -334,8 +334,8 @@ update_group_announce_walkcb (struct update_group *updgrp, void *arg)
return UPDWALK_CONTINUE; return UPDWALK_CONTINUE;
} }
static int static int update_group_announce_rrc_walkcb(struct update_group *updgrp,
update_group_announce_rrc_walkcb (struct update_group *updgrp, void *arg) void *arg)
{ {
struct update_subgroup *subgrp; struct update_subgroup *subgrp;
afi_t afi; afi_t afi;
@ -347,8 +347,7 @@ update_group_announce_rrc_walkcb (struct update_group *updgrp, void *arg)
peer = UPDGRP_PEER(updgrp); peer = UPDGRP_PEER(updgrp);
/* Only announce if this is a group of route-reflector-clients */ /* Only announce if this is a group of route-reflector-clients */
if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_REFLECTOR_CLIENT)) if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_REFLECTOR_CLIENT)) {
{
UPDGRP_FOREACH_SUBGRP(updgrp, subgrp) UPDGRP_FOREACH_SUBGRP(updgrp, subgrp)
{ {
subgroup_announce_all(subgrp); subgroup_announce_all(subgrp);
@ -366,16 +365,15 @@ update_group_announce_rrc_walkcb (struct update_group *updgrp, void *arg)
* Allocate an adj-out object. Do proper initialization of its fields, * Allocate an adj-out object. Do proper initialization of its fields,
* primarily its association with the subgroup and the prefix. * primarily its association with the subgroup and the prefix.
*/ */
struct bgp_adj_out * struct bgp_adj_out *bgp_adj_out_alloc(struct update_subgroup *subgrp,
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)
{ {
struct bgp_adj_out *adj; struct bgp_adj_out *adj;
adj = XCALLOC(MTYPE_BGP_ADJ_OUT, sizeof(struct bgp_adj_out)); adj = XCALLOC(MTYPE_BGP_ADJ_OUT, sizeof(struct bgp_adj_out));
adj->subgroup = subgrp; adj->subgroup = subgrp;
if (rn) if (rn) {
{
BGP_ADJ_OUT_ADD(rn, adj); BGP_ADJ_OUT_ADD(rn, adj);
bgp_lock_node(rn); bgp_lock_node(rn);
adj->rn = rn; adj->rn = rn;
@ -401,8 +399,7 @@ bgp_advertise_clean_subgroup (struct update_subgroup *subgrp,
baa = adv->baa; baa = adv->baa;
next = NULL; next = NULL;
if (baa) if (baa) {
{
fhead = &subgrp->sync->update; fhead = &subgrp->sync->update;
/* Unlink myself from advertise attribute FIFO. */ /* Unlink myself from advertise attribute FIFO. */
@ -413,8 +410,7 @@ bgp_advertise_clean_subgroup (struct update_subgroup *subgrp,
/* Unintern BGP advertise attribute. */ /* Unintern BGP advertise attribute. */
bgp_advertise_unintern(subgrp->hash, baa); bgp_advertise_unintern(subgrp->hash, baa);
} } else
else
fhead = &subgrp->sync->withdraw; fhead = &subgrp->sync->withdraw;
@ -428,10 +424,9 @@ bgp_advertise_clean_subgroup (struct update_subgroup *subgrp,
return next; return next;
} }
void void bgp_adj_out_set_subgroup(struct bgp_node *rn,
bgp_adj_out_set_subgroup (struct bgp_node *rn, struct update_subgroup *subgrp, struct attr *attr,
struct update_subgroup *subgrp, struct bgp_info *binfo)
struct attr *attr, struct bgp_info *binfo)
{ {
struct bgp_adj_out *adj = NULL; struct bgp_adj_out *adj = NULL;
struct bgp_advertise *adv; struct bgp_advertise *adv;
@ -442,8 +437,7 @@ bgp_adj_out_set_subgroup (struct bgp_node *rn,
/* Look for adjacency information. */ /* Look for adjacency information. */
adj = adj_lookup(rn, subgrp, binfo->addpath_tx_id); adj = adj_lookup(rn, subgrp, binfo->addpath_tx_id);
if (!adj) if (!adj) {
{
adj = bgp_adj_out_alloc(subgrp, rn, binfo->addpath_tx_id); adj = bgp_adj_out_alloc(subgrp, rn, binfo->addpath_tx_id);
if (!adj) if (!adj)
return; return;
@ -471,8 +465,7 @@ bgp_adj_out_set_subgroup (struct bgp_node *rn,
* If the update adv list is empty, trigger the member peers' * If the update adv list is empty, trigger the member peers'
* mrai timers so the socket writes can happen. * mrai timers so the socket writes can happen.
*/ */
if (BGP_ADV_FIFO_EMPTY (&subgrp->sync->update)) if (BGP_ADV_FIFO_EMPTY(&subgrp->sync->update)) {
{
struct peer_af *paf; struct peer_af *paf;
SUBGRP_FOREACH_PEER(subgrp, paf) SUBGRP_FOREACH_PEER(subgrp, paf)
@ -490,10 +483,8 @@ bgp_adj_out_set_subgroup (struct bgp_node *rn,
* the "neighbor x.x.x.x default-originate" default and need to clear * the "neighbor x.x.x.x default-originate" default and need to clear
* bgp_adj_out for the 0.0.0.0/0 route in the BGP table. * bgp_adj_out for the 0.0.0.0/0 route in the BGP table.
*/ */
void void bgp_adj_out_unset_subgroup(struct bgp_node *rn,
bgp_adj_out_unset_subgroup (struct bgp_node *rn, struct update_subgroup *subgrp, char withdraw,
struct update_subgroup *subgrp,
char withdraw,
u_int32_t addpath_tx_id) u_int32_t addpath_tx_id)
{ {
struct bgp_adj_out *adj; struct bgp_adj_out *adj;
@ -504,14 +495,12 @@ bgp_adj_out_unset_subgroup (struct bgp_node *rn,
return; return;
/* Lookup existing adjacency */ /* Lookup existing adjacency */
if ((adj = adj_lookup (rn, subgrp, addpath_tx_id)) != NULL) if ((adj = adj_lookup(rn, subgrp, addpath_tx_id)) != NULL) {
{
/* Clean up previous advertisement. */ /* Clean up previous advertisement. */
if (adj->adv) if (adj->adv)
bgp_advertise_clean_subgroup(subgrp, adj); bgp_advertise_clean_subgroup(subgrp, adj);
if (adj->attr && withdraw) if (adj->attr && withdraw) {
{
/* We need advertisement structure. */ /* We need advertisement structure. */
adj->adv = bgp_advertise_new(); adj->adv = bgp_advertise_new();
adv = adj->adv; adv = adj->adv;
@ -524,15 +513,15 @@ bgp_adj_out_unset_subgroup (struct bgp_node *rn,
else else
trigger_write = 0; trigger_write = 0;
/* Add to synchronization entry for withdraw announcement. */ /* Add to synchronization entry for withdraw
* announcement. */
BGP_ADV_FIFO_ADD(&subgrp->sync->withdraw, &adv->fifo); BGP_ADV_FIFO_ADD(&subgrp->sync->withdraw, &adv->fifo);
/* Schedule packet write, if FIFO is getting its first entry. */ /* Schedule packet write, if FIFO is getting its first
* entry. */
if (trigger_write) if (trigger_write)
subgroup_trigger_write(subgrp); subgroup_trigger_write(subgrp);
} } else {
else
{
/* Remove myself from adjacency. */ /* Remove myself from adjacency. */
BGP_ADJ_OUT_DEL(rn, adj); BGP_ADJ_OUT_DEL(rn, adj);
@ -546,8 +535,7 @@ bgp_adj_out_unset_subgroup (struct bgp_node *rn,
subgrp->version = max(subgrp->version, rn->version); subgrp->version = max(subgrp->version, rn->version);
} }
void void bgp_adj_out_remove_subgroup(struct bgp_node *rn, struct bgp_adj_out *adj,
bgp_adj_out_remove_subgroup (struct bgp_node *rn, struct bgp_adj_out *adj,
struct update_subgroup *subgrp) struct update_subgroup *subgrp)
{ {
if (adj->attr) if (adj->attr)
@ -564,8 +552,7 @@ bgp_adj_out_remove_subgroup (struct bgp_node *rn, struct bgp_adj_out *adj,
* Go through all the routes and clean up the adj/adv structures corresponding * Go through all the routes and clean up the adj/adv structures corresponding
* to the subgroup. * to the subgroup.
*/ */
void void subgroup_clear_table(struct update_subgroup *subgrp)
subgroup_clear_table (struct update_subgroup *subgrp)
{ {
struct bgp_adj_out *aout, *taout; struct bgp_adj_out *aout, *taout;
@ -580,14 +567,12 @@ subgroup_clear_table (struct update_subgroup *subgrp)
/* /*
* subgroup_announce_table * subgroup_announce_table
*/ */
void void subgroup_announce_table(struct update_subgroup *subgrp,
subgroup_announce_table (struct update_subgroup *subgrp,
struct bgp_table *table) struct bgp_table *table)
{ {
struct bgp_node *rn; struct bgp_node *rn;
struct bgp_info *ri; struct bgp_info *ri;
struct attr attr; struct attr attr;
struct attr_extra extra;
struct peer *peer; struct peer *peer;
afi_t afi; afi_t afi;
safi_t safi; safi_t safi;
@ -598,28 +583,31 @@ subgroup_announce_table (struct update_subgroup *subgrp,
safi = SUBGRP_SAFI(subgrp); safi = SUBGRP_SAFI(subgrp);
addpath_capable = bgp_addpath_encode_tx(peer, afi, safi); addpath_capable = bgp_addpath_encode_tx(peer, afi, safi);
if (safi == SAFI_LABELED_UNICAST)
safi = SAFI_UNICAST;
if (!table) if (!table)
table = peer->bgp->rib[afi][safi]; table = peer->bgp->rib[afi][safi];
if (safi != SAFI_MPLS_VPN if (safi != SAFI_MPLS_VPN && safi != SAFI_ENCAP && safi != SAFI_EVPN
&& safi != SAFI_ENCAP && CHECK_FLAG(peer->af_flags[afi][safi],
&& safi != SAFI_EVPN PEER_FLAG_DEFAULT_ORIGINATE))
&& CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE))
subgroup_default_originate(subgrp, 0); subgroup_default_originate(subgrp, 0);
/* It's initialized in bgp_announce_check() */
attr.extra = &extra;
for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn))
for (ri = rn->info; ri; ri = ri->next) for (ri = rn->info; ri; ri = ri->next)
if (CHECK_FLAG (ri->flags, BGP_INFO_SELECTED) || if (CHECK_FLAG(ri->flags, BGP_INFO_SELECTED)
(addpath_capable && bgp_addpath_tx_path(peer, afi, safi, ri))) || (addpath_capable
{ && bgp_addpath_tx_path(peer, afi, safi, ri))) {
if (subgroup_announce_check (rn, ri, subgrp, &rn->p, &attr)) if (subgroup_announce_check(rn, ri, subgrp,
bgp_adj_out_set_subgroup (rn, subgrp, &attr, ri); &rn->p, &attr))
bgp_adj_out_set_subgroup(rn, subgrp,
&attr, ri);
else else
bgp_adj_out_unset_subgroup (rn, subgrp, 1, ri->addpath_tx_id); bgp_adj_out_unset_subgroup(
rn, subgrp, 1,
ri->addpath_tx_id);
} }
/* /*
@ -643,32 +631,29 @@ subgroup_announce_table (struct update_subgroup *subgrp,
* *
* Refresh all routes out to a subgroup. * Refresh all routes out to a subgroup.
*/ */
void void subgroup_announce_route(struct update_subgroup *subgrp)
subgroup_announce_route (struct update_subgroup *subgrp)
{ {
struct bgp_node *rn; struct bgp_node *rn;
struct bgp_table *table; struct bgp_table *table;
struct peer *onlypeer; struct peer *onlypeer;
if (update_subgroup_needs_refresh (subgrp)) if (update_subgroup_needs_refresh(subgrp)) {
{
update_subgroup_set_needs_refresh(subgrp, 0); update_subgroup_set_needs_refresh(subgrp, 0);
} }
/* /*
* First update is deferred until ORF or ROUTE-REFRESH is received * First update is deferred until ORF or ROUTE-REFRESH is received
*/ */
onlypeer = ((SUBGRP_PCOUNT (subgrp) == 1) ? onlypeer = ((SUBGRP_PCOUNT(subgrp) == 1) ? (SUBGRP_PFIRST(subgrp))->peer
(SUBGRP_PFIRST (subgrp))->peer : NULL); : NULL);
if (onlypeer && if (onlypeer && CHECK_FLAG(onlypeer->af_sflags[SUBGRP_AFI(subgrp)]
CHECK_FLAG (onlypeer-> [SUBGRP_SAFI(subgrp)],
af_sflags[SUBGRP_AFI (subgrp)][SUBGRP_SAFI (subgrp)],
PEER_STATUS_ORF_WAIT_REFRESH)) PEER_STATUS_ORF_WAIT_REFRESH))
return; return;
if (SUBGRP_SAFI (subgrp) != SAFI_MPLS_VPN && if (SUBGRP_SAFI(subgrp) != SAFI_MPLS_VPN
SUBGRP_SAFI (subgrp) != SAFI_ENCAP && && SUBGRP_SAFI(subgrp) != SAFI_ENCAP
SUBGRP_SAFI (subgrp) != SAFI_EVPN) && SUBGRP_SAFI(subgrp) != SAFI_EVPN)
subgroup_announce_table(subgrp, NULL); subgroup_announce_table(subgrp, NULL);
else else
for (rn = bgp_table_top(update_subgroup_rib(subgrp)); rn; for (rn = bgp_table_top(update_subgroup_rib(subgrp)); rn;
@ -677,8 +662,7 @@ subgroup_announce_route (struct update_subgroup *subgrp)
subgroup_announce_table(subgrp, table); subgroup_announce_table(subgrp, table);
} }
void void subgroup_default_originate(struct update_subgroup *subgrp, int withdraw)
subgroup_default_originate (struct update_subgroup *subgrp, int withdraw)
{ {
struct bgp *bgp; struct bgp *bgp;
struct attr attr; struct attr attr;
@ -711,45 +695,39 @@ subgroup_default_originate (struct update_subgroup *subgrp, int withdraw)
if (afi == AFI_IP) if (afi == AFI_IP)
str2prefix("0.0.0.0/0", &p); str2prefix("0.0.0.0/0", &p);
else if (afi == AFI_IP6) else if (afi == AFI_IP6) {
{
struct attr_extra *ae = attr.extra;
str2prefix("::/0", &p); str2prefix("::/0", &p);
/* IPv6 global nexthop must be included. */ /* IPv6 global nexthop must be included. */
ae->mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL; attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
/* If the peer is on shared nextwork and we have link-local /* If the peer is on shared nextwork and we have link-local
nexthop set it. */ nexthop set it. */
if (peer->shared_network if (peer->shared_network
&& !IN6_IS_ADDR_UNSPECIFIED(&peer->nexthop.v6_local)) && !IN6_IS_ADDR_UNSPECIFIED(&peer->nexthop.v6_local))
ae->mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL; attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL;
} }
if (peer->default_rmap[afi][safi].name) if (peer->default_rmap[afi][safi].name) {
{
SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_DEFAULT); SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_DEFAULT);
for (rn = bgp_table_top(bgp->rib[afi][safi]); rn; for (rn = bgp_table_top(bgp->rib[afi][safi]); rn;
rn = bgp_route_next (rn)) rn = bgp_route_next(rn)) {
{ for (ri = rn->info; ri; ri = ri->next) {
for (ri = rn->info; ri; ri = ri->next)
{
struct attr dummy_attr; struct attr dummy_attr;
struct attr_extra dummy_extra;
struct bgp_info info; struct bgp_info info;
/* Provide dummy so the route-map can't modify the attributes */ /* Provide dummy so the route-map can't modify
dummy_attr.extra = &dummy_extra; * the attributes */
bgp_attr_dup(&dummy_attr, ri->attr); bgp_attr_dup(&dummy_attr, ri->attr);
info.peer = ri->peer; info.peer = ri->peer;
info.attr = &dummy_attr; info.attr = &dummy_attr;
ret = ret = route_map_apply(
route_map_apply (peer->default_rmap[afi][safi].map, &rn->p, peer->default_rmap[afi][safi].map,
RMAP_BGP, &info); &rn->p, RMAP_BGP, &info);
/* The route map might have set attributes. If we don't flush them /* The route map might have set attributes. If
* we don't flush them
* here, they will be leaked. */ * here, they will be leaked. */
bgp_attr_flush(&dummy_attr); bgp_attr_flush(&dummy_attr);
if (ret != RMAP_DENYMATCH) if (ret != RMAP_DENYMATCH)
@ -764,34 +742,37 @@ subgroup_default_originate (struct update_subgroup *subgrp, int withdraw)
withdraw = 1; withdraw = 1;
} }
if (withdraw) if (withdraw) {
{
if (CHECK_FLAG(subgrp->sflags, SUBGRP_STATUS_DEFAULT_ORIGINATE)) if (CHECK_FLAG(subgrp->sflags, SUBGRP_STATUS_DEFAULT_ORIGINATE))
subgroup_default_withdraw_packet(subgrp); subgroup_default_withdraw_packet(subgrp);
UNSET_FLAG(subgrp->sflags, SUBGRP_STATUS_DEFAULT_ORIGINATE); UNSET_FLAG(subgrp->sflags, SUBGRP_STATUS_DEFAULT_ORIGINATE);
} } else {
else if (!CHECK_FLAG(subgrp->sflags,
{ SUBGRP_STATUS_DEFAULT_ORIGINATE)) {
if (!CHECK_FLAG (subgrp->sflags, SUBGRP_STATUS_DEFAULT_ORIGINATE)) SET_FLAG(subgrp->sflags,
{ SUBGRP_STATUS_DEFAULT_ORIGINATE);
SET_FLAG (subgrp->sflags, SUBGRP_STATUS_DEFAULT_ORIGINATE);
subgroup_default_update_packet(subgrp, &attr, from); subgroup_default_update_packet(subgrp, &attr, from);
/* The 'neighbor x.x.x.x default-originate' default will act as an /* The 'neighbor x.x.x.x default-originate' default will
* implicit withdraw for any previous UPDATEs sent for 0.0.0.0/0 so * act as an
* clear adj_out for the 0.0.0.0/0 prefix in the BGP table. * implicit withdraw for any previous UPDATEs sent for
* 0.0.0.0/0 so
* clear adj_out for the 0.0.0.0/0 prefix in the BGP
* table.
*/ */
if (afi == AFI_IP) if (afi == AFI_IP)
str2prefix("0.0.0.0/0", &p); str2prefix("0.0.0.0/0", &p);
else else
str2prefix("::/0", &p); str2prefix("::/0", &p);
rn = bgp_afi_node_get (bgp->rib[afi][safi], afi, safi, &p, NULL); rn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi,
bgp_adj_out_unset_subgroup (rn, subgrp, 0, BGP_ADDPATH_TX_ID_FOR_DEFAULT_ORIGINATE); &p, NULL);
bgp_adj_out_unset_subgroup(
rn, subgrp, 0,
BGP_ADDPATH_TX_ID_FOR_DEFAULT_ORIGINATE);
} }
} }
bgp_attr_extra_free (&attr);
aspath_unintern(&aspath); aspath_unintern(&aspath);
} }
@ -803,8 +784,7 @@ subgroup_default_originate (struct update_subgroup *subgrp, int withdraw)
* subgrp->v_coalesce will be set to zero and the normal logic * subgrp->v_coalesce will be set to zero and the normal logic
* prevails. * prevails.
*/ */
void void subgroup_announce_all(struct update_subgroup *subgrp)
subgroup_announce_all (struct update_subgroup *subgrp)
{ {
if (!subgrp) if (!subgrp)
return; return;
@ -812,10 +792,10 @@ subgroup_announce_all (struct update_subgroup *subgrp)
/* /*
* If coalesce timer value is not set, announce routes immediately. * If coalesce timer value is not set, announce routes immediately.
*/ */
if (!subgrp->v_coalesce) if (!subgrp->v_coalesce) {
{
if (bgp_debug_update(NULL, NULL, subgrp->update_group, 0)) if (bgp_debug_update(NULL, NULL, subgrp->update_group, 0))
zlog_debug ("u%" PRIu64 ":s%" PRIu64 " announcing all routes", zlog_debug("u%" PRIu64 ":s%" PRIu64
" announcing all routes",
subgrp->update_group->id, subgrp->id); subgrp->update_group->id, subgrp->id);
subgroup_announce_route(subgrp); subgroup_announce_route(subgrp);
return; return;
@ -824,10 +804,10 @@ subgroup_announce_all (struct update_subgroup *subgrp)
/* /*
* We should wait for the coalesce timer. Arm the timer if not done. * We should wait for the coalesce timer. Arm the timer if not done.
*/ */
if (!subgrp->t_coalesce) if (!subgrp->t_coalesce) {
{ thread_add_timer_msec(bm->master, subgroup_coalesce_timer,
thread_add_timer_msec(bm->master, subgroup_coalesce_timer, subgrp, subgrp, subgrp->v_coalesce,
subgrp->v_coalesce, &subgrp->t_coalesce); &subgrp->t_coalesce);
} }
} }
@ -835,8 +815,7 @@ subgroup_announce_all (struct update_subgroup *subgrp)
* Go through all update subgroups and set up the adv queue for the * Go through all update subgroups and set up the adv queue for the
* input route. * input route.
*/ */
void 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)
{ {
struct updwalk_context ctx; struct updwalk_context ctx;
@ -845,28 +824,24 @@ group_announce_route (struct bgp *bgp, afi_t afi, safi_t safi,
update_group_af_walk(bgp, afi, safi, group_announce_route_walkcb, &ctx); update_group_af_walk(bgp, afi, safi, group_announce_route_walkcb, &ctx);
} }
void void update_group_show_adj_queue(struct bgp *bgp, afi_t afi, safi_t safi,
update_group_show_adj_queue (struct bgp *bgp, afi_t afi, safi_t safi,
struct vty *vty, uint64_t id) struct vty *vty, uint64_t id)
{ {
updgrp_show_adj(bgp, afi, safi, vty, id, UPDWALK_FLAGS_ADVQUEUE); updgrp_show_adj(bgp, afi, safi, vty, id, UPDWALK_FLAGS_ADVQUEUE);
} }
void void update_group_show_advertised(struct bgp *bgp, afi_t afi, safi_t safi,
update_group_show_advertised (struct bgp *bgp, afi_t afi, safi_t safi,
struct vty *vty, uint64_t id) struct vty *vty, uint64_t id)
{ {
updgrp_show_adj(bgp, afi, safi, vty, id, UPDWALK_FLAGS_ADVERTISED); updgrp_show_adj(bgp, afi, safi, vty, id, UPDWALK_FLAGS_ADVERTISED);
} }
void void update_group_announce(struct bgp *bgp)
update_group_announce (struct bgp *bgp)
{ {
update_group_walk(bgp, update_group_announce_walkcb, NULL); update_group_walk(bgp, update_group_announce_walkcb, NULL);
} }
void void update_group_announce_rrclients(struct bgp *bgp)
update_group_announce_rrclients (struct bgp *bgp)
{ {
update_group_walk(bgp, update_group_announce_rrc_walkcb, NULL); update_group_walk(bgp, update_group_announce_rrc_walkcb, NULL);
} }

File diff suppressed because it is too large Load Diff

View File

@ -30,9 +30,9 @@
#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;
@ -48,15 +48,13 @@ show_adj_route_vpn (struct vty *vty, struct peer *peer, struct prefix_rd *prd,
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_outln (vty, "No BGP process is configured"); vty_out(vty, "No BGP process is configured\n");
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();
@ -75,13 +73,11 @@ show_adj_route_vpn (struct vty *vty, struct peer *peer, struct prefix_rd *prd,
} }
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
@ -89,39 +85,49 @@ show_adj_route_vpn (struct vty *vty, struct peer *peer, struct prefix_rd *prd,
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 {
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; 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;
@ -131,70 +137,114 @@ show_adj_route_vpn (struct vty *vty, struct peer *peer, struct prefix_rd *prd,
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,
&rd_as);
else if (type == RD_TYPE_AS4) else if (type == RD_TYPE_AS4)
decode_rd_as4 (pnt + 2, &rd_as); decode_rd_as4(pnt + 2,
&rd_as);
else if (type == RD_TYPE_IP) else if (type == RD_TYPE_IP)
decode_rd_ip (pnt + 2, &rd_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 || type == RD_TYPE_AS4) if (type == RD_TYPE_AS
sprintf (buffer, "%u:%d", rd_as.as, rd_as.val); || type == RD_TYPE_AS4)
else if (type == RD_TYPE_IP) sprintf(buffer,
sprintf (buffer, "%s:%d", inet_ntoa (rd_ip.ip), rd_ip.val); "%u:%d",
json_object_string_add(json_routes, "routeDistinguisher", buffer); rd_as.as,
} rd_as.val);
else else if (type
{ == RD_TYPE_IP)
vty_out (vty, "Route Distinguisher: "); sprintf(buffer,
"%s:%d",
inet_ntoa(
rd_ip.ip),
rd_ip.val);
json_object_string_add(
json_routes,
"routeDistinguisher",
buffer);
} else {
vty_out(vty,
"Route Distinguisher: ");
if (type == RD_TYPE_AS || type == RD_TYPE_AS4) 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) if (use_json) {
{
struct prefix *p; struct prefix *p;
char buf_a[BUFSIZ]; char buf_a[BUFSIZ];
char buf_b[BUFSIZ]; char buf_b[BUFSIZ];
p = &rm->p; p = &rm->p;
sprintf(buf_a, "%s/%d", inet_ntop (p->family, &p->u.prefix, buf_b, BUFSIZ), p->prefixlen); sprintf(buf_a, "%s/%d",
json_object_object_add(json_routes, buf_a, json_array); inet_ntop(p->family, &p->u.prefix,
buf_b, BUFSIZ),
p->prefixlen);
json_object_object_add(json_routes, buf_a,
json_array);
} }
} }
} }
if (use_json) if (use_json) {
{
json_object_object_add(json, "routes", json_routes); json_object_object_add(json, "routes", json_routes);
vty_outln (vty, "%s", vty_out(vty, "%s\n", json_object_to_json_string_ext(
json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY)); json, JSON_C_TO_STRING_PRETTY));
json_object_free(json); json_object_free(json);
} }
return CMD_SUCCESS; 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,15 +28,21 @@ 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
#define BGP_SAFI_WITH_LABEL_CMD_STR "<unicast|multicast|vpn|labeled-unicast>"
#define BGP_SAFI_WITH_LABEL_HELP_STR \
"Address Family modifier\n" \
"Address Family modifier\n" \
"Address Family modifier\n" \
"Address Family modifier\n"
extern void bgp_vty_init(void); extern void bgp_vty_init(void);
extern const char *afi_safi_print(afi_t, safi_t); extern const char *afi_safi_print(afi_t, safi_t);
extern const char *afi_safi_json(afi_t, safi_t); extern const char *afi_safi_json(afi_t, safi_t);
@ -45,22 +51,23 @@ 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,21 +21,13 @@
#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 *))
#define BGP_IFINDICES_BUF_SIZE (8 * sizeof (unsigned int))
#define BGP_LABEL_BUF_SIZE (8 * sizeof (unsigned int))
extern struct stream *bgp_nexthop_buf;
extern struct stream *bgp_ifindices_buf;
extern struct stream *bgp_label_buf;
extern void bgp_zebra_init(struct thread_master *master); extern void bgp_zebra_init(struct thread_master *master);
extern void bgp_zebra_destroy(void); extern void bgp_zebra_destroy(void);
extern int bgp_if_update_all(void); extern int bgp_if_update_all(void);
extern int bgp_config_write_maxpaths (struct vty *, struct bgp *, afi_t, extern int bgp_config_write_maxpaths(struct vty *, struct bgp *, afi_t, safi_t,
safi_t, int *);
extern int bgp_config_write_redistribute (struct vty *, struct bgp *, afi_t, safi_t,
int *); 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 *, extern void bgp_zebra_announce(struct bgp_node *, struct prefix *,
struct bgp_info *, struct bgp *, afi_t, safi_t); 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_announce_table(struct bgp *, afi_t, safi_t);
@ -47,20 +39,25 @@ extern void bgp_zebra_terminate_radv (struct bgp *bgp, struct peer *peer);
extern void bgp_zebra_instance_register(struct bgp *); extern void bgp_zebra_instance_register(struct bgp *);
extern void bgp_zebra_instance_deregister(struct bgp *); extern void bgp_zebra_instance_deregister(struct bgp *);
extern struct bgp_redist *bgp_redist_lookup (struct bgp *, afi_t, u_char, u_short); extern struct bgp_redist *bgp_redist_lookup(struct bgp *, afi_t, u_char,
u_short);
extern struct bgp_redist *bgp_redist_add(struct bgp *, afi_t, u_char, u_short); extern 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_set(struct bgp *, afi_t, int, u_short);
extern int bgp_redistribute_resend(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_rmap_set(struct bgp_redist *, const char *);
extern int bgp_redistribute_metric_set(struct bgp *, struct bgp_redist *, extern int bgp_redistribute_metric_set(struct bgp *, struct bgp_redist *, afi_t,
afi_t, int, u_int32_t); int, u_int32_t);
extern int bgp_redistribute_unset(struct bgp *, afi_t, int, u_short); 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 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(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_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(struct in6_addr *, ifindex_t,
extern struct interface *if_lookup_by_ipv6_exact (struct in6_addr *, ifindex_t, vrf_id_t); vrf_id_t);
extern struct interface *if_lookup_by_ipv6_exact(struct in6_addr *, ifindex_t,
vrf_id_t);
extern int bgp_zebra_advertise_all_vni(struct bgp *, int);
extern int bgp_zebra_num_connects(void); extern int bgp_zebra_num_connects(void);

File diff suppressed because it is too large Load Diff

View File

@ -33,6 +33,7 @@
#include "linklist.h" #include "linklist.h"
#include "defaults.h" #include "defaults.h"
#include "bgp_memory.h" #include "bgp_memory.h"
#include "bitfield.h"
#define BGP_MAX_HOSTNAME 64 /* Linux max, is larger than most other sys */ #define BGP_MAX_HOSTNAME 64 /* Linux max, is larger than most other sys */
@ -44,11 +45,11 @@ struct bpacket;
/* /*
* Allow the neighbor XXXX remote-as to take internal or external * Allow the neighbor XXXX remote-as to take internal or external
* AS_SPECIFIED is zero to auto-inherit original non-feature/enhancement behavior * AS_SPECIFIED is zero to auto-inherit original non-feature/enhancement
* behavior
* in the system. * in the system.
*/ */
enum { enum { AS_UNSPECIFIED = 0,
AS_UNSPECIFIED = 0,
AS_SPECIFIED, AS_SPECIFIED,
AS_INTERNAL, AS_INTERNAL,
AS_EXTERNAL, AS_EXTERNAL,
@ -60,12 +61,13 @@ typedef u_int16_t as16_t; /* we may still encounter 16 Bit asnums */
typedef u_int16_t bgp_size_t; typedef u_int16_t bgp_size_t;
#define max(a, b) \ #define max(a, b) \
({ __typeof__ (a) _a = (a); \ ({ \
__typeof__(a) _a = (a); \
__typeof__(b) _b = (b); \ __typeof__(b) _b = (b); \
_a > _b ? _a : _b; }) _a > _b ? _a : _b; \
})
enum bgp_af_index enum bgp_af_index {
{
BGP_AF_START, BGP_AF_START,
BGP_AF_IPV4_UNICAST = BGP_AF_START, BGP_AF_IPV4_UNICAST = BGP_AF_START,
BGP_AF_IPV4_MULTICAST, BGP_AF_IPV4_MULTICAST,
@ -81,16 +83,14 @@ enum bgp_af_index
BGP_AF_MAX BGP_AF_MAX
}; };
#define AF_FOREACH(af) \ #define AF_FOREACH(af) for ((af) = BGP_AF_START; (af) < BGP_AF_MAX; (af)++)
for ((af) = BGP_AF_START; (af) < BGP_AF_MAX; (af)++)
#define FOREACH_AFI_SAFI(afi, safi) \ #define FOREACH_AFI_SAFI(afi, 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++)
/* BGP master for system wide configurations and variables. */ /* BGP master for system wide configurations and variables. */
struct bgp_master struct bgp_master {
{
/* BGP instance list. */ /* BGP instance list. */
struct list *bgp; struct list *bgp;
@ -125,6 +125,8 @@ struct bgp_master
/* timer to dampen route map changes */ /* timer to dampen route map changes */
struct thread *t_rmap_update; /* Handle route map updates */ struct thread *t_rmap_update; /* Handle route map updates */
u_int32_t rmap_update_timer; /* Route map update timer */ u_int32_t rmap_update_timer; /* Route map update timer */
/* $FRR indent$ */
/* clang-format off */
#define RMAP_DEFAULT_UPDATE_TIMER 5 /* disabled by default */ #define RMAP_DEFAULT_UPDATE_TIMER 5 /* disabled by default */
QOBJ_FIELDS QOBJ_FIELDS
@ -132,14 +134,12 @@ struct bgp_master
DECLARE_QOBJ_TYPE(bgp_master) DECLARE_QOBJ_TYPE(bgp_master)
/* BGP route-map structure. */ /* BGP route-map structure. */
struct bgp_rmap struct bgp_rmap {
{
char *name; char *name;
struct route_map *map; struct route_map *map;
}; };
struct bgp_redist struct bgp_redist {
{
u_short instance; u_short instance;
/* BGP redistribute metric configuration. */ /* BGP redistribute metric configuration. */
@ -158,16 +158,14 @@ struct bgp_redist
* The "default" instance is treated separately to simplify the code. Note * The "default" instance is treated separately to simplify the code. Note
* that if deployed in a Multi-VRF environment, it may not exist. * that if deployed in a Multi-VRF environment, it may not exist.
*/ */
enum bgp_instance_type enum bgp_instance_type {
{
BGP_INSTANCE_TYPE_DEFAULT, BGP_INSTANCE_TYPE_DEFAULT,
BGP_INSTANCE_TYPE_VRF, BGP_INSTANCE_TYPE_VRF,
BGP_INSTANCE_TYPE_VIEW BGP_INSTANCE_TYPE_VIEW
}; };
/* BGP instance structure. */ /* BGP instance structure. */
struct bgp struct bgp {
{
/* AS number of this BGP instance. */ /* AS number of this BGP instance. */
as_t as; as_t as;
@ -236,17 +234,26 @@ struct bgp
as_t *confed_peers; as_t *confed_peers;
int confed_peers_cnt; int confed_peers_cnt;
struct thread *t_startup; /* start-up timer on only once at the beginning */ struct thread
*t_startup; /* start-up timer on only once at the beginning */
u_int32_t v_maxmed_onstartup; /* Duration of max-med on start-up */ u_int32_t v_maxmed_onstartup; /* Duration of max-med on start-up */
/* $FRR indent$ */
/* clang-format off */
#define BGP_MAXMED_ONSTARTUP_UNCONFIGURED 0 /* 0 means off, its the default */ #define BGP_MAXMED_ONSTARTUP_UNCONFIGURED 0 /* 0 means off, its the default */
u_int32_t maxmed_onstartup_value; /* Max-med value when active on start-up */ u_int32_t maxmed_onstartup_value; /* Max-med value when active on
struct thread *t_maxmed_onstartup; /* non-null when max-med onstartup is on */ start-up */
struct thread
*t_maxmed_onstartup; /* non-null when max-med onstartup is on */
u_char maxmed_onstartup_over; /* Flag to make it effective only once */ u_char maxmed_onstartup_over; /* Flag to make it effective only once */
u_char v_maxmed_admin; /* 1/0 if max-med administrative is on/off */ u_char v_maxmed_admin; /* 1/0 if max-med administrative is on/off */
/* $FRR indent$ */
/* clang-format off */
#define BGP_MAXMED_ADMIN_UNCONFIGURED 0 /* Off by default */ #define BGP_MAXMED_ADMIN_UNCONFIGURED 0 /* Off by default */
u_int32_t maxmed_admin_value; /* Max-med value when administrative in on */ u_int32_t
maxmed_admin_value; /* Max-med value when administrative in on
*/
#define BGP_MAXMED_VALUE_DEFAULT 4294967294 /* Maximum by default */ #define BGP_MAXMED_VALUE_DEFAULT 4294967294 /* Maximum by default */
u_char maxmed_active; /* 1/0 if max-med is active or not */ u_char maxmed_active; /* 1/0 if max-med is active or not */
@ -367,6 +374,20 @@ struct bgp
struct rfapi *rfapi; struct rfapi *rfapi;
#endif #endif
/* EVPN related information */
/* EVI hash table */
struct hash *vnihash;
/* EVPN enable - advertise local VNIs and their MACs etc. */
int advertise_all_vni;
/* Hash table of Import RTs to EVIs */
struct hash *import_rt_hash;
/* Id space for automatic RD derivation for an EVI */
bitfield_t rd_idspace;
QOBJ_FIELDS QOBJ_FIELDS
}; };
DECLARE_QOBJ_TYPE(bgp) DECLARE_QOBJ_TYPE(bgp)
@ -374,12 +395,12 @@ DECLARE_QOBJ_TYPE(bgp)
#define BGP_ROUTE_ADV_HOLD(bgp) (bgp->main_peers_update_hold) #define BGP_ROUTE_ADV_HOLD(bgp) (bgp->main_peers_update_hold)
#define IS_BGP_INST_KNOWN_TO_ZEBRA(bgp) \ #define IS_BGP_INST_KNOWN_TO_ZEBRA(bgp) \
(bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT || \ (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT \
(bgp->inst_type == BGP_INSTANCE_TYPE_VRF && bgp->vrf_id != VRF_UNKNOWN)) || (bgp->inst_type == BGP_INSTANCE_TYPE_VRF \
&& bgp->vrf_id != VRF_UNKNOWN))
/* BGP peer-group support. */ /* BGP peer-group support. */
struct peer_group struct peer_group {
{
/* Name of the peer-group. */ /* Name of the peer-group. */
char *name; char *name;
@ -397,8 +418,7 @@ struct peer_group
}; };
/* BGP Notify message format. */ /* BGP Notify message format. */
struct bgp_notify struct bgp_notify {
{
u_char code; u_char code;
u_char subcode; u_char subcode;
char *data; char *data;
@ -407,8 +427,7 @@ struct bgp_notify
}; };
/* Next hop self address. */ /* Next hop self address. */
struct bgp_nexthop struct bgp_nexthop {
{
struct interface *ifp; struct interface *ifp;
struct in_addr v4; struct in_addr v4;
struct in6_addr v6_global; struct in6_addr v6_global;
@ -425,8 +444,7 @@ struct bgp_nexthop
/* BGP router distinguisher value. */ /* BGP router distinguisher value. */
#define BGP_RD_SIZE 8 #define BGP_RD_SIZE 8
struct bgp_rd struct bgp_rd {
{
u_char val[BGP_RD_SIZE]; u_char val[BGP_RD_SIZE];
}; };
@ -437,39 +455,33 @@ struct bgp_rd
#include "filter.h" #include "filter.h"
/* BGP filter structure. */ /* BGP filter structure. */
struct bgp_filter struct bgp_filter {
{
/* Distribute-list. */ /* Distribute-list. */
struct struct {
{
char *name; char *name;
struct access_list *alist; struct access_list *alist;
} dlist[FILTER_MAX]; } dlist[FILTER_MAX];
/* Prefix-list. */ /* Prefix-list. */
struct struct {
{
char *name; char *name;
struct prefix_list *plist; struct prefix_list *plist;
} plist[FILTER_MAX]; } plist[FILTER_MAX];
/* Filter-list. */ /* Filter-list. */
struct struct {
{
char *name; char *name;
struct as_list *aslist; struct as_list *aslist;
} aslist[FILTER_MAX]; } aslist[FILTER_MAX];
/* Route-map. */ /* Route-map. */
struct struct {
{
char *name; char *name;
struct route_map *map; struct route_map *map;
} map[RMAP_MAX]; } map[RMAP_MAX];
/* Unsuppress-map. */ /* Unsuppress-map. */
struct struct {
{
char *name; char *name;
struct route_map *map; struct route_map *map;
} usmap; } usmap;
@ -477,8 +489,7 @@ struct bgp_filter
/* IBGP/EBGP identifier. We also have a CONFED peer, which is to say, /* IBGP/EBGP identifier. We also have a CONFED peer, which is to say,
a peer who's AS is part of our Confederation. */ a peer who's AS is part of our Confederation. */
typedef enum typedef enum {
{
BGP_PEER_IBGP = 1, BGP_PEER_IBGP = 1,
BGP_PEER_EBGP, BGP_PEER_EBGP,
BGP_PEER_INTERNAL, BGP_PEER_INTERNAL,
@ -497,8 +508,7 @@ typedef enum
#define BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS 100 #define BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS 100
#define BGP_ANNOUNCE_ROUTE_DELAY_MS 500 #define BGP_ANNOUNCE_ROUTE_DELAY_MS 500
struct peer_af struct peer_af {
{
/* back pointer to the peer */ /* back pointer to the peer */
struct peer *peer; struct peer *peer;
@ -524,8 +534,7 @@ struct peer_af
}; };
/* BGP neighbor structure. */ /* BGP neighbor structure. */
struct peer struct peer {
{
/* BGP structure. */ /* BGP structure. */
struct bgp *bgp; struct bgp *bgp;
@ -598,6 +607,8 @@ struct peer
unsigned short port; /* Destination port for peer */ unsigned short port; /* Destination port for peer */
char *host; /* Printable address of the peer. */ char *host; /* Printable address of the peer. */
union sockunion su; /* Sockunion address of the peer. */ union sockunion su; /* Sockunion address of the peer. */
/* $FRR indent$ */
/* clang-format off */
#define BGP_PEER_SU_UNSPEC(peer) (peer->su.sa.sa_family == AF_UNSPEC) #define BGP_PEER_SU_UNSPEC(peer) (peer->su.sa.sa_family == AF_UNSPEC)
time_t uptime; /* Last Up/Down time */ time_t uptime; /* Last Up/Down time */
time_t readtime; /* Last read time */ time_t readtime; /* Last read time */
@ -719,8 +730,7 @@ struct peer
char *password; char *password;
/* default-originate route-map. */ /* default-originate route-map. */
struct struct {
{
char *name; char *name;
struct route_map *map; struct route_map *map;
} default_rmap[AFI_MAX][SAFI_MAX]; } default_rmap[AFI_MAX][SAFI_MAX];
@ -799,7 +809,8 @@ struct peer
u_int32_t dropped; /* Dropped */ u_int32_t dropped; /* Dropped */
/* Update delay related fields */ /* Update delay related fields */
u_char update_delay_over; /* When this is set, BGP is no more waiting for EOR */ u_char update_delay_over; /* When this is set, BGP is no more waiting
for EOR */
/* Syncronization list and time. */ /* Syncronization list and time. */
struct bgp_synchronize *sync[AFI_MAX][SAFI_MAX]; struct bgp_synchronize *sync[AFI_MAX][SAFI_MAX];
@ -909,8 +920,7 @@ DECLARE_QOBJ_TYPE(peer)
/* This structure's member directly points incoming packet data /* This structure's member directly points incoming packet data
stream. */ stream. */
struct bgp_nlri struct bgp_nlri {
{
/* AFI. */ /* AFI. */
afi_t afi; afi_t afi;
@ -1100,8 +1110,7 @@ struct bgp_nlri
#define BGP_DYNAMIC_NEIGHBORS_LIMIT_MAX 5000 #define BGP_DYNAMIC_NEIGHBORS_LIMIT_MAX 5000
/* Flag for peer_clear_soft(). */ /* Flag for peer_clear_soft(). */
enum bgp_clear_type enum bgp_clear_type {
{
BGP_CLEAR_SOFT_NONE, BGP_CLEAR_SOFT_NONE,
BGP_CLEAR_SOFT_OUT, BGP_CLEAR_SOFT_OUT,
BGP_CLEAR_SOFT_IN, BGP_CLEAR_SOFT_IN,
@ -1151,12 +1160,12 @@ enum bgp_clear_type
#define BGP_ERR_INVALID_FOR_DYNAMIC_PEER -32 #define BGP_ERR_INVALID_FOR_DYNAMIC_PEER -32
#define BGP_ERR_MAX -33 #define BGP_ERR_MAX -33
#define BGP_ERR_INVALID_FOR_DIRECT_PEER -34 #define BGP_ERR_INVALID_FOR_DIRECT_PEER -34
#define BGP_ERR_PEER_SAFI_CONFLICT -35
/* /*
* Enumeration of different policy kinds a peer can be configured with. * Enumeration of different policy kinds a peer can be configured with.
*/ */
typedef enum typedef enum {
{
BGP_POLICY_ROUTE_MAP, BGP_POLICY_ROUTE_MAP,
BGP_POLICY_FILTER_LIST, BGP_POLICY_FILTER_LIST,
BGP_POLICY_PREFIX_LIST, BGP_POLICY_PREFIX_LIST,
@ -1185,11 +1194,13 @@ extern int peer_group_listen_range_del(struct peer_group *, struct prefix *);
extern struct peer_group *peer_group_lookup(struct bgp *, const char *); extern struct peer_group *peer_group_lookup(struct bgp *, const char *);
extern struct peer_group *peer_group_get(struct bgp *, const char *); extern struct peer_group *peer_group_get(struct bgp *, const char *);
extern struct peer *peer_create_bind_dynamic_neighbor(struct bgp *, extern struct peer *peer_create_bind_dynamic_neighbor(struct bgp *,
union sockunion *, struct peer_group *); union sockunion *,
extern struct prefix *peer_group_lookup_dynamic_neighbor_range ( struct peer_group *);
struct peer_group *, struct prefix *); extern struct prefix *
peer_group_lookup_dynamic_neighbor_range(struct peer_group *, struct prefix *);
extern struct peer_group *peer_group_lookup_dynamic_neighbor(struct bgp *, extern struct peer_group *peer_group_lookup_dynamic_neighbor(struct bgp *,
struct prefix *, struct prefix **); struct prefix *,
struct prefix **);
extern struct peer *peer_lookup_dynamic_neighbor(struct bgp *, extern struct peer *peer_lookup_dynamic_neighbor(struct bgp *,
union sockunion *); union sockunion *);
extern void peer_drop_dynamic_neighbor(struct peer *); extern void peer_drop_dynamic_neighbor(struct peer *);
@ -1209,7 +1220,8 @@ extern int peer_active (struct peer *);
extern int peer_active_nego(struct peer *); extern int peer_active_nego(struct peer *);
extern void bgp_recalculate_all_bestpaths(struct bgp *bgp); extern void bgp_recalculate_all_bestpaths(struct bgp *bgp);
extern struct peer *peer_create(union sockunion *, const char *, struct bgp *, extern struct peer *peer_create(union sockunion *, const char *, struct bgp *,
as_t, as_t, int, afi_t, safi_t, struct peer_group *); as_t, as_t, int, afi_t, safi_t,
struct peer_group *);
extern struct peer *peer_create_accept(struct bgp *); extern struct peer *peer_create_accept(struct bgp *);
extern void peer_xfer_config(struct peer *dst, struct peer *src); extern void peer_xfer_config(struct peer *dst, struct peer *src);
extern char *peer_uptime(time_t, char *, size_t, u_char, json_object *); extern char *peer_uptime(time_t, char *, size_t, u_char, json_object *);
@ -1252,7 +1264,8 @@ extern int bgp_confederation_peers_check (struct bgp *, as_t);
extern int bgp_confederation_peers_add(struct bgp *, as_t); extern int bgp_confederation_peers_add(struct bgp *, as_t);
extern int bgp_confederation_peers_remove(struct bgp *, as_t); extern int bgp_confederation_peers_remove(struct bgp *, as_t);
extern int bgp_timers_set (struct bgp *, u_int32_t keepalive, u_int32_t holdtime); extern int bgp_timers_set(struct bgp *, u_int32_t keepalive,
u_int32_t holdtime);
extern int bgp_timers_unset(struct bgp *); extern int bgp_timers_unset(struct bgp *);
extern int bgp_default_local_preference_set(struct bgp *, u_int32_t); extern int bgp_default_local_preference_set(struct bgp *, u_int32_t);
@ -1301,7 +1314,8 @@ extern int peer_update_source_if_set (struct peer *, const char *);
extern int peer_update_source_addr_set(struct peer *, const union sockunion *); extern int peer_update_source_addr_set(struct peer *, const union sockunion *);
extern int peer_update_source_unset(struct peer *); extern int peer_update_source_unset(struct peer *);
extern int peer_default_originate_set (struct peer *, afi_t, safi_t, const char *); extern int peer_default_originate_set(struct peer *, afi_t, safi_t,
const char *);
extern int peer_default_originate_unset(struct peer *, afi_t, safi_t); extern int peer_default_originate_unset(struct peer *, afi_t, safi_t);
extern int peer_port_set(struct peer *, u_int16_t); extern int peer_port_set(struct peer *, u_int16_t);
@ -1310,7 +1324,8 @@ extern int peer_port_unset (struct peer *);
extern int peer_weight_set(struct peer *, afi_t, safi_t, u_int16_t); extern int peer_weight_set(struct peer *, afi_t, safi_t, u_int16_t);
extern int peer_weight_unset(struct peer *, afi_t, safi_t); extern int peer_weight_unset(struct peer *, afi_t, safi_t);
extern int peer_timers_set (struct peer *, u_int32_t keepalive, u_int32_t holdtime); extern int peer_timers_set(struct peer *, u_int32_t keepalive,
u_int32_t holdtime);
extern int peer_timers_unset(struct peer *); extern int peer_timers_unset(struct peer *);
extern int peer_timers_connect_set(struct peer *, u_int32_t); extern int peer_timers_connect_set(struct peer *, u_int32_t);
@ -1331,7 +1346,8 @@ extern int peer_allowas_in_unset (struct peer *, afi_t, safi_t);
extern int peer_local_as_set(struct peer *, as_t, int, int); extern int peer_local_as_set(struct peer *, as_t, int, int);
extern int peer_local_as_unset(struct peer *); extern int peer_local_as_unset(struct peer *);
extern int peer_prefix_list_set (struct peer *, afi_t, safi_t, int, const char *); extern int peer_prefix_list_set(struct peer *, afi_t, safi_t, int,
const char *);
extern int peer_prefix_list_unset(struct peer *, afi_t, safi_t, int); extern int peer_prefix_list_unset(struct peer *, afi_t, safi_t, int);
extern int peer_aslist_set(struct peer *, afi_t, safi_t, int, const char *); extern int peer_aslist_set(struct peer *, afi_t, safi_t, int, const char *);
@ -1347,7 +1363,8 @@ extern int peer_password_unset (struct peer *);
extern int peer_unsuppress_map_unset(struct peer *, afi_t, safi_t); extern int peer_unsuppress_map_unset(struct peer *, afi_t, safi_t);
extern int peer_maximum_prefix_set (struct peer *, afi_t, safi_t, u_int32_t, u_char, int, u_int16_t); extern int peer_maximum_prefix_set(struct peer *, afi_t, safi_t, u_int32_t,
u_char, int, u_int16_t);
extern int peer_maximum_prefix_unset(struct peer *, afi_t, safi_t); extern int peer_maximum_prefix_unset(struct peer *, afi_t, safi_t);
extern int peer_clear(struct peer *, struct listnode **); extern int peer_clear(struct peer *, struct listnode **);
@ -1364,11 +1381,9 @@ extern void bgp_route_map_terminate(void);
extern int peer_cmp(struct peer *p1, struct peer *p2); extern int peer_cmp(struct peer *p1, struct peer *p2);
extern int extern int bgp_map_afi_safi_iana2int(iana_afi_t pkt_afi, safi_t pkt_safi,
bgp_map_afi_safi_iana2int (iana_afi_t pkt_afi, safi_t pkt_safi,
afi_t *afi, safi_t *safi); afi_t *afi, safi_t *safi);
extern int extern int bgp_map_afi_safi_int2iana(afi_t afi, safi_t safi,
bgp_map_afi_safi_int2iana (afi_t afi, safi_t safi,
iana_afi_t *pkt_afi, safi_t *pkt_safi); iana_afi_t *pkt_afi, safi_t *pkt_safi);
extern struct peer_af *peer_af_create(struct peer *, afi_t, safi_t); extern struct peer_af *peer_af_create(struct peer *, afi_t, safi_t);
@ -1377,14 +1392,11 @@ extern int peer_af_delete (struct peer *, afi_t, safi_t);
extern void bgp_close(void); extern void bgp_close(void);
static inline int static inline int afindex(afi_t afi, safi_t safi)
afindex (afi_t afi, safi_t safi)
{
switch (afi)
{ {
switch (afi) {
case AFI_IP: case AFI_IP:
switch (safi) switch (safi) {
{
case SAFI_UNICAST: case SAFI_UNICAST:
return BGP_AF_IPV4_UNICAST; return BGP_AF_IPV4_UNICAST;
break; break;
@ -1406,8 +1418,7 @@ afindex (afi_t afi, safi_t safi)
} }
break; break;
case AFI_IP6: case AFI_IP6:
switch (safi) switch (safi) {
{
case SAFI_UNICAST: case SAFI_UNICAST:
return BGP_AF_IPV6_UNICAST; return BGP_AF_IPV6_UNICAST;
break; break;
@ -1429,8 +1440,7 @@ afindex (afi_t afi, safi_t safi)
} }
break; break;
case AFI_L2VPN: case AFI_L2VPN:
switch (safi) switch (safi) {
{
case SAFI_EVPN: case SAFI_EVPN:
return BGP_AF_L2VPN_EVPN; return BGP_AF_L2VPN_EVPN;
break; break;
@ -1445,8 +1455,7 @@ afindex (afi_t afi, safi_t safi)
} }
/* If the peer is not a peer-group but is bound to a peer-group return 1 */ /* If the peer is not a peer-group but is bound to a peer-group return 1 */
static inline int static inline int peer_group_active(struct peer *peer)
peer_group_active (struct peer *peer)
{ {
if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP) && peer->group) if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP) && peer->group)
return 1; return 1;
@ -1454,69 +1463,61 @@ peer_group_active (struct peer *peer)
} }
/* If peer is negotiated at least one address family return 1. */ /* If peer is negotiated at least one address family return 1. */
static inline int static inline int peer_afi_active_nego(const struct peer *peer, afi_t afi)
peer_afi_active_nego (const struct peer *peer, afi_t afi)
{ {
if (peer->afc_nego[afi][SAFI_UNICAST] if (peer->afc_nego[afi][SAFI_UNICAST]
|| peer->afc_nego[afi][SAFI_MULTICAST] || peer->afc_nego[afi][SAFI_MULTICAST]
|| peer->afc_nego[afi][SAFI_LABELED_UNICAST] || peer->afc_nego[afi][SAFI_LABELED_UNICAST]
|| peer->afc_nego[afi][SAFI_MPLS_VPN] || peer->afc_nego[afi][SAFI_MPLS_VPN]
|| peer->afc_nego[afi][SAFI_ENCAP]) || peer->afc_nego[afi][SAFI_ENCAP]
|| peer->afc_nego[afi][SAFI_EVPN])
return 1; return 1;
return 0; return 0;
} }
/* If at least one address family activated for group, return 1. */ /* If at least one address family activated for group, return 1. */
static inline int static inline int peer_group_af_configured(struct peer_group *group)
peer_group_af_configured (struct peer_group *group)
{ {
struct peer *peer = group->conf; struct peer *peer = group->conf;
if (peer->afc[AFI_IP][SAFI_UNICAST] if (peer->afc[AFI_IP][SAFI_UNICAST] || peer->afc[AFI_IP][SAFI_MULTICAST]
|| peer->afc[AFI_IP][SAFI_MULTICAST]
|| peer->afc[AFI_IP][SAFI_LABELED_UNICAST] || peer->afc[AFI_IP][SAFI_LABELED_UNICAST]
|| peer->afc[AFI_IP][SAFI_MPLS_VPN] || peer->afc[AFI_IP][SAFI_MPLS_VPN] || peer->afc[AFI_IP][SAFI_ENCAP]
|| peer->afc[AFI_IP][SAFI_ENCAP]
|| peer->afc[AFI_IP6][SAFI_UNICAST] || peer->afc[AFI_IP6][SAFI_UNICAST]
|| peer->afc[AFI_IP6][SAFI_MULTICAST] || peer->afc[AFI_IP6][SAFI_MULTICAST]
|| peer->afc[AFI_IP6][SAFI_LABELED_UNICAST] || peer->afc[AFI_IP6][SAFI_LABELED_UNICAST]
|| peer->afc[AFI_IP6][SAFI_MPLS_VPN] || peer->afc[AFI_IP6][SAFI_MPLS_VPN]
|| peer->afc[AFI_IP6][SAFI_ENCAP]) || peer->afc[AFI_IP6][SAFI_ENCAP] || peer->afc[AFI_IP6][SAFI_EVPN])
return 1; return 1;
return 0; return 0;
} }
static inline char * static inline char *timestamp_string(time_t ts)
timestamp_string (time_t ts)
{ {
time_t tbuf; time_t tbuf;
tbuf = time(NULL) - (bgp_clock() - ts); tbuf = time(NULL) - (bgp_clock() - ts);
return ctime(&tbuf); return ctime(&tbuf);
} }
static inline int static inline int peer_established(struct peer *peer)
peer_established (struct peer *peer)
{ {
if (peer->status == Established) if (peer->status == Established)
return 1; return 1;
return 0; return 0;
} }
static inline int static inline int peer_dynamic_neighbor(struct peer *peer)
peer_dynamic_neighbor (struct peer *peer)
{ {
return (CHECK_FLAG(peer->flags, PEER_FLAG_DYNAMIC_NEIGHBOR)) ? 1 : 0; return (CHECK_FLAG(peer->flags, PEER_FLAG_DYNAMIC_NEIGHBOR)) ? 1 : 0;
} }
static inline int static inline int peer_cap_enhe(struct peer *peer, afi_t afi, safi_t safi)
peer_cap_enhe (struct peer *peer, afi_t afi, safi_t safi)
{ {
return (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ENHE_AF_NEGO)); return (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ENHE_AF_NEGO));
} }
/* Lookup VRF for BGP instance based on its type. */ /* Lookup VRF for BGP instance based on its type. */
static inline struct vrf * static inline struct vrf *bgp_vrf_lookup_by_instance_type(struct bgp *bgp)
bgp_vrf_lookup_by_instance_type (struct bgp *bgp)
{ {
struct vrf *vrf; struct vrf *vrf;
@ -1531,23 +1532,19 @@ bgp_vrf_lookup_by_instance_type (struct bgp *bgp)
} }
/* Link BGP instance to VRF. */ /* Link BGP instance to VRF. */
static inline void static inline void bgp_vrf_link(struct bgp *bgp, struct vrf *vrf)
bgp_vrf_link (struct bgp *bgp, struct vrf *vrf)
{ {
bgp->vrf_id = vrf->vrf_id; bgp->vrf_id = vrf->vrf_id;
if (vrf->info != (void *)bgp) if (vrf->info != (void *)bgp) {
{
bgp_lock(bgp); bgp_lock(bgp);
vrf->info = (void *)bgp; vrf->info = (void *)bgp;
} }
} }
/* Unlink BGP instance from VRF. */ /* Unlink BGP instance from VRF. */
static inline void static inline void bgp_vrf_unlink(struct bgp *bgp, struct vrf *vrf)
bgp_vrf_unlink (struct bgp *bgp, struct vrf *vrf)
{
if (vrf->info == (void *)bgp)
{ {
if (vrf->info == (void *)bgp) {
vrf->info = NULL; vrf->info = NULL;
bgp_unlock(bgp); bgp_unlock(bgp);
} }

File diff suppressed because it is too large Load Diff

View File

@ -27,8 +27,7 @@
#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 */
@ -40,16 +39,14 @@ struct rfapi_l2_group_cfg
}; };
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 */
@ -115,21 +112,18 @@ struct rfapi_nve_group_cfg
}; };
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;
@ -169,7 +163,8 @@ struct rfapi_cfg
/* /*
* 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
* rfapi_rfg_name>)
* This list is used when BGP_VNC_CONFIG_EXPORT_ZEBRA_MODE_BITS is * This list is used when BGP_VNC_CONFIG_EXPORT_ZEBRA_MODE_BITS is
* BGP_VNC_CONFIG_EXPORT_ZEBRA_MODE_GRP * BGP_VNC_CONFIG_EXPORT_ZEBRA_MODE_GRP
*/ */
@ -245,96 +240,74 @@ struct rfapi_cfg
/* 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 rfapi_nve_group_cfg *rfg,
struct list **nves, struct list **nves,
uint8_t family); /* AF_INET, AF_INET6 */ uint8_t family); /* AF_INET, AF_INET6 */
struct rfapi_nve_group_cfg * struct rfapi_nve_group_cfg *bgp_rfapi_cfg_match_group(struct rfapi_cfg *hc,
bgp_rfapi_cfg_match_group (
struct rfapi_cfg *hc,
struct prefix *vn, struct prefix *vn,
struct prefix *un); struct prefix *un);
struct rfapi_nve_group_cfg * struct rfapi_nve_group_cfg *
bgp_rfapi_cfg_match_byname ( bgp_rfapi_cfg_match_byname(struct bgp *bgp, const char *name,
struct bgp *bgp,
const char *name,
rfapi_group_cfg_type_t type); /* _MAX = any */ rfapi_group_cfg_type_t type); /* _MAX = any */
extern void extern void vnc_prefix_list_update(struct bgp *bgp);
vnc_prefix_list_update (struct bgp *bgp);
extern void extern void vnc_routemap_update(struct bgp *bgp, const char *unused);
vnc_routemap_update (struct bgp *bgp, const char *unused);
extern void extern void bgp_rfapi_show_summary(struct bgp *bgp, struct vty *vty);
bgp_rfapi_show_summary (struct bgp *bgp, struct vty *vty);
extern struct rfapi_cfg * extern struct rfapi_cfg *bgp_rfapi_get_config(struct bgp *bgp);
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 logical_net_id,
uint32_t label); 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 is_import,
uint32_t logical_net_id, uint32_t logical_net_id,
uint32_t label); /* note, 20bit label! */ 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 logical_net_id,
uint32_t label); /* note, 20bit label! */ 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

@ -44,31 +44,26 @@
#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 in_addr v4; /* in network order */
struct in6_addr v6; /* in network order */ struct in6_addr v6; /* in network order */
} addr; } 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;
@ -81,8 +76,7 @@ struct rfapi_next_hop_entry
#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,
@ -91,24 +85,24 @@ struct rfapi_l2address_option
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_reserved reserved;
struct bgp_encap_type_l2tpv3_over_ip l2tpv3_ip; struct bgp_encap_type_l2tpv3_over_ip l2tpv3_ip;
struct bgp_encap_type_gre gre; struct bgp_encap_type_gre gre;
struct bgp_encap_type_transmit_tunnel_endpoint 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 ip_ipsec; struct bgp_encap_type_ip_in_ip_tunnel_with_ipsec_transport_mode
struct bgp_encap_type_mpls_in_ip_tunnel_with_ipsec_transport_mode mpls_ipsec; ip_ipsec;
struct bgp_encap_type_mpls_in_ip_tunnel_with_ipsec_transport_mode
mpls_ipsec;
struct bgp_encap_type_ip_in_ip ip_ip; struct bgp_encap_type_ip_in_ip ip_ip;
struct bgp_encap_type_vxlan vxlan; struct bgp_encap_type_vxlan vxlan;
struct bgp_encap_type_nvgre nvgre; struct bgp_encap_type_nvgre nvgre;
@ -120,31 +114,27 @@ struct rfapi_tunneltype_option
} bgpinfo; } 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; struct rfapi_tunneltype_option tunnel;
} v; } 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;
/* /*
@ -160,8 +150,7 @@ struct rfapi_vn_option
} 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;
@ -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, const char *name, void *rfp_cfg_group);
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,16 +303,14 @@ 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 */
/* /*
@ -370,9 +352,7 @@ 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 thread_master *master,
struct rfapi_rfp_cfg **cfgp, struct rfapi_rfp_cfg **cfgp,
struct rfapi_rfp_cb_methods **cbmp); struct rfapi_rfp_cb_methods **cbmp);
@ -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,9 +392,7 @@ 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 (
void *rfp_start_val,
struct rfapi_rfp_cfg *rfp_cfg); struct rfapi_rfp_cfg *rfp_cfg);
/*------------------------------------------ /*------------------------------------------
@ -433,9 +410,7 @@ 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 (
void *rfp_start_val,
struct rfapi_rfp_cb_methods *methods); struct rfapi_rfp_cb_methods *methods);
/*********************************************************************** /***********************************************************************
@ -463,9 +438,7 @@ 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 (
void *rfp_start_val,
rfapi_rfp_cfg_group_type type, rfapi_rfp_cfg_group_type type,
struct vty *vty, struct vty *vty,
uint32_t size); uint32_t size);
@ -489,9 +462,7 @@ 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 (
void *rfp_start_val,
rfapi_rfp_cfg_group_type type, rfapi_rfp_cfg_group_type type,
struct vty *vty); struct vty *vty);
@ -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,10 +531,8 @@ 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,
void *criteria,
rfp_group_config_search_cb_t *search_cb); rfp_group_config_search_cb_t *search_cb);
/*********************************************************************** /***********************************************************************
@ -615,14 +579,10 @@ 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 (
void *rfp_start_val,
struct rfapi_ip_addr *vn,
struct rfapi_ip_addr *un, struct rfapi_ip_addr *un,
struct rfapi_un_option *default_options, struct rfapi_un_option *default_options,
uint32_t *response_lifetime, uint32_t *response_lifetime, void *userdata,
void *userdata,
rfapi_handle *pHandle); 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,10 +659,7 @@ 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 (
rfapi_handle rfd,
struct rfapi_ip_addr *target,
struct rfapi_l2address_option *l2o, struct rfapi_l2address_option *l2o,
struct rfapi_next_hop_entry **ppNextHopEntry); struct rfapi_next_hop_entry **ppNextHopEntry);
@ -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,19 +738,14 @@ 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_ip_prefix *prefix,
uint32_t lifetime,
struct rfapi_un_option *options_un,
struct rfapi_vn_option *options_vn, struct rfapi_vn_option *options_vn,
rfapi_register_action action); rfapi_register_action action);
@ -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,8 +83,7 @@
* 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;
@ -102,28 +101,27 @@ sl_adb_lifetime_cmp (void *adb1, void *adb2)
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);
@ -135,8 +133,7 @@ rfapiApRelease (struct rfapi_advertised_prefixes *ap)
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;
@ -144,8 +141,7 @@ rfapiApCount (struct rfapi_descriptor *rfd)
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;
@ -153,10 +149,8 @@ rfapiApCountAll (struct bgp *bgp)
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);
} }
} }
@ -164,20 +158,16 @@ rfapiApCountAll (struct bgp *bgp)
} }
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);
@ -190,17 +180,18 @@ rfapiApReadvertiseAll (struct bgp *bgp, struct rfapi_descriptor *rfd)
* 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,
&prd, /* RD to use (0 for ENCAP) */
&rfd->vn_addr, /* nexthop */ &rfd->vn_addr, /* nexthop */
&local_pref, &adb->lifetime, NULL, NULL, /* struct rfapi_un_option */ &local_pref, &adb->lifetime, NULL,
NULL, /* struct rfapi_un_option */
NULL, /* struct rfapi_vn_option */ NULL, /* struct rfapi_vn_option */
rfd->rt_export_list, NULL, /* med */ rfd->rt_export_list, NULL, /* med */
NULL, ZEBRA_ROUTE_BGP, BGP_ROUTE_RFP, 0); 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;
@ -208,44 +199,40 @@ rfapiApWithdrawAll (struct bgp *bgp, struct rfapi_descriptor *rfd)
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 ("%s: BAD: handle has bad vn_addr: skipping", vnc_zlog_debug_verbose(
"%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,
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); ZEBRA_ROUTE_BGP, BGP_ROUTE_RFP, NULL, 0);
} }
} }
@ -253,8 +240,7 @@ rfapiApWithdrawAll (struct bgp *bgp, struct rfapi_descriptor *rfd)
/* /*
* 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 */
@ -263,20 +249,20 @@ rfapiApAdjustLifetimeStats (
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__,
*old_lifetime);
if (new_lifetime) if (new_lifetime)
vnc_zlog_debug_verbose ("%s: NewLife=%d", __func__, *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
*/ */
@ -286,48 +272,38 @@ rfapiApAdjustLifetimeStats (
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) if (*new_lifetime < rfd->min_prefix_lifetime) {
{
rfd->min_prefix_lifetime = *new_lifetime; rfd->min_prefix_lifetime = *new_lifetime;
} }
if (*new_lifetime > rfd->max_prefix_lifetime) if (*new_lifetime > rfd->max_prefix_lifetime) {
{
advertise = 1; advertise = 1;
rfd->max_prefix_lifetime = *new_lifetime; rfd->max_prefix_lifetime = *new_lifetime;
} }
} }
} } else {
else
{
/* /*
* Deleting * Deleting
*/ */
@ -344,8 +320,7 @@ rfapiApAdjustLifetimeStats (
* address family that matches the VN address. * address family that matches the VN address.
* *
*/ */
if (rfd->max_prefix_lifetime == rfd->min_prefix_lifetime) if (rfd->max_prefix_lifetime == rfd->min_prefix_lifetime) {
{
/* /*
* Common case: all lifetimes are the same. Only * Common case: all lifetimes are the same. Only
@ -353,43 +328,35 @@ rfapiApAdjustLifetimeStats (
* no exported routes left. In that case, reinitialize * no exported routes left. In that case, reinitialize
* the max and min values. * the max and min values.
*/ */
if (!rfapiApCount (rfd)) if (!rfapiApCount(rfd)) {
{
rfd->max_prefix_lifetime = 0; rfd->max_prefix_lifetime = 0;
rfd->min_prefix_lifetime = UINT32_MAX; rfd->min_prefix_lifetime = UINT32_MAX;
} }
} } else {
else if (old_lifetime) {
{ if (*old_lifetime == rfd->min_prefix_lifetime) {
if (old_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;
} }
} }
} }
} }
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
@ -397,25 +364,24 @@ rfapiApAdjustLifetimeStats (
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;
@ -427,11 +393,11 @@ rfapiApAdjustLifetimeStats (
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;
@ -466,15 +432,9 @@ 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 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 */ struct rfapi_l2address_option *l2o) /* other options TBD */
{ {
int rc; int rc;
@ -484,55 +444,45 @@ rfapiApAdd (
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 = 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) {
{
/* 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, &adb->u.key, skiplist_insert(rfd->advertised.ip0_by_ether,
adb); &adb->u.key, adb);
} } else {
else skiplist_insert(rfd->advertised.ipN_by_prefix,
{ &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; old_lifetime = adb->lifetime;
if (old_lifetime != lifetime) if (old_lifetime != lifetime) {
{ assert(!skiplist_delete(rfd->advertised.by_lifetime,
assert (!skiplist_delete (rfd->advertised.by_lifetime, adb, NULL)); adb, NULL));
adb->lifetime = lifetime; adb->lifetime = lifetime;
assert (!skiplist_insert (rfd->advertised.by_lifetime, adb, adb)); assert(!skiplist_insert(rfd->advertised.by_lifetime,
adb, adb));
} }
} }
adb->cost = cost; adb->cost = cost;
@ -541,8 +491,8 @@ rfapiApAdd (
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;
@ -552,14 +502,9 @@ rfapiApAdd (
* 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;
@ -572,38 +517,29 @@ rfapiApDelete (
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 {
else
{
rc = skiplist_delete(rfd->advertised.ipN_by_prefix, &rk, NULL); rc = skiplist_delete(rfd->advertised.ipN_by_prefix, &rk, NULL);
} }
assert(!rc); assert(!rc);
@ -613,8 +549,7 @@ rfapiApDelete (
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;
} }

View File

@ -56,42 +56,28 @@
#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,
extern int
rfapiApCountAll (struct bgp *bgp);
extern void
rfapiApReadvertiseAll (struct bgp *bgp, struct rfapi_descriptor *rfd);
extern void
rfapiApWithdrawAll (struct bgp *bgp, struct rfapi_descriptor *rfd);
extern int
rfapiApAdd (
struct bgp *bgp,
struct rfapi_descriptor *rfd,
struct prefix *pfx_ip,
struct prefix *pfx_eth,
struct prefix_rd *prd,
uint32_t lifetime,
uint8_t cost, uint8_t cost,
struct rfapi_l2address_option *l2o); /* other options TBD */ struct rfapi_l2address_option *l2o); /* other options TBD */
extern int extern int rfapiApDelete(struct bgp *bgp, struct rfapi_descriptor *rfd,
rfapiApDelete ( struct prefix *pfx_ip, struct prefix *pfx_eth,
struct bgp *bgp,
struct rfapi_descriptor *rfd,
struct prefix *pfx_ip,
struct prefix *pfx_eth,
struct prefix_rd *prd, struct prefix_rd *prd,
int *advertise_tunnel); /* out */ int *advertise_tunnel); /* out */

View File

@ -35,38 +35,26 @@ 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,
struct prefix *p,
struct prefix_rd *prd,
struct attr *attr,
afi_t afi, safi_t safi, u_char type, int kill); 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);

View File

@ -36,8 +36,7 @@
#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));
@ -60,8 +59,7 @@ 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;
@ -84,8 +82,7 @@ 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;
@ -93,8 +90,7 @@ rfapi_compare_rfds (void *rfd1, void *rfd2)
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));
@ -114,8 +110,7 @@ rfapi_compare_rfds (void *rfd1, void *rfd2)
* 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

View File

@ -37,10 +37,8 @@
#include "bgpd/rfapi/bgp_rfapi_cfg.h" #include "bgpd/rfapi/bgp_rfapi_cfg.h"
#include "bgpd/rfapi/vnc_debug.h" #include "bgpd/rfapi/vnc_debug.h"
static void static void rfapi_add_endpoint_address_to_subtlv(
rfapi_add_endpoint_address_to_subtlv ( struct bgp *bgp, struct rfapi_ip_addr *ea,
struct bgp *bgp,
struct rfapi_ip_addr *ea,
struct bgp_tea_subtlv_remote_endpoint *subtlv) struct bgp_tea_subtlv_remote_endpoint *subtlv)
{ {
subtlv->family = ea->addr_family; subtlv->family = ea->addr_family;
@ -52,37 +50,36 @@ rfapi_add_endpoint_address_to_subtlv (
} }
bgp_encap_types bgp_encap_types
rfapi_tunneltype_option_to_tlv ( rfapi_tunneltype_option_to_tlv(struct bgp *bgp, struct rfapi_ip_addr *ea,
struct bgp *bgp,
struct rfapi_ip_addr *ea,
struct rfapi_tunneltype_option *tto, struct rfapi_tunneltype_option *tto,
struct attr *attr, struct attr *attr, int always_add)
int always_add)
{ {
#define _RTTO_MAYBE_ADD_ENDPOINT_ADDRESS(ttype) \ #define _RTTO_MAYBE_ADD_ENDPOINT_ADDRESS(ttype) \
if ((always_add || (bgp->rfapi_cfg && \ if ((always_add \
!CHECK_FLAG(bgp->rfapi_cfg->flags, \ || (bgp->rfapi_cfg \
BGP_VNC_CONFIG_ADV_UN_METHOD_ENCAP))) && \ && !CHECK_FLAG(bgp->rfapi_cfg->flags, \
ea && !CHECK_SUBTLV_FLAG(&tto->bgpinfo.ttype, \ BGP_VNC_CONFIG_ADV_UN_METHOD_ENCAP))) \
&& ea \
&& !CHECK_SUBTLV_FLAG(&tto->bgpinfo.ttype, \
BGP_TEA_SUBTLV_REMOTE_ENDPOINT)) { \ BGP_TEA_SUBTLV_REMOTE_ENDPOINT)) { \
rfapi_add_endpoint_address_to_subtlv(bgp, ea, \ rfapi_add_endpoint_address_to_subtlv( \
&tto->bgpinfo.ttype.st_endpoint); \ bgp, ea, &tto->bgpinfo.ttype.st_endpoint); \
SET_SUBTLV_FLAG(&tto->bgpinfo.ttype, BGP_TEA_SUBTLV_REMOTE_ENDPOINT); \ SET_SUBTLV_FLAG(&tto->bgpinfo.ttype, \
BGP_TEA_SUBTLV_REMOTE_ENDPOINT); \
} }
struct rfapi_tunneltype_option dto; struct rfapi_tunneltype_option dto;
if (tto == NULL) if (tto == NULL) { /* create default type */
{ /* create default type */
tto = &dto; tto = &dto;
memset(tto, 0, sizeof(dto)); memset(tto, 0, sizeof(dto));
tto->type = RFAPI_BGP_ENCAP_TYPE_DEFAULT; tto->type = RFAPI_BGP_ENCAP_TYPE_DEFAULT;
} }
switch (tto->type) switch (tto->type) {
{
case BGP_ENCAP_TYPE_L2TPV3_OVER_IP: case BGP_ENCAP_TYPE_L2TPV3_OVER_IP:
_RTTO_MAYBE_ADD_ENDPOINT_ADDRESS(l2tpv3_ip); _RTTO_MAYBE_ADD_ENDPOINT_ADDRESS(l2tpv3_ip);
bgp_encap_type_l2tpv3overip_to_tlv (&tto->bgpinfo.l2tpv3_ip, attr); bgp_encap_type_l2tpv3overip_to_tlv(&tto->bgpinfo.l2tpv3_ip,
attr);
break; break;
case BGP_ENCAP_TYPE_GRE: case BGP_ENCAP_TYPE_GRE:
@ -92,26 +89,26 @@ rfapi_tunneltype_option_to_tlv (
case BGP_ENCAP_TYPE_TRANSMIT_TUNNEL_ENDPOINT: case BGP_ENCAP_TYPE_TRANSMIT_TUNNEL_ENDPOINT:
_RTTO_MAYBE_ADD_ENDPOINT_ADDRESS(transmit_tunnel_endpoint); _RTTO_MAYBE_ADD_ENDPOINT_ADDRESS(transmit_tunnel_endpoint);
bgp_encap_type_transmit_tunnel_endpoint (&tto->bgpinfo.transmit_tunnel_endpoint, bgp_encap_type_transmit_tunnel_endpoint(
attr); &tto->bgpinfo.transmit_tunnel_endpoint, attr);
break; break;
case BGP_ENCAP_TYPE_IPSEC_IN_TUNNEL_MODE: case BGP_ENCAP_TYPE_IPSEC_IN_TUNNEL_MODE:
_RTTO_MAYBE_ADD_ENDPOINT_ADDRESS(ipsec_tunnel); _RTTO_MAYBE_ADD_ENDPOINT_ADDRESS(ipsec_tunnel);
bgp_encap_type_ipsec_in_tunnel_mode_to_tlv (&tto->bgpinfo.ipsec_tunnel, bgp_encap_type_ipsec_in_tunnel_mode_to_tlv(
attr); &tto->bgpinfo.ipsec_tunnel, attr);
break; break;
case BGP_ENCAP_TYPE_IP_IN_IP_TUNNEL_WITH_IPSEC_TRANSPORT_MODE: case BGP_ENCAP_TYPE_IP_IN_IP_TUNNEL_WITH_IPSEC_TRANSPORT_MODE:
_RTTO_MAYBE_ADD_ENDPOINT_ADDRESS(ip_ipsec); _RTTO_MAYBE_ADD_ENDPOINT_ADDRESS(ip_ipsec);
bgp_encap_type_ip_in_ip_tunnel_with_ipsec_transport_mode_to_tlv bgp_encap_type_ip_in_ip_tunnel_with_ipsec_transport_mode_to_tlv(
(&tto->bgpinfo.ip_ipsec, attr); &tto->bgpinfo.ip_ipsec, attr);
break; break;
case BGP_ENCAP_TYPE_MPLS_IN_IP_TUNNEL_WITH_IPSEC_TRANSPORT_MODE: case BGP_ENCAP_TYPE_MPLS_IN_IP_TUNNEL_WITH_IPSEC_TRANSPORT_MODE:
_RTTO_MAYBE_ADD_ENDPOINT_ADDRESS(mpls_ipsec); _RTTO_MAYBE_ADD_ENDPOINT_ADDRESS(mpls_ipsec);
bgp_encap_type_mpls_in_ip_tunnel_with_ipsec_transport_mode_to_tlv bgp_encap_type_mpls_in_ip_tunnel_with_ipsec_transport_mode_to_tlv(
(&tto->bgpinfo.mpls_ipsec, attr); &tto->bgpinfo.mpls_ipsec, attr);
break; break;
case BGP_ENCAP_TYPE_IP_IN_IP: case BGP_ENCAP_TYPE_IP_IN_IP:
@ -159,34 +156,29 @@ rfapi_tunneltype_option_to_tlv (
return tto->type; return tto->type;
} }
struct rfapi_un_option * struct rfapi_un_option *rfapi_encap_tlv_to_un_option(struct attr *attr)
rfapi_encap_tlv_to_un_option (struct attr *attr)
{ {
struct attr_extra *attre = attr->extra;
struct rfapi_un_option *uo = NULL; struct rfapi_un_option *uo = NULL;
struct rfapi_tunneltype_option *tto; struct rfapi_tunneltype_option *tto;
int rc; int rc;
struct bgp_attr_encap_subtlv *stlv; struct bgp_attr_encap_subtlv *stlv;
if (!attre)
return NULL;
/* no tunnel encap attr stored */ /* no tunnel encap attr stored */
if (!attre->encap_tunneltype) if (!attr->encap_tunneltype)
return NULL; return NULL;
stlv = attre->encap_subtlvs; stlv = attr->encap_subtlvs;
uo = XCALLOC(MTYPE_RFAPI_UN_OPTION, sizeof(struct rfapi_un_option)); uo = XCALLOC(MTYPE_RFAPI_UN_OPTION, sizeof(struct rfapi_un_option));
assert(uo); assert(uo);
uo->type = RFAPI_UN_OPTION_TYPE_TUNNELTYPE; uo->type = RFAPI_UN_OPTION_TYPE_TUNNELTYPE;
uo->v.tunnel.type = attre->encap_tunneltype; uo->v.tunnel.type = attr->encap_tunneltype;
tto = &uo->v.tunnel; tto = &uo->v.tunnel;
switch (attre->encap_tunneltype) switch (attr->encap_tunneltype) {
{
case BGP_ENCAP_TYPE_L2TPV3_OVER_IP: case BGP_ENCAP_TYPE_L2TPV3_OVER_IP:
rc = tlv_to_bgp_encap_type_l2tpv3overip (stlv, &tto->bgpinfo.l2tpv3_ip); rc = tlv_to_bgp_encap_type_l2tpv3overip(
stlv, &tto->bgpinfo.l2tpv3_ip);
break; break;
case BGP_ENCAP_TYPE_GRE: case BGP_ENCAP_TYPE_GRE:
@ -194,25 +186,23 @@ rfapi_encap_tlv_to_un_option (struct attr *attr)
break; break;
case BGP_ENCAP_TYPE_TRANSMIT_TUNNEL_ENDPOINT: case BGP_ENCAP_TYPE_TRANSMIT_TUNNEL_ENDPOINT:
rc = tlv_to_bgp_encap_type_transmit_tunnel_endpoint (stlv, rc = tlv_to_bgp_encap_type_transmit_tunnel_endpoint(
&tto->bgpinfo.transmit_tunnel_endpoint); stlv, &tto->bgpinfo.transmit_tunnel_endpoint);
break; break;
case BGP_ENCAP_TYPE_IPSEC_IN_TUNNEL_MODE: case BGP_ENCAP_TYPE_IPSEC_IN_TUNNEL_MODE:
rc = tlv_to_bgp_encap_type_ipsec_in_tunnel_mode (stlv, rc = tlv_to_bgp_encap_type_ipsec_in_tunnel_mode(
&tto->bgpinfo.ipsec_tunnel); stlv, &tto->bgpinfo.ipsec_tunnel);
break; break;
case BGP_ENCAP_TYPE_IP_IN_IP_TUNNEL_WITH_IPSEC_TRANSPORT_MODE: case BGP_ENCAP_TYPE_IP_IN_IP_TUNNEL_WITH_IPSEC_TRANSPORT_MODE:
rc = rc = tlv_to_bgp_encap_type_ip_in_ip_tunnel_with_ipsec_transport_mode(
tlv_to_bgp_encap_type_ip_in_ip_tunnel_with_ipsec_transport_mode (stlv, stlv, &tto->bgpinfo.ip_ipsec);
&tto->bgpinfo.ip_ipsec);
break; break;
case BGP_ENCAP_TYPE_MPLS_IN_IP_TUNNEL_WITH_IPSEC_TRANSPORT_MODE: case BGP_ENCAP_TYPE_MPLS_IN_IP_TUNNEL_WITH_IPSEC_TRANSPORT_MODE:
rc = rc = tlv_to_bgp_encap_type_mpls_in_ip_tunnel_with_ipsec_transport_mode(
tlv_to_bgp_encap_type_mpls_in_ip_tunnel_with_ipsec_transport_mode stlv, &tto->bgpinfo.mpls_ipsec);
(stlv, &tto->bgpinfo.mpls_ipsec);
break; break;
case BGP_ENCAP_TYPE_IP_IN_IP: case BGP_ENCAP_TYPE_IP_IN_IP:
@ -232,15 +222,18 @@ rfapi_encap_tlv_to_un_option (struct attr *attr)
break; break;
case BGP_ENCAP_TYPE_MPLS_IN_GRE: case BGP_ENCAP_TYPE_MPLS_IN_GRE:
rc = tlv_to_bgp_encap_type_mpls_in_gre (stlv, &tto->bgpinfo.mpls_gre); rc = tlv_to_bgp_encap_type_mpls_in_gre(stlv,
&tto->bgpinfo.mpls_gre);
break; break;
case BGP_ENCAP_TYPE_VXLAN_GPE: case BGP_ENCAP_TYPE_VXLAN_GPE:
rc = tlv_to_bgp_encap_type_vxlan_gpe (stlv, &tto->bgpinfo.vxlan_gpe); rc = tlv_to_bgp_encap_type_vxlan_gpe(stlv,
&tto->bgpinfo.vxlan_gpe);
break; break;
case BGP_ENCAP_TYPE_MPLS_IN_UDP: case BGP_ENCAP_TYPE_MPLS_IN_UDP:
rc = tlv_to_bgp_encap_type_mpls_in_udp (stlv, &tto->bgpinfo.mpls_udp); rc = tlv_to_bgp_encap_type_mpls_in_udp(stlv,
&tto->bgpinfo.mpls_udp);
break; break;
case BGP_ENCAP_TYPE_PBB: case BGP_ENCAP_TYPE_PBB:
@ -248,13 +241,12 @@ rfapi_encap_tlv_to_un_option (struct attr *attr)
break; break;
default: default:
vnc_zlog_debug_verbose ("%s: unknown tunnel type %d", vnc_zlog_debug_verbose("%s: unknown tunnel type %d", __func__,
__func__, attre->encap_tunneltype); attr->encap_tunneltype);
rc = -1; rc = -1;
break; break;
} }
if (rc) if (rc) {
{
XFREE(MTYPE_RFAPI_UN_OPTION, uo); XFREE(MTYPE_RFAPI_UN_OPTION, uo);
uo = NULL; uo = NULL;
} }
@ -265,10 +257,8 @@ rfapi_encap_tlv_to_un_option (struct attr *attr)
* SUBTLV PRINT * SUBTLV PRINT
***********************************************************************/ ***********************************************************************/
static void static void subtlv_print_encap_l2tpv3_over_ip(
subtlv_print_encap_l2tpv3_over_ip ( void *stream, int column_offset,
void *stream,
int column_offset,
struct bgp_tea_subtlv_encap_l2tpv3_over_ip *st) struct bgp_tea_subtlv_encap_l2tpv3_over_ip *st)
{ {
int (*fp)(void *, const char *, ...); int (*fp)(void *, const char *, ...);
@ -285,14 +275,11 @@ subtlv_print_encap_l2tpv3_over_ip (
vty_newline); vty_newline);
fp(out, "%*s SessionID: %d%s", column_offset, "", st->sessionid, fp(out, "%*s SessionID: %d%s", column_offset, "", st->sessionid,
vty_newline); vty_newline);
fp (out, "%*s Cookie: (length %d)%s", column_offset, "", st->cookie_length, fp(out, "%*s Cookie: (length %d)%s", column_offset, "",
vty_newline); st->cookie_length, vty_newline);
} }
static void static void subtlv_print_encap_gre(void *stream, int column_offset,
subtlv_print_encap_gre (
void *stream,
int column_offset,
struct bgp_tea_subtlv_encap_gre_key *st) struct bgp_tea_subtlv_encap_gre_key *st)
{ {
int (*fp)(void *, const char *, ...); int (*fp)(void *, const char *, ...);
@ -305,15 +292,13 @@ subtlv_print_encap_gre (
if (!st) if (!st)
return; return;
fp (out, "%*s%s%s", column_offset, "", "SubTLV: Encap(GRE)", vty_newline); fp(out, "%*s%s%s", column_offset, "", "SubTLV: Encap(GRE)",
vty_newline);
fp(out, "%*s GRE key: %d (0x%x)%s", column_offset, "", st->gre_key, fp(out, "%*s GRE key: %d (0x%x)%s", column_offset, "", st->gre_key,
st->gre_key, vty_newline); st->gre_key, vty_newline);
} }
static void static void subtlv_print_encap_pbb(void *stream, int column_offset,
subtlv_print_encap_pbb (
void *stream,
int column_offset,
struct bgp_tea_subtlv_encap_pbb *st) struct bgp_tea_subtlv_encap_pbb *st)
{ {
int (*fp)(void *, const char *, ...); int (*fp)(void *, const char *, ...);
@ -326,29 +311,22 @@ subtlv_print_encap_pbb (
if (!st) if (!st)
return; return;
fp (out, "%*s%s%s", column_offset, "", "SubTLV: Encap(PBB)", vty_newline); fp(out, "%*s%s%s", column_offset, "", "SubTLV: Encap(PBB)",
if (st->flag_isid) vty_newline);
{ if (st->flag_isid) {
fp(out, "%*s ISID: %d (0x%x)%s", column_offset, "", st->isid, fp(out, "%*s ISID: %d (0x%x)%s", column_offset, "", st->isid,
st->isid, vty_newline); st->isid, vty_newline);
} }
if (st->flag_vid) if (st->flag_vid) {
{ fp(out, "%*s VID: %d (0x%x)%s", column_offset, "", st->vid,
fp (out, "%*s VID: %d (0x%x)%s", column_offset, "", st->vid, st->vid, st->vid, vty_newline);
vty_newline);
} }
fp (out, "%*s MACADDR %02x:%02x:%02x:%02x:%02x:%02x%s", fp(out, "%*s MACADDR %02x:%02x:%02x:%02x:%02x:%02x%s", column_offset,
column_offset, "", "", st->macaddr[0], st->macaddr[1], st->macaddr[2], st->macaddr[3],
st->macaddr[0], st->macaddr[4], st->macaddr[5], vty_newline);
st->macaddr[1],
st->macaddr[2],
st->macaddr[3], st->macaddr[4], st->macaddr[5], vty_newline);
} }
static void static void subtlv_print_proto_type(void *stream, int column_offset,
subtlv_print_proto_type (
void *stream,
int column_offset,
struct bgp_tea_subtlv_proto_type *st) struct bgp_tea_subtlv_proto_type *st)
{ {
int (*fp)(void *, const char *, ...); int (*fp)(void *, const char *, ...);
@ -363,14 +341,11 @@ subtlv_print_proto_type (
fp(out, "%*s%s%s", column_offset, "", "SubTLV: Encap(Proto Type)", fp(out, "%*s%s%s", column_offset, "", "SubTLV: Encap(Proto Type)",
vty_newline); vty_newline);
fp (out, "%*s Proto %d (0x%x)%s", column_offset, "", st->proto, st->proto, fp(out, "%*s Proto %d (0x%x)%s", column_offset, "", st->proto,
vty_newline); st->proto, vty_newline);
} }
static void static void subtlv_print_color(void *stream, int column_offset,
subtlv_print_color (
void *stream,
int column_offset,
struct bgp_tea_subtlv_color *st) struct bgp_tea_subtlv_color *st)
{ {
int (*fp)(void *, const char *, ...); int (*fp)(void *, const char *, ...);
@ -384,14 +359,11 @@ subtlv_print_color (
return; return;
fp(out, "%*s%s%s", column_offset, "", "SubTLV: Color", vty_newline); fp(out, "%*s%s%s", column_offset, "", "SubTLV: Color", vty_newline);
fp (out, "%*s Color: %d (0x%x)", column_offset, "", st->color, st->color, fp(out, "%*s Color: %d (0x%x)", column_offset, "", st->color,
vty_newline); st->color, vty_newline);
} }
static void static void subtlv_print_ipsec_ta(void *stream, int column_offset,
subtlv_print_ipsec_ta (
void *stream,
int column_offset,
struct bgp_tea_subtlv_ipsec_ta *st) struct bgp_tea_subtlv_ipsec_ta *st)
{ {
int (*fp)(void *, const char *, ...); int (*fp)(void *, const char *, ...);
@ -416,9 +388,7 @@ subtlv_print_ipsec_ta (
***********************************************************************/ ***********************************************************************/
static void static void
print_encap_type_l2tpv3overip ( print_encap_type_l2tpv3overip(void *stream, int column_offset,
void *stream,
int column_offset,
struct bgp_encap_type_l2tpv3_over_ip *bet) struct bgp_encap_type_l2tpv3_over_ip *bet)
{ {
const char *type = "L2TPv3 over IP"; const char *type = "L2TPv3 over IP";
@ -440,10 +410,7 @@ print_encap_type_l2tpv3overip (
subtlv_print_color(stream, column_offset + 2, &bet->st_color); subtlv_print_color(stream, column_offset + 2, &bet->st_color);
} }
static void static void print_encap_type_gre(void *stream, int column_offset,
print_encap_type_gre (
void *stream,
int column_offset,
struct bgp_encap_type_gre *bet) struct bgp_encap_type_gre *bet)
{ {
const char *type = "GRE"; const char *type = "GRE";
@ -464,10 +431,7 @@ print_encap_type_gre (
subtlv_print_color(stream, column_offset + 2, &bet->st_color); subtlv_print_color(stream, column_offset + 2, &bet->st_color);
} }
static void static void print_encap_type_ip_in_ip(void *stream, int column_offset,
print_encap_type_ip_in_ip (
void *stream,
int column_offset,
struct bgp_encap_type_ip_in_ip *bet) struct bgp_encap_type_ip_in_ip *bet)
{ {
const char *type = "IP in IP"; const char *type = "IP in IP";
@ -487,10 +451,8 @@ print_encap_type_ip_in_ip (
subtlv_print_color(stream, column_offset + 2, &bet->st_color); subtlv_print_color(stream, column_offset + 2, &bet->st_color);
} }
static void static void print_encap_type_transmit_tunnel_endpoint(
print_encap_type_transmit_tunnel_endpoint ( void *stream, int column_offset,
void *stream,
int column_offset,
struct bgp_encap_type_transmit_tunnel_endpoint *bet) struct bgp_encap_type_transmit_tunnel_endpoint *bet)
{ {
const char *type = "Transmit Tunnel Endpoint"; const char *type = "Transmit Tunnel Endpoint";
@ -509,10 +471,8 @@ print_encap_type_transmit_tunnel_endpoint (
/* no subtlvs for this type */ /* no subtlvs for this type */
} }
static void static void print_encap_type_ipsec_in_tunnel_mode(
print_encap_type_ipsec_in_tunnel_mode ( void *stream, int column_offset,
void *stream,
int column_offset,
struct bgp_encap_type_ipsec_in_tunnel_mode *bet) struct bgp_encap_type_ipsec_in_tunnel_mode *bet)
{ {
const char *type = "IPSEC in Tunnel mode"; const char *type = "IPSEC in Tunnel mode";
@ -530,10 +490,8 @@ print_encap_type_ipsec_in_tunnel_mode (
subtlv_print_ipsec_ta(stream, column_offset + 2, &bet->st_ipsec_ta); subtlv_print_ipsec_ta(stream, column_offset + 2, &bet->st_ipsec_ta);
} }
static void static void print_encap_type_ip_in_ip_tunnel_with_ipsec_transport_mode(
print_encap_type_ip_in_ip_tunnel_with_ipsec_transport_mode ( void *stream, int column_offset,
void *stream,
int column_offset,
struct bgp_encap_type_ip_in_ip_tunnel_with_ipsec_transport_mode *bet) struct bgp_encap_type_ip_in_ip_tunnel_with_ipsec_transport_mode *bet)
{ {
const char *type = "IP in IP Tunnel with IPSEC transport mode"; const char *type = "IP in IP Tunnel with IPSEC transport mode";
@ -552,10 +510,8 @@ print_encap_type_ip_in_ip_tunnel_with_ipsec_transport_mode (
subtlv_print_ipsec_ta(stream, column_offset + 2, &bet->st_ipsec_ta); subtlv_print_ipsec_ta(stream, column_offset + 2, &bet->st_ipsec_ta);
} }
static void static void print_encap_type_mpls_in_ip_tunnel_with_ipsec_transport_mode(
print_encap_type_mpls_in_ip_tunnel_with_ipsec_transport_mode ( void *stream, int column_offset,
void *stream,
int column_offset,
struct bgp_encap_type_mpls_in_ip_tunnel_with_ipsec_transport_mode *bet) struct bgp_encap_type_mpls_in_ip_tunnel_with_ipsec_transport_mode *bet)
{ {
const char *type = "MPLS in IP Tunnel with IPSEC transport mode"; const char *type = "MPLS in IP Tunnel with IPSEC transport mode";
@ -575,10 +531,7 @@ print_encap_type_mpls_in_ip_tunnel_with_ipsec_transport_mode (
} }
static void static void print_encap_type_pbb(void *stream, int column_offset,
print_encap_type_pbb (
void *stream,
int column_offset,
struct bgp_encap_type_pbb *bet) struct bgp_encap_type_pbb *bet)
{ {
const char *type = "PBB"; const char *type = "PBB";
@ -598,10 +551,7 @@ print_encap_type_pbb (
} }
static void static void print_encap_type_vxlan(void *stream, int column_offset,
print_encap_type_vxlan (
void *stream,
int column_offset,
struct bgp_encap_type_vxlan *bet) struct bgp_encap_type_vxlan *bet)
{ {
const char *type = "VXLAN"; const char *type = "VXLAN";
@ -621,10 +571,7 @@ print_encap_type_vxlan (
} }
static void static void print_encap_type_nvgre(void *stream, int column_offset,
print_encap_type_nvgre (
void *stream,
int column_offset,
struct bgp_encap_type_nvgre *bet) struct bgp_encap_type_nvgre *bet)
{ {
const char *type = "NVGRE"; const char *type = "NVGRE";
@ -643,10 +590,7 @@ print_encap_type_nvgre (
/* no subtlvs for this type */ /* no subtlvs for this type */
} }
static void static void print_encap_type_mpls(void *stream, int column_offset,
print_encap_type_mpls (
void *stream,
int column_offset,
struct bgp_encap_type_mpls *bet) struct bgp_encap_type_mpls *bet)
{ {
const char *type = "MPLS"; const char *type = "MPLS";
@ -665,10 +609,7 @@ print_encap_type_mpls (
/* no subtlvs for this type */ /* no subtlvs for this type */
} }
static void static void print_encap_type_mpls_in_gre(void *stream, int column_offset,
print_encap_type_mpls_in_gre (
void *stream,
int column_offset,
struct bgp_encap_type_mpls_in_gre *bet) struct bgp_encap_type_mpls_in_gre *bet)
{ {
const char *type = "MPLS in GRE"; const char *type = "MPLS in GRE";
@ -687,10 +628,7 @@ print_encap_type_mpls_in_gre (
/* no subtlvs for this type */ /* no subtlvs for this type */
} }
static void static void print_encap_type_vxlan_gpe(void *stream, int column_offset,
print_encap_type_vxlan_gpe (
void *stream,
int column_offset,
struct bgp_encap_type_vxlan_gpe *bet) struct bgp_encap_type_vxlan_gpe *bet)
{ {
const char *type = "VXLAN GPE"; const char *type = "VXLAN GPE";
@ -709,10 +647,7 @@ print_encap_type_vxlan_gpe (
/* no subtlvs for this type */ /* no subtlvs for this type */
} }
static void static void print_encap_type_mpls_in_udp(void *stream, int column_offset,
print_encap_type_mpls_in_udp (
void *stream,
int column_offset,
struct bgp_encap_type_mpls_in_udp *bet) struct bgp_encap_type_mpls_in_udp *bet)
{ {
const char *type = "MPLS in UDP"; const char *type = "MPLS in UDP";
@ -731,14 +666,10 @@ print_encap_type_mpls_in_udp (
/* no subtlvs for this type */ /* no subtlvs for this type */
} }
void void rfapi_print_tunneltype_option(void *stream, int column_offset,
rfapi_print_tunneltype_option (
void *stream,
int column_offset,
struct rfapi_tunneltype_option *tto) struct rfapi_tunneltype_option *tto)
{ {
switch (tto->type) switch (tto->type) {
{
case BGP_ENCAP_TYPE_L2TPV3_OVER_IP: case BGP_ENCAP_TYPE_L2TPV3_OVER_IP:
print_encap_type_l2tpv3overip(stream, column_offset, print_encap_type_l2tpv3overip(stream, column_offset,
&tto->bgpinfo.l2tpv3_ip); &tto->bgpinfo.l2tpv3_ip);
@ -749,41 +680,44 @@ rfapi_print_tunneltype_option (
break; break;
case BGP_ENCAP_TYPE_TRANSMIT_TUNNEL_ENDPOINT: case BGP_ENCAP_TYPE_TRANSMIT_TUNNEL_ENDPOINT:
print_encap_type_transmit_tunnel_endpoint (stream, column_offset, print_encap_type_transmit_tunnel_endpoint(
stream, column_offset,
&tto->bgpinfo.transmit_tunnel_endpoint); &tto->bgpinfo.transmit_tunnel_endpoint);
break; break;
case BGP_ENCAP_TYPE_IPSEC_IN_TUNNEL_MODE: case BGP_ENCAP_TYPE_IPSEC_IN_TUNNEL_MODE:
print_encap_type_ipsec_in_tunnel_mode (stream, column_offset, print_encap_type_ipsec_in_tunnel_mode(
&tto->bgpinfo.ipsec_tunnel); stream, column_offset, &tto->bgpinfo.ipsec_tunnel);
break; break;
case BGP_ENCAP_TYPE_IP_IN_IP_TUNNEL_WITH_IPSEC_TRANSPORT_MODE: case BGP_ENCAP_TYPE_IP_IN_IP_TUNNEL_WITH_IPSEC_TRANSPORT_MODE:
print_encap_type_ip_in_ip_tunnel_with_ipsec_transport_mode (stream, print_encap_type_ip_in_ip_tunnel_with_ipsec_transport_mode(
column_offset, stream, column_offset, &tto->bgpinfo.ip_ipsec);
&tto->bgpinfo.ip_ipsec);
break; break;
case BGP_ENCAP_TYPE_MPLS_IN_IP_TUNNEL_WITH_IPSEC_TRANSPORT_MODE: case BGP_ENCAP_TYPE_MPLS_IN_IP_TUNNEL_WITH_IPSEC_TRANSPORT_MODE:
print_encap_type_mpls_in_ip_tunnel_with_ipsec_transport_mode (stream, print_encap_type_mpls_in_ip_tunnel_with_ipsec_transport_mode(
column_offset, stream, column_offset, &tto->bgpinfo.mpls_ipsec);
&tto->bgpinfo.mpls_ipsec);
break; break;
case BGP_ENCAP_TYPE_IP_IN_IP: case BGP_ENCAP_TYPE_IP_IN_IP:
print_encap_type_ip_in_ip (stream, column_offset, &tto->bgpinfo.ip_ip); print_encap_type_ip_in_ip(stream, column_offset,
&tto->bgpinfo.ip_ip);
break; break;
case BGP_ENCAP_TYPE_VXLAN: case BGP_ENCAP_TYPE_VXLAN:
print_encap_type_vxlan (stream, column_offset, &tto->bgpinfo.vxlan); print_encap_type_vxlan(stream, column_offset,
&tto->bgpinfo.vxlan);
break; break;
case BGP_ENCAP_TYPE_NVGRE: case BGP_ENCAP_TYPE_NVGRE:
print_encap_type_nvgre (stream, column_offset, &tto->bgpinfo.nvgre); print_encap_type_nvgre(stream, column_offset,
&tto->bgpinfo.nvgre);
break; break;
case BGP_ENCAP_TYPE_MPLS: case BGP_ENCAP_TYPE_MPLS:
print_encap_type_mpls (stream, column_offset, &tto->bgpinfo.mpls); print_encap_type_mpls(stream, column_offset,
&tto->bgpinfo.mpls);
break; break;
case BGP_ENCAP_TYPE_MPLS_IN_GRE: case BGP_ENCAP_TYPE_MPLS_IN_GRE:

View File

@ -22,20 +22,13 @@
#define RFAPI_BGP_ENCAP_TYPE_DEFAULT BGP_ENCAP_TYPE_IP_IN_IP #define RFAPI_BGP_ENCAP_TYPE_DEFAULT BGP_ENCAP_TYPE_IP_IN_IP
extern bgp_encap_types extern bgp_encap_types
rfapi_tunneltype_option_to_tlv ( rfapi_tunneltype_option_to_tlv(struct bgp *bgp, struct rfapi_ip_addr *ea,
struct bgp *bgp,
struct rfapi_ip_addr *ea,
struct rfapi_tunneltype_option *tto, struct rfapi_tunneltype_option *tto,
struct attr *attr, struct attr *attr, int always_add);
int always_add);
extern struct rfapi_un_option * extern struct rfapi_un_option *rfapi_encap_tlv_to_un_option(struct attr *attr);
rfapi_encap_tlv_to_un_option (struct attr *attr);
extern void extern void rfapi_print_tunneltype_option(void *stream, int column_offset,
rfapi_print_tunneltype_option (
void *stream,
int column_offset,
struct rfapi_tunneltype_option *tto); struct rfapi_tunneltype_option *tto);

File diff suppressed because it is too large Load Diff

View File

@ -34,8 +34,7 @@
* routes are not segregated by RD - the RD is stored in bgp_info_extra * routes are not segregated by RD - the RD is stored in bgp_info_extra
* and is needed to determine if two prefixes are the same. * and is needed to determine if two prefixes are the same.
*/ */
struct rfapi_import_table struct rfapi_import_table {
{
struct rfapi_import_table *next; struct rfapi_import_table *next;
struct rfapi_nve_group_cfg *rfg; struct rfapi_nve_group_cfg *rfg;
struct ecommunity *rt_import_list; /* copied from nve grp */ struct ecommunity *rt_import_list; /* copied from nve grp */
@ -56,7 +55,8 @@ struct rfapi_import_table
(((bi)->type == ZEBRA_ROUTE_BGP) && ((bi)->sub_type == BGP_ROUTE_RFP)) (((bi)->type == ZEBRA_ROUTE_BGP) && ((bi)->sub_type == BGP_ROUTE_RFP))
#define RFAPI_DIRECT_IMPORT_BI(bi) \ #define RFAPI_DIRECT_IMPORT_BI(bi) \
(((bi)->type == ZEBRA_ROUTE_BGP_DIRECT) || ((bi)->type == ZEBRA_ROUTE_BGP_DIRECT_EXT)) (((bi)->type == ZEBRA_ROUTE_BGP_DIRECT) \
|| ((bi)->type == ZEBRA_ROUTE_BGP_DIRECT_EXT))
#define RFAPI_UPDATE_ITABLE_COUNT(bi, itable, afi, cnt) \ #define RFAPI_UPDATE_ITABLE_COUNT(bi, itable, afi, cnt) \
if (RFAPI_LOCAL_BI(bi)) { \ if (RFAPI_LOCAL_BI(bi)) { \
@ -68,37 +68,25 @@ struct rfapi_import_table
(itable)->remote_count[(afi)] += (cnt); \ (itable)->remote_count[(afi)] += (cnt); \
} }
extern uint8_t extern uint8_t rfapiRfpCost(struct attr *attr);
rfapiRfpCost (struct attr *attr);
extern void extern void rfapiDebugBacktrace(void);
rfapiDebugBacktrace (void);
extern void extern void rfapiCheckRouteCount(void);
rfapiCheckRouteCount (void);
/* /*
* Print BI in an Import Table * Print BI in an Import Table
*/ */
extern void extern void rfapiPrintBi(void *stream, struct bgp_info *bi);
rfapiPrintBi (void *stream, struct bgp_info *bi);
extern void extern void rfapiShowImportTable(void *stream, const char *label,
rfapiShowImportTable ( struct route_table *rt, int isvpn);
void *stream,
const char *label,
struct route_table *rt,
int isvpn);
extern struct rfapi_import_table * extern struct rfapi_import_table *
rfapiImportTableRefAdd ( rfapiImportTableRefAdd(struct bgp *bgp, struct ecommunity *rt_import_list,
struct bgp *bgp,
struct ecommunity *rt_import_list,
struct rfapi_nve_group_cfg *rfg); struct rfapi_nve_group_cfg *rfg);
extern void extern void rfapiImportTableRefDelByIt(struct bgp *bgp,
rfapiImportTableRefDelByIt (
struct bgp *bgp,
struct rfapi_import_table *it_target); struct rfapi_import_table *it_target);
@ -111,53 +99,41 @@ rfapiImportTableRefDelByIt (
* then return those, and also include all the non-removed routes from the * then return those, and also include all the non-removed routes from the
* next less-specific node (i.e., this node's parent) at the end. * next less-specific node (i.e., this node's parent) at the end.
*/ */
extern struct rfapi_next_hop_entry * extern struct rfapi_next_hop_entry *rfapiRouteNode2NextHopList(
rfapiRouteNode2NextHopList ( struct route_node *rn, uint32_t lifetime, /* put into nexthop entries */
struct route_node *rn,
uint32_t lifetime, /* put into nexthop entries */
struct rfapi_ip_addr *exclude_vnaddr, /* omit routes to same NVE */ struct rfapi_ip_addr *exclude_vnaddr, /* omit routes to same NVE */
struct route_table *rfd_rib_table, /* preload this NVE rib table */ struct route_table *rfd_rib_table, /* preload this NVE rib table */
struct prefix *pfx_target_original); /* query target */ struct prefix *pfx_target_original); /* query target */
extern struct rfapi_next_hop_entry * extern struct rfapi_next_hop_entry *rfapiRouteTable2NextHopList(
rfapiRouteTable2NextHopList (
struct route_table *rt, struct route_table *rt,
uint32_t lifetime, /* put into nexthop entries */ uint32_t lifetime, /* put into nexthop entries */
struct rfapi_ip_addr *exclude_vnaddr, /* omit routes to same NVE */ struct rfapi_ip_addr *exclude_vnaddr, /* omit routes to same NVE */
struct route_table *rfd_rib_table, /* preload this NVE rib table */ struct route_table *rfd_rib_table, /* preload this NVE rib table */
struct prefix *pfx_target_original); /* query target */ struct prefix *pfx_target_original); /* query target */
extern struct rfapi_next_hop_entry * extern struct rfapi_next_hop_entry *rfapiEthRouteTable2NextHopList(
rfapiEthRouteTable2NextHopList ( uint32_t logical_net_id, struct rfapi_ip_prefix *rprefix,
uint32_t logical_net_id,
struct rfapi_ip_prefix *rprefix,
uint32_t lifetime, /* put into nexthop entries */ uint32_t lifetime, /* put into nexthop entries */
struct rfapi_ip_addr *exclude_vnaddr, /* omit routes to same NVE */ struct rfapi_ip_addr *exclude_vnaddr, /* omit routes to same NVE */
struct route_table *rib_route_table, /* preload NVE rib node */ struct route_table *rib_route_table, /* preload NVE rib node */
struct prefix *pfx_target_original); /* query target */ struct prefix *pfx_target_original); /* query target */
extern int extern int rfapiEcommunitiesIntersect(struct ecommunity *e1,
rfapiEcommunitiesIntersect (struct ecommunity *e1, struct ecommunity *e2); struct ecommunity *e2);
extern void extern void rfapiCheckRefcount(struct route_node *rn, safi_t safi,
rfapiCheckRefcount (struct route_node *rn, safi_t safi, int lockoffset); int lockoffset);
extern int extern int rfapiHasNonRemovedRoutes(struct route_node *rn);
rfapiHasNonRemovedRoutes (struct route_node *rn);
extern int extern int rfapiProcessDeferredClose(struct thread *t);
rfapiProcessDeferredClose (struct thread *t);
extern int extern int rfapiGetUnAddrOfVpnBi(struct bgp_info *bi, struct prefix *p);
rfapiGetUnAddrOfVpnBi (struct bgp_info *bi, struct prefix *p);
extern void extern void rfapiNexthop2Prefix(struct attr *attr, struct prefix *p);
rfapiNexthop2Prefix (struct attr *attr, struct prefix *p);
extern void extern void rfapiUnicastNexthop2Prefix(afi_t afi, struct attr *attr,
rfapiUnicastNexthop2Prefix (
afi_t afi,
struct attr *attr,
struct prefix *p); struct prefix *p);
/* Filtered Import Function actions */ /* Filtered Import Function actions */
@ -165,51 +141,35 @@ rfapiUnicastNexthop2Prefix (
#define FIF_ACTION_WITHDRAW 1 #define FIF_ACTION_WITHDRAW 1
#define FIF_ACTION_KILL 2 #define FIF_ACTION_KILL 2
extern void extern void rfapiBgpInfoFilteredImportVPN(
rfapiBgpInfoFilteredImportVPN ( struct rfapi_import_table *import_table, int action, struct peer *peer,
struct rfapi_import_table *import_table,
int action,
struct peer *peer,
void *rfd, /* set for looped back routes */ void *rfd, /* set for looped back routes */
struct prefix *p, struct prefix *p,
struct prefix *aux_prefix, /* AFI_ETHER: optional IP */ struct prefix *aux_prefix, /* AFI_ETHER: optional IP */
afi_t afi, afi_t afi, struct prefix_rd *prd,
struct prefix_rd *prd,
struct attr *attr, /* part of bgp_info */ struct attr *attr, /* part of bgp_info */
u_char type, /* part of bgp_info */ u_char type, /* part of bgp_info */
u_char sub_type, /* part of bgp_info */ u_char sub_type, /* part of bgp_info */
uint32_t *label); /* part of bgp_info */ uint32_t *label); /* part of bgp_info */
extern struct rfapi_next_hop_entry * extern struct rfapi_next_hop_entry *rfapiEthRouteNode2NextHopList(
rfapiEthRouteNode2NextHopList ( struct route_node *rn, struct rfapi_ip_prefix *rprefix,
struct route_node *rn,
struct rfapi_ip_prefix *rprefix,
uint32_t lifetime, /* put into nexthop entries */ uint32_t lifetime, /* put into nexthop entries */
struct rfapi_ip_addr *exclude_vnaddr, /* omit routes to same NVE */ struct rfapi_ip_addr *exclude_vnaddr, /* omit routes to same NVE */
struct route_table *rib_route_table, /* preload NVE rib table */ struct route_table *rib_route_table, /* preload NVE rib table */
struct prefix *pfx_target_original); /* query target */ struct prefix *pfx_target_original); /* query target */
extern struct rfapi_import_table * extern struct rfapi_import_table *rfapiMacImportTableGetNoAlloc(struct bgp *bgp,
rfapiMacImportTableGetNoAlloc (
struct bgp *bgp,
uint32_t lni); uint32_t lni);
extern struct rfapi_import_table * extern struct rfapi_import_table *rfapiMacImportTableGet(struct bgp *bgp,
rfapiMacImportTableGet (
struct bgp *bgp,
uint32_t lni); uint32_t lni);
extern int extern int rfapiGetL2o(struct attr *attr, struct rfapi_l2address_option *l2o);
rfapiGetL2o (
struct attr *attr,
struct rfapi_l2address_option *l2o);
extern int rfapiEcommunityGetLNI ( extern int rfapiEcommunityGetLNI(struct ecommunity *ecom, uint32_t *lni);
struct ecommunity *ecom,
uint32_t *lni);
extern int rfapiEcommunityGetEthernetTag ( extern int rfapiEcommunityGetEthernetTag(struct ecommunity *ecom,
struct ecommunity *ecom,
uint16_t *tag_id); uint16_t *tag_id);
/* enable for debugging; disable for performance */ /* enable for debugging; disable for performance */
@ -239,14 +199,10 @@ extern int rfapiEcommunityGetEthernetTag (
* return value: * return value:
* void * void
--------------------------------------------*/ --------------------------------------------*/
extern void extern void rfapiDeleteRemotePrefixes(struct prefix *un, struct prefix *vn,
rfapiDeleteRemotePrefixes (
struct prefix *un,
struct prefix *vn,
struct prefix *p, struct prefix *p,
struct rfapi_import_table *it, struct rfapi_import_table *it,
int delete_active, int delete_active, int delete_holddown,
int delete_holddown,
uint32_t *pARcount, /* active routes */ uint32_t *pARcount, /* active routes */
uint32_t *pAHcount, /* active nves */ uint32_t *pAHcount, /* active nves */
uint32_t *pHRcount, /* holddown routes */ uint32_t *pHRcount, /* holddown routes */
@ -267,9 +223,7 @@ rfapiDeleteRemotePrefixes (
* return value: * return value:
* void * void
--------------------------------------------*/ --------------------------------------------*/
extern void extern void rfapiCountAllItRoutes(int *pALRcount, /* active local routes */
rfapiCountAllItRoutes (
int *pALRcount, /* active local routes */
int *pARRcount, /* active remote routes */ int *pARRcount, /* active remote routes */
int *pHRcount, /* holddown routes */ int *pHRcount, /* holddown routes */
int *pIRcount); /* direct imported routes */ int *pIRcount); /* direct imported routes */
@ -287,7 +241,6 @@ rfapiCountAllItRoutes (
* and RFAPI_LIFETIME_INFINITE_WITHDRAW_DELAY * and RFAPI_LIFETIME_INFINITE_WITHDRAW_DELAY
* *
--------------------------------------------*/ --------------------------------------------*/
extern uint32_t extern uint32_t rfapiGetHolddownFromLifetime(uint32_t lifetime);
rfapiGetHolddownFromLifetime (uint32_t lifetime);
#endif /* QUAGGA_HGP_RFAPI_IMPORT_H */ #endif /* QUAGGA_HGP_RFAPI_IMPORT_H */

File diff suppressed because it is too large Load Diff

View File

@ -29,8 +29,7 @@
* These get attached to the nodes in an import table (using "aggregate" ptr) * These get attached to the nodes in an import table (using "aggregate" ptr)
* to indicate which nves are interested in a prefix/target * to indicate which nves are interested in a prefix/target
*/ */
struct rfapi_monitor_vpn struct rfapi_monitor_vpn {
{
struct rfapi_monitor_vpn *next; /* chain from struct route_node */ struct rfapi_monitor_vpn *next; /* chain from struct route_node */
struct rfapi_descriptor *rfd; /* which NVE requested the route */ struct rfapi_descriptor *rfd; /* which NVE requested the route */
struct prefix p; /* constant: pfx in original request */ struct prefix p; /* constant: pfx in original request */
@ -42,8 +41,7 @@ struct rfapi_monitor_vpn
struct thread *timer; struct thread *timer;
}; };
struct rfapi_monitor_encap struct rfapi_monitor_encap {
{
struct rfapi_monitor_encap *next; struct rfapi_monitor_encap *next;
struct rfapi_monitor_encap *prev; struct rfapi_monitor_encap *prev;
struct route_node *node; /* VPN node */ struct route_node *node; /* VPN node */
@ -51,8 +49,7 @@ struct rfapi_monitor_encap
struct route_node *rn; /* parent node */ struct route_node *rn; /* parent node */
}; };
struct rfapi_monitor_eth struct rfapi_monitor_eth {
{
struct rfapi_monitor_eth *next; /* for use in vpn0_queries list */ struct rfapi_monitor_eth *next; /* for use in vpn0_queries list */
struct rfapi_descriptor *rfd; /* which NVE requested the route */ struct rfapi_descriptor *rfd; /* which NVE requested the route */
struct ethaddr macaddr; struct ethaddr macaddr;
@ -75,35 +72,36 @@ struct rfapi_monitor_eth
* - one lock per chained struct rfapi_monitor_encap * - one lock per chained struct rfapi_monitor_encap
* *
*/ */
struct rfapi_it_extra struct rfapi_it_extra {
{ union {
union struct {
{
struct
{
struct rfapi_monitor_vpn *v; struct rfapi_monitor_vpn *v;
struct skiplist *idx_rd; /* RD index */ struct skiplist *idx_rd; /* RD index */
struct skiplist *mon_eth; /* ether queries */ struct skiplist *mon_eth; /* ether queries */
struct struct {
{ /* routes with UN addrs, either cached encap or
/* routes with UN addrs, either cached encap or Encap TLV */ * Encap TLV */
int valid_interior_count; int valid_interior_count;
/* unicast exterior routes, key=bi, val=allocated prefix */ /* unicast exterior routes, key=bi,
* val=allocated prefix */
struct skiplist *source; struct skiplist *source;
} e; } e;
} vpn; } vpn;
struct struct {
{
struct rfapi_monitor_encap *e; struct rfapi_monitor_encap *e;
} encap; } encap;
} u; } u;
}; };
#define RFAPI_IT_EXTRA_GET(rn) ((struct rfapi_it_extra *)( \ #define RFAPI_IT_EXTRA_GET(rn) \
(rn)->aggregate? (rn)->aggregate: \ ((struct rfapi_it_extra \
(route_lock_node(rn), (rn)->aggregate = \ *)((rn)->aggregate \
XCALLOC(MTYPE_RFAPI_IT_EXTRA,sizeof(struct rfapi_it_extra))))) ? (rn)->aggregate \
: (route_lock_node(rn), \
(rn)->aggregate = XCALLOC( \
MTYPE_RFAPI_IT_EXTRA, \
sizeof(struct rfapi_it_extra)))))
#define RFAPI_RDINDEX(rn) \ #define RFAPI_RDINDEX(rn) \
((rn)->aggregate ? RFAPI_IT_EXTRA_GET(rn)->u.vpn.idx_rd : NULL) ((rn)->aggregate ? RFAPI_IT_EXTRA_GET(rn)->u.vpn.idx_rd : NULL)
@ -127,89 +125,65 @@ struct rfapi_it_extra
#define RFAPI_MONITOR_EXTERIOR(rn) (&(RFAPI_IT_EXTRA_GET(rn)->u.vpn.e)) #define RFAPI_MONITOR_EXTERIOR(rn) (&(RFAPI_IT_EXTRA_GET(rn)->u.vpn.e))
#define RFAPI_HAS_MONITOR_EXTERIOR(rn) (rn && rn->aggregate && \ #define RFAPI_HAS_MONITOR_EXTERIOR(rn) \
((struct rfapi_it_extra *)(rn->aggregate))->u.vpn.e.source && \ (rn && rn->aggregate \
!skiplist_first(((struct rfapi_it_extra *)(rn->aggregate))-> \ && ((struct rfapi_it_extra *)(rn->aggregate))->u.vpn.e.source \
u.vpn.e.source, NULL, NULL)) && !skiplist_first(((struct rfapi_it_extra *)(rn->aggregate)) \
->u.vpn.e.source, \
NULL, NULL))
extern void extern void rfapiMonitorLoopCheck(struct rfapi_monitor_vpn *mchain);
rfapiMonitorLoopCheck (struct rfapi_monitor_vpn *mchain);
extern void extern void rfapiMonitorCleanCheck(struct bgp *bgp);
rfapiMonitorCleanCheck (struct bgp *bgp);
extern void extern void rfapiMonitorCheckAttachAllowed(void);
rfapiMonitorCheckAttachAllowed (void);
extern void extern void rfapiMonitorExtraFlush(safi_t safi, struct route_node *rn);
rfapiMonitorExtraFlush (safi_t safi, struct route_node *rn);
extern struct route_node * extern struct route_node *
rfapiMonitorGetAttachNode(struct rfapi_descriptor *rfd, struct prefix *p); rfapiMonitorGetAttachNode(struct rfapi_descriptor *rfd, struct prefix *p);
extern void extern void rfapiMonitorAttachImportHd(struct rfapi_descriptor *rfd);
rfapiMonitorAttachImportHd (struct rfapi_descriptor *rfd);
extern struct route_node * extern struct route_node *rfapiMonitorAdd(struct bgp *bgp,
rfapiMonitorAdd (
struct bgp *bgp,
struct rfapi_descriptor *rfd, struct rfapi_descriptor *rfd,
struct prefix *p); struct prefix *p);
extern void extern void rfapiMonitorDetachImportHd(struct rfapi_descriptor *rfd);
rfapiMonitorDetachImportHd (struct rfapi_descriptor *rfd);
extern void extern void rfapiMonitorDel(struct bgp *bgp, struct rfapi_descriptor *rfd,
rfapiMonitorDel (
struct bgp *bgp,
struct rfapi_descriptor *rfd,
struct prefix *p); struct prefix *p);
extern int extern int rfapiMonitorDelHd(struct rfapi_descriptor *rfd);
rfapiMonitorDelHd (struct rfapi_descriptor *rfd);
extern void extern void rfapiMonitorCallbacksOff(struct bgp *bgp);
rfapiMonitorCallbacksOff (struct bgp *bgp);
extern void extern void rfapiMonitorCallbacksOn(struct bgp *bgp);
rfapiMonitorCallbacksOn (struct bgp *bgp);
extern void extern void rfapiMonitorResponseRemovalOff(struct bgp *bgp);
rfapiMonitorResponseRemovalOff (struct bgp *bgp);
extern void extern void rfapiMonitorResponseRemovalOn(struct bgp *bgp);
rfapiMonitorResponseRemovalOn (struct bgp *bgp);
extern void extern void rfapiMonitorExtraPrune(safi_t safi, struct route_node *rn);
rfapiMonitorExtraPrune (safi_t safi, struct route_node *rn);
extern void extern void rfapiMonitorTimersRestart(struct rfapi_descriptor *rfd,
rfapiMonitorTimersRestart (struct rfapi_descriptor *rfd, struct prefix *p); struct prefix *p);
extern void extern void rfapiMonitorItNodeChanged(struct rfapi_import_table *import_table,
rfapiMonitorItNodeChanged (
struct rfapi_import_table *import_table,
struct route_node *it_node, struct route_node *it_node,
struct rfapi_monitor_vpn *monitor_list); struct rfapi_monitor_vpn *monitor_list);
extern void extern void rfapiMonitorMovedUp(struct rfapi_import_table *import_table,
rfapiMonitorMovedUp (
struct rfapi_import_table *import_table,
struct route_node *old_node, struct route_node *old_node,
struct route_node *new_node, struct route_node *new_node,
struct rfapi_monitor_vpn *monitor_list); struct rfapi_monitor_vpn *monitor_list);
extern struct route_node * extern struct route_node *rfapiMonitorEthAdd(struct bgp *bgp,
rfapiMonitorEthAdd (
struct bgp *bgp,
struct rfapi_descriptor *rfd, struct rfapi_descriptor *rfd,
struct ethaddr *macaddr, struct ethaddr *macaddr,
uint32_t logical_net_id); uint32_t logical_net_id);
extern void extern void rfapiMonitorEthDel(struct bgp *bgp, struct rfapi_descriptor *rfd,
rfapiMonitorEthDel (
struct bgp *bgp,
struct rfapi_descriptor *rfd,
struct ethaddr *macaddr, struct ethaddr *macaddr,
uint32_t logical_net_id); uint32_t logical_net_id);

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