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,67 +43,60 @@
/* BGP advertise attribute is used for pack same attribute update into /* BGP advertise attribute is used for pack same attribute update into
one packet. To do that we maintain attribute hash in struct one packet. To do that we maintain attribute hash in struct
peer. */ peer. */
struct bgp_advertise_attr * struct bgp_advertise_attr *baa_new(void)
baa_new (void)
{ {
return (struct bgp_advertise_attr *) return (struct bgp_advertise_attr *)XCALLOC(
XCALLOC (MTYPE_BGP_ADVERTISE_ATTR, sizeof (struct bgp_advertise_attr)); MTYPE_BGP_ADVERTISE_ATTR, sizeof(struct bgp_advertise_attr));
} }
static void static void baa_free(struct bgp_advertise_attr *baa)
baa_free (struct bgp_advertise_attr *baa)
{ {
XFREE (MTYPE_BGP_ADVERTISE_ATTR, baa); XFREE(MTYPE_BGP_ADVERTISE_ATTR, baa);
} }
static void * static void *baa_hash_alloc(void *p)
baa_hash_alloc (void *p)
{ {
struct bgp_advertise_attr * ref = (struct bgp_advertise_attr *) p; struct bgp_advertise_attr *ref = (struct bgp_advertise_attr *)p;
struct bgp_advertise_attr *baa; struct bgp_advertise_attr *baa;
baa = baa_new (); baa = baa_new();
baa->attr = ref->attr; baa->attr = ref->attr;
return baa; return baa;
} }
unsigned int unsigned int baa_hash_key(void *p)
baa_hash_key (void *p)
{ {
struct bgp_advertise_attr * baa = (struct bgp_advertise_attr *) p; struct bgp_advertise_attr *baa = (struct bgp_advertise_attr *)p;
return attrhash_key_make (baa->attr); return attrhash_key_make(baa->attr);
} }
int int baa_hash_cmp(const void *p1, const void *p2)
baa_hash_cmp (const void *p1, const void *p2)
{ {
const struct bgp_advertise_attr * baa1 = p1; const struct bgp_advertise_attr *baa1 = p1;
const struct bgp_advertise_attr * baa2 = p2; const struct bgp_advertise_attr *baa2 = p2;
return attrhash_cmp (baa1->attr, baa2->attr); return attrhash_cmp(baa1->attr, baa2->attr);
} }
/* BGP update and withdraw information is stored in BGP advertise /* BGP update and withdraw information is stored in BGP advertise
structure. This structure is referred from BGP adjacency structure. This structure is referred from BGP adjacency
information. */ information. */
struct bgp_advertise * struct bgp_advertise *bgp_advertise_new(void)
bgp_advertise_new (void)
{ {
return (struct bgp_advertise *) return (struct bgp_advertise *)XCALLOC(MTYPE_BGP_ADVERTISE,
XCALLOC (MTYPE_BGP_ADVERTISE, sizeof (struct bgp_advertise)); sizeof(struct bgp_advertise));
} }
void void bgp_advertise_free(struct bgp_advertise *adv)
bgp_advertise_free (struct bgp_advertise *adv)
{ {
if (adv->binfo) if (adv->binfo)
bgp_info_unlock (adv->binfo); /* bgp_advertise bgp_info reference */ bgp_info_unlock(
XFREE (MTYPE_BGP_ADVERTISE, adv); adv->binfo); /* bgp_advertise bgp_info reference */
XFREE(MTYPE_BGP_ADVERTISE, adv);
} }
void void bgp_advertise_add(struct bgp_advertise_attr *baa,
bgp_advertise_add (struct bgp_advertise_attr *baa,
struct bgp_advertise *adv) struct bgp_advertise *adv)
{ {
adv->next = baa->adv; adv->next = baa->adv;
@ -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,40 +116,36 @@ 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;
ref.attr = bgp_attr_intern (attr); ref.attr = bgp_attr_intern(attr);
baa = (struct bgp_advertise_attr *) hash_get (hash, &ref, baa_hash_alloc); baa = (struct bgp_advertise_attr *)hash_get(hash, &ref, baa_hash_alloc);
baa->refcnt++; baa->refcnt++;
return baa; return baa;
} }
void void bgp_advertise_unintern(struct hash *hash, struct bgp_advertise_attr *baa)
bgp_advertise_unintern (struct hash *hash, struct bgp_advertise_attr *baa)
{ {
if (baa->refcnt) if (baa->refcnt)
baa->refcnt--; baa->refcnt--;
if (baa->refcnt && baa->attr) if (baa->refcnt && baa->attr)
bgp_attr_unintern (&baa->attr); bgp_attr_unintern(&baa->attr);
else else {
{ if (baa->attr) {
if (baa->attr) hash_release(hash, baa);
{ bgp_attr_unintern(&baa->attr);
hash_release (hash, baa);
bgp_attr_unintern (&baa->attr);
} }
baa_free (baa); baa_free(baa);
} }
} }
int int bgp_adj_out_lookup(struct peer *peer, struct bgp_node *rn,
bgp_adj_out_lookup (struct peer *peer, struct bgp_node *rn,
u_int32_t addpath_tx_id) u_int32_t addpath_tx_id)
{ {
struct bgp_adj_out *adj; struct bgp_adj_out *adj;
@ -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,43 +176,37 @@ 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) {
{ bgp_attr_unintern(&adj->attr);
if (adj->attr != attr) adj->attr = bgp_attr_intern(attr);
{
bgp_attr_unintern (&adj->attr);
adj->attr = bgp_attr_intern (attr);
} }
return; return;
} }
} }
adj = XCALLOC (MTYPE_BGP_ADJ_IN, sizeof (struct bgp_adj_in)); adj = XCALLOC(MTYPE_BGP_ADJ_IN, sizeof(struct bgp_adj_in));
adj->peer = peer_lock (peer); /* adj_in peer reference */ adj->peer = peer_lock(peer); /* adj_in peer reference */
adj->attr = bgp_attr_intern (attr); adj->attr = bgp_attr_intern(attr);
adj->addpath_rx_id = addpath_id; adj->addpath_rx_id = addpath_id;
BGP_ADJ_IN_ADD (rn, adj); BGP_ADJ_IN_ADD(rn, adj);
bgp_lock_node (rn); bgp_lock_node(rn);
} }
void void bgp_adj_in_remove(struct bgp_node *rn, struct bgp_adj_in *bai)
bgp_adj_in_remove (struct bgp_node *rn, struct bgp_adj_in *bai)
{ {
bgp_attr_unintern (&bai->attr); bgp_attr_unintern(&bai->attr);
BGP_ADJ_IN_DEL (rn, bai); BGP_ADJ_IN_DEL(rn, bai);
peer_unlock (bai->peer); /* adj_in peer reference */ peer_unlock(bai->peer); /* adj_in peer reference */
XFREE (MTYPE_BGP_ADJ_IN, bai); XFREE(MTYPE_BGP_ADJ_IN, bai);
} }
int int bgp_adj_in_unset(struct bgp_node *rn, struct peer *peer,
bgp_adj_in_unset (struct bgp_node *rn, struct peer *peer,
u_int32_t addpath_id) u_int32_t addpath_id)
{ {
struct bgp_adj_in *adj; struct bgp_adj_in *adj;
@ -235,14 +217,12 @@ 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);
} }
adj = adj_next; adj = adj_next;
@ -251,41 +231,39 @@ 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])
hash_free (peer->hash[afi][safi]); hash_free(peer->hash[afi][safi]);
peer->hash[afi][safi] = NULL; peer->hash[afi][safi] = NULL;
} }
} }

View File

@ -26,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,15 +106,14 @@ 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;
}; };
/* BGP adjacency linked list. */ /* BGP adjacency linked list. */
#define BGP_INFO_ADD(N,A,TYPE) \ #define BGP_INFO_ADD(N, A, TYPE) \
do { \ do { \
(A)->prev = NULL; \ (A)->prev = NULL; \
(A)->next = (N)->TYPE; \ (A)->next = (N)->TYPE; \
@ -128,7 +122,7 @@ struct bgp_synchronize
(N)->TYPE = (A); \ (N)->TYPE = (A); \
} while (0) } while (0)
#define BGP_INFO_DEL(N,A,TYPE) \ #define BGP_INFO_DEL(N, A, TYPE) \
do { \ do { \
if ((A)->next) \ if ((A)->next) \
(A)->next->prev = (A)->prev; \ (A)->next->prev = (A)->prev; \
@ -161,37 +155,39 @@ 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 *,
extern int bgp_adj_in_unset (struct bgp_node *, struct peer *, u_int32_t); u_int32_t);
extern void bgp_adj_in_remove (struct bgp_node *, struct bgp_adj_in *); extern int bgp_adj_in_unset(struct bgp_node *, struct peer *, u_int32_t);
extern void bgp_adj_in_remove(struct bgp_node *, struct bgp_adj_in *);
extern void bgp_sync_init (struct peer *); extern void bgp_sync_init(struct peer *);
extern void bgp_sync_delete (struct peer *); extern void bgp_sync_delete(struct peer *);
extern unsigned int baa_hash_key (void *p); extern unsigned int baa_hash_key(void *p);
extern int baa_hash_cmp (const void *p1, const void *p2); extern int baa_hash_cmp(const void *p1, const void *p2);
extern void bgp_advertise_add (struct bgp_advertise_attr *baa, extern void bgp_advertise_add(struct bgp_advertise_attr *baa,
struct bgp_advertise *adv); struct bgp_advertise *adv);
extern struct bgp_advertise *bgp_advertise_new (void); extern struct bgp_advertise *bgp_advertise_new(void);
extern void bgp_advertise_free (struct bgp_advertise *adv); extern void bgp_advertise_free(struct bgp_advertise *adv);
extern struct bgp_advertise_attr * extern struct bgp_advertise_attr *bgp_advertise_intern(struct hash *hash,
bgp_advertise_intern (struct hash *hash, struct attr *attr); struct attr *attr);
extern struct bgp_advertise_attr *baa_new (void); extern struct bgp_advertise_attr *baa_new(void);
extern void extern void bgp_advertise_delete(struct bgp_advertise_attr *baa,
bgp_advertise_delete (struct bgp_advertise_attr *baa,
struct bgp_advertise *adv); struct bgp_advertise *adv);
extern void 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;
@ -77,53 +75,57 @@ struct aspath
#define ASPATH_STR_DEFAULT_LEN 32 #define ASPATH_STR_DEFAULT_LEN 32
/* Prototypes. */ /* Prototypes. */
extern void aspath_init (void); extern void aspath_init(void);
extern void aspath_finish (void); extern void aspath_finish(void);
extern struct aspath *aspath_parse (struct stream *, size_t, int); extern struct aspath *aspath_parse(struct stream *, size_t, int);
extern struct aspath *aspath_dup (struct aspath *); extern struct aspath *aspath_dup(struct aspath *);
extern struct aspath *aspath_aggregate (struct aspath *, struct aspath *); extern struct aspath *aspath_aggregate(struct aspath *, struct aspath *);
extern struct aspath *aspath_prepend (struct aspath *, struct aspath *); extern struct aspath *aspath_prepend(struct aspath *, struct aspath *);
extern struct aspath *aspath_filter_exclude (struct aspath *, struct aspath *); extern struct aspath *aspath_filter_exclude(struct aspath *, struct aspath *);
extern struct aspath *aspath_add_seq_n (struct aspath *, as_t, unsigned); extern struct aspath *aspath_add_seq_n(struct aspath *, as_t, unsigned);
extern struct aspath *aspath_add_seq (struct aspath *, as_t); extern struct aspath *aspath_add_seq(struct aspath *, as_t);
extern struct aspath *aspath_add_confed_seq (struct aspath *, as_t); extern struct aspath *aspath_add_confed_seq(struct aspath *, as_t);
extern int aspath_cmp (const void *, const void *); extern int aspath_cmp(const void *, const void *);
extern int aspath_cmp_left (const struct aspath *, const struct aspath *); extern int aspath_cmp_left(const struct aspath *, const struct aspath *);
extern int aspath_cmp_left_confed (const struct aspath *, const struct aspath *); extern int aspath_cmp_left_confed(const struct aspath *, const struct aspath *);
extern struct aspath *aspath_delete_confed_seq (struct aspath *); extern struct aspath *aspath_delete_confed_seq(struct aspath *);
extern struct aspath *aspath_empty (void); extern struct aspath *aspath_empty(void);
extern struct aspath *aspath_empty_get (void); extern struct aspath *aspath_empty_get(void);
extern struct aspath *aspath_str2aspath (const char *); extern struct aspath *aspath_str2aspath(const char *);
extern void aspath_free (struct aspath *); extern void aspath_free(struct aspath *);
extern struct aspath *aspath_intern (struct aspath *); extern struct aspath *aspath_intern(struct aspath *);
extern void aspath_unintern (struct aspath **); extern void aspath_unintern(struct aspath **);
extern const char *aspath_print (struct aspath *); extern const char *aspath_print(struct aspath *);
extern void aspath_print_vty (struct vty *, const char *, struct aspath *, const char *); extern void aspath_print_vty(struct vty *, const char *, struct aspath *,
extern void aspath_print_all_vty (struct vty *); const char *);
extern unsigned int aspath_key_make (void *); extern void aspath_print_all_vty(struct vty *);
extern unsigned int aspath_get_first_as (struct aspath *); extern unsigned int aspath_key_make(void *);
extern unsigned int aspath_get_last_as (struct aspath *); extern unsigned int aspath_get_first_as(struct aspath *);
extern int aspath_loop_check (struct aspath *, as_t); extern unsigned int aspath_get_last_as(struct aspath *);
extern int aspath_private_as_check (struct aspath *); extern int aspath_loop_check(struct aspath *, as_t);
extern int aspath_single_asn_check (struct aspath *, as_t asn); extern int aspath_private_as_check(struct aspath *);
extern struct aspath *aspath_replace_specific_asn (struct aspath *aspath, as_t target_asn, as_t our_asn); extern int aspath_single_asn_check(struct aspath *, as_t asn);
extern struct aspath *aspath_replace_private_asns(struct aspath *aspath, as_t asn); extern struct aspath *aspath_replace_specific_asn(struct aspath *aspath,
extern struct aspath *aspath_remove_private_asns (struct aspath *aspath); as_t target_asn,
extern int aspath_firstas_check (struct aspath *, as_t); as_t our_asn);
extern int aspath_confed_check (struct aspath *); extern struct aspath *aspath_replace_private_asns(struct aspath *aspath,
extern int aspath_left_confed_check (struct aspath *); as_t asn);
extern unsigned long aspath_count (void); extern struct aspath *aspath_remove_private_asns(struct aspath *aspath);
extern unsigned int aspath_count_hops (const struct aspath *); extern int aspath_firstas_check(struct aspath *, as_t);
extern unsigned int aspath_count_confeds (struct aspath *); extern int aspath_confed_check(struct aspath *);
extern unsigned int aspath_size (struct aspath *); extern int aspath_left_confed_check(struct aspath *);
extern as_t aspath_highest (struct aspath *); extern unsigned long aspath_count(void);
extern as_t aspath_leftmost (struct aspath *); extern unsigned int aspath_count_hops(const struct aspath *);
extern size_t aspath_put (struct stream *, struct aspath *, int); extern unsigned int aspath_count_confeds(struct aspath *);
extern unsigned int aspath_size(struct aspath *);
extern as_t aspath_highest(struct aspath *);
extern as_t aspath_leftmost(struct aspath *);
extern size_t aspath_put(struct stream *, struct aspath *, int);
extern struct aspath *aspath_reconcile_as4 (struct aspath *, struct aspath *); extern struct aspath *aspath_reconcile_as4(struct aspath *, struct aspath *);
extern unsigned int aspath_has_as4 (struct aspath *); extern unsigned int aspath_has_as4(struct aspath *);
/* For SNMP BGP4PATHATTRASPATHSEGMENT, might be useful for debug */ /* For SNMP BGP4PATHATTRASPATHSEGMENT, might be useful for debug */
extern u_char *aspath_snmp_pathseg (struct aspath *, size_t *); extern u_char *aspath_snmp_pathseg(struct aspath *, size_t *);
#endif /* _QUAGGA_BGP_ASPATH_H */ #endif /* _QUAGGA_BGP_ASPATH_H */

File diff suppressed because it is too large Load Diff

View File

@ -21,20 +21,20 @@
#ifndef _QUAGGA_BGP_ATTR_H #ifndef _QUAGGA_BGP_ATTR_H
#define _QUAGGA_BGP_ATTR_H #define _QUAGGA_BGP_ATTR_H
#include "mpls.h"
#include "bgp_attr_evpn.h" #include "bgp_attr_evpn.h"
/* Simple bit mapping. */ /* Simple bit mapping. */
#define BITMAP_NBBY 8 #define BITMAP_NBBY 8
#define SET_BITMAP(MAP, NUM) \ #define SET_BITMAP(MAP, NUM) \
SET_FLAG (MAP[(NUM) / BITMAP_NBBY], 1 << ((NUM) % BITMAP_NBBY)) SET_FLAG(MAP[(NUM) / BITMAP_NBBY], 1 << ((NUM) % BITMAP_NBBY))
#define CHECK_BITMAP(MAP, NUM) \ #define CHECK_BITMAP(MAP, NUM) \
CHECK_FLAG (MAP[(NUM) / BITMAP_NBBY], 1 << ((NUM) % BITMAP_NBBY)) CHECK_FLAG(MAP[(NUM) / BITMAP_NBBY], 1 << ((NUM) % BITMAP_NBBY))
#define BGP_MED_MAX UINT32_MAX #define BGP_MED_MAX UINT32_MAX
/* BGP Attribute type range. */ /* BGP Attribute type range. */
#define BGP_ATTR_TYPE_RANGE 256 #define BGP_ATTR_TYPE_RANGE 256
#define BGP_ATTR_BITMAP_SIZE (BGP_ATTR_TYPE_RANGE / BITMAP_NBBY) #define BGP_ATTR_BITMAP_SIZE (BGP_ATTR_TYPE_RANGE / BITMAP_NBBY)
@ -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,60 +210,61 @@ 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;
struct bpacket_attr_vec_arr; struct bpacket_attr_vec_arr;
/* Prototypes. */ /* Prototypes. */
extern void bgp_attr_init (void); extern void bgp_attr_init(void);
extern void bgp_attr_finish (void); extern void bgp_attr_finish(void);
extern bgp_attr_parse_ret_t bgp_attr_parse (struct peer *, struct attr *, extern bgp_attr_parse_ret_t bgp_attr_parse(struct peer *, struct attr *,
bgp_size_t, struct bgp_nlri *, bgp_size_t, struct bgp_nlri *,
struct bgp_nlri *); struct bgp_nlri *);
extern struct attr_extra *bgp_attr_extra_get (struct attr *); extern void bgp_attr_dup(struct attr *, struct attr *);
extern void bgp_attr_extra_free (struct attr *); extern void bgp_attr_deep_dup(struct attr *, struct attr *);
extern void bgp_attr_dup (struct attr *, struct attr *); extern void bgp_attr_deep_free(struct attr *);
extern void bgp_attr_deep_dup (struct attr *, struct attr *); extern struct attr *bgp_attr_intern(struct attr *attr);
extern void bgp_attr_deep_free (struct attr *); extern struct attr *bgp_attr_refcount(struct attr *attr);
extern struct attr *bgp_attr_intern (struct attr *attr); extern void bgp_attr_unintern_sub(struct attr *);
extern struct attr *bgp_attr_refcount (struct attr *attr); extern void bgp_attr_unintern(struct attr **);
extern void bgp_attr_unintern_sub (struct attr *); extern void bgp_attr_flush(struct attr *);
extern void bgp_attr_unintern (struct attr **); extern struct attr *bgp_attr_default_set(struct attr *attr, u_char);
extern void bgp_attr_flush (struct attr *); extern struct attr *bgp_attr_aggregate_intern(struct bgp *, u_char,
extern struct attr *bgp_attr_default_set (struct attr *attr, u_char);
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,
extern bgp_size_t bgp_packet_attribute (struct bgp *bgp, struct peer *, u_char);
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 *);
extern unsigned int attrhash_key_make (void *); extern unsigned int attrhash_key_make(void *);
extern void attr_show_all (struct vty *); extern void attr_show_all(struct vty *);
extern unsigned long int attr_count (void); extern unsigned long int attr_count(void);
extern unsigned long int attr_unknown_count (void); extern unsigned long int attr_unknown_count(void);
/* Cluster list prototypes. */ /* Cluster list prototypes. */
extern int cluster_loop_check (struct cluster_list *, struct in_addr); extern int cluster_loop_check(struct cluster_list *, struct in_addr);
extern void cluster_unintern (struct cluster_list *); extern void cluster_unintern(struct cluster_list *);
/* Transit attribute prototypes. */ /* Transit attribute prototypes. */
void transit_unintern (struct transit *); void transit_unintern(struct transit *);
/* Below exported for unit-test purposes only */ /* Below exported for unit-test purposes only */
struct bgp_attr_parser_args { struct bgp_attr_parser_args {
@ -280,16 +276,15 @@ struct bgp_attr_parser_args {
u_int8_t flags; u_int8_t flags;
u_char *startp; u_char *startp;
}; };
extern int bgp_mp_reach_parse (struct bgp_attr_parser_args *args, extern int bgp_mp_reach_parse(struct bgp_attr_parser_args *args,
struct bgp_nlri *); struct bgp_nlri *);
extern int bgp_mp_unreach_parse (struct bgp_attr_parser_args *args, extern int bgp_mp_unreach_parse(struct bgp_attr_parser_args *args,
struct bgp_nlri *); struct bgp_nlri *);
extern struct bgp_attr_encap_subtlv * extern struct bgp_attr_encap_subtlv *
encap_tlv_dup(struct bgp_attr_encap_subtlv *orig); encap_tlv_dup(struct bgp_attr_encap_subtlv *orig);
extern void extern void bgp_attr_flush_encap(struct attr *attr);
bgp_attr_flush_encap(struct attr *attr);
/** /**
* Set of functions to encode MP_REACH_NLRI and MP_UNREACH_NLRI attributes. * Set of functions to encode MP_REACH_NLRI and MP_UNREACH_NLRI attributes.
@ -303,30 +298,39 @@ 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);
extern size_t bgp_packet_mpunreach_start (struct stream *s, afi_t afi, extern size_t bgp_packet_mpunreach_start(struct stream *s, afi_t afi,
safi_t safi); safi_t safi);
extern void bgp_packet_mpunreach_prefix (struct stream *s, struct prefix *p, extern void bgp_packet_mpunreach_prefix(struct stream *s, struct prefix *p,
afi_t afi, safi_t safi, struct prefix_rd *prd, afi_t afi, safi_t safi,
u_char *tag, int, u_int32_t, struct attr *); struct prefix_rd *prd, mpls_label_t *,
extern void bgp_packet_mpunreach_end (struct stream *s, size_t attrlen_pnt); int, u_int32_t, struct attr *);
extern void bgp_packet_mpunreach_end(struct stream *s, size_t attrlen_pnt);
static inline int static inline int bgp_rmap_nhop_changed(u_int32_t out_rmap_flags,
bgp_rmap_nhop_changed(u_int32_t out_rmap_flags, u_int32_t in_rmap_flags) u_int32_t in_rmap_flags)
{ {
return ((CHECK_FLAG(out_rmap_flags, BATTR_RMAP_NEXTHOP_PEER_ADDRESS) || return ((CHECK_FLAG(out_rmap_flags, BATTR_RMAP_NEXTHOP_PEER_ADDRESS)
CHECK_FLAG(out_rmap_flags, BATTR_RMAP_NEXTHOP_UNCHANGED) || || CHECK_FLAG(out_rmap_flags, BATTR_RMAP_NEXTHOP_UNCHANGED)
CHECK_FLAG(out_rmap_flags, BATTR_RMAP_IPV4_NHOP_CHANGED) || || CHECK_FLAG(out_rmap_flags, BATTR_RMAP_IPV4_NHOP_CHANGED)
CHECK_FLAG(out_rmap_flags, BATTR_RMAP_IPV6_GLOBAL_NHOP_CHANGED) || || CHECK_FLAG(out_rmap_flags,
CHECK_FLAG(out_rmap_flags, BATTR_RMAP_IPV6_PREFER_GLOBAL_CHANGED) || BATTR_RMAP_IPV6_GLOBAL_NHOP_CHANGED)
CHECK_FLAG(out_rmap_flags, BATTR_RMAP_IPV6_LL_NHOP_CHANGED) || || CHECK_FLAG(out_rmap_flags,
CHECK_FLAG(in_rmap_flags, BATTR_RMAP_NEXTHOP_UNCHANGED)) ? 1 : 0); BATTR_RMAP_IPV6_PREFER_GLOBAL_CHANGED)
|| CHECK_FLAG(out_rmap_flags, BATTR_RMAP_IPV6_LL_NHOP_CHANGED)
|| CHECK_FLAG(in_rmap_flags, BATTR_RMAP_NEXTHOP_UNCHANGED))
? 1
: 0);
}
static inline u_int32_t mac_mobility_seqnum(struct attr *attr)
{
return (attr) ? attr->mm_seqnum : 0;
} }
#endif /* _QUAGGA_BGP_ATTR_H */ #endif /* _QUAGGA_BGP_ATTR_H */

View File

@ -33,21 +33,20 @@
#include "bgpd/bgp_attr_evpn.h" #include "bgpd/bgp_attr_evpn.h"
#include "bgpd/bgp_ecommunity.h" #include "bgpd/bgp_ecommunity.h"
#include "bgpd/bgp_evpn.h" #include "bgpd/bgp_evpn.h"
#include "bgpd/bgp_evpn_private.h"
void bgp_add_routermac_ecom(struct attr *attr, struct ethaddr *routermac) void bgp_add_routermac_ecom(struct attr *attr, struct ethaddr *routermac)
{ {
struct ecommunity_val routermac_ecom; struct ecommunity_val routermac_ecom;
if (attr->extra) {
memset(&routermac_ecom, 0, sizeof(struct ecommunity_val)); memset(&routermac_ecom, 0, sizeof(struct ecommunity_val));
routermac_ecom.val[0] = ECOMMUNITY_ENCODE_EVPN; routermac_ecom.val[0] = ECOMMUNITY_ENCODE_EVPN;
routermac_ecom.val[1] = ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC; routermac_ecom.val[1] = ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC;
memcpy(&routermac_ecom.val[2], routermac->octet, ETHER_ADDR_LEN); memcpy(&routermac_ecom.val[2], routermac->octet, ETHER_ADDR_LEN);
if (!attr->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,19 +171,19 @@ bgp_build_evpn_prefix(int evpn_type, uint32_t eth_tag, struct prefix *dst)
p_evpn_p = &(dst->u.prefix_evpn); p_evpn_p = &(dst->u.prefix_evpn);
dst->family = AF_ETHERNET; dst->family = AF_ETHERNET;
p_evpn_p->route_type = evpn_type; p_evpn_p->route_type = evpn_type;
if (evpn_type == EVPN_IP_PREFIX) { if (evpn_type == BGP_EVPN_IP_PREFIX_ROUTE) {
p_evpn_p->eth_tag = eth_tag; p_evpn_p->eth_tag = eth_tag;
p_evpn_p->ip_prefix_length = p2.prefixlen; p_evpn_p->ip_prefix_length = p2.prefixlen;
if (src->family == AF_INET) { if (src->family == AF_INET) {
p_evpn_p->flags = IP_PREFIX_V4; SET_IPADDR_V4(&p_evpn_p->ip);
memcpy(&p_evpn_p->ip.v4_addr, &src->u.prefix4, memcpy(&p_evpn_p->ip.ipaddr_v4, &src->u.prefix4,
sizeof(struct in_addr)); sizeof(struct in_addr));
dst->prefixlen = (u_char) PREFIX_LEN_ROUTE_TYPE_5_IPV4; dst->prefixlen = (u_char)PREFIX_LEN_ROUTE_TYPE_5_IPV4;
} else { } else {
p_evpn_p->flags = IP_PREFIX_V6; SET_IPADDR_V6(&p_evpn_p->ip);
memcpy(&p_evpn_p->ip.v6_addr, &src->u.prefix6, memcpy(&p_evpn_p->ip.ipaddr_v6, &src->u.prefix6,
sizeof(struct in6_addr)); sizeof(struct in6_addr));
dst->prefixlen = (u_char) PREFIX_LEN_ROUTE_TYPE_5_IPV6; dst->prefixlen = (u_char)PREFIX_LEN_ROUTE_TYPE_5_IPV6;
} }
} else } else
return -1; return -1;

View File

@ -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,15 +234,14 @@ 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;
struct peer *peer; struct peer *peer;
if (BGP_DEBUG (zebra, ZEBRA)) if (BGP_DEBUG(zebra, ZEBRA))
zlog_debug("Zebra: BFD Dest replay request"); zlog_debug("Zebra: BFD Dest replay request");
/* Send the client registration */ /* Send the client registration */
@ -255,9 +249,8 @@ 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,10 +276,9 @@ 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;
@ -304,22 +295,22 @@ bgp_bfd_dest_update (int command, struct zclient *zclient,
struct prefix sp; struct prefix sp;
int status; int status;
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));
} }
} }
@ -329,56 +320,59 @@ bgp_bfd_dest_update (int command, struct zclient *zclient,
struct bgp *bgp; struct bgp *bgp;
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;
@ -525,25 +508,26 @@ 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);
@ -560,17 +544,16 @@ DEFUN (neighbor_bfd,
struct peer *peer; struct peer *peer;
int ret; int ret;
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);
if (ret != 0) if (ret != 0)
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,
@ -593,20 +576,21 @@ DEFUN (neighbor_bfd_param,
u_int8_t dm_val; u_int8_t dm_val;
int ret; int ret;
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);
if (ret != 0) if (ret != 0)
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,
@ -624,20 +608,20 @@ DEFUN_HIDDEN (neighbor_bfd_type,
enum bfd_sess_type type; enum bfd_sess_type type;
int ret; int ret;
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)
return bgp_vty_return (vty, ret); return bgp_vty_return(vty, ret);
return CMD_SUCCESS; return CMD_SUCCESS;
} }
@ -657,13 +641,13 @@ DEFUN (no_neighbor_bfd,
struct peer *peer; struct peer *peer;
int ret; int ret;
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)
return bgp_vty_return (vty, ret); return bgp_vty_return(vty, ret);
return CMD_SUCCESS; return CMD_SUCCESS;
} }
@ -683,22 +667,21 @@ DEFUN_HIDDEN (no_neighbor_bfd_type,
struct peer *peer; struct peer *peer;
int ret; int ret;
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;
ret = bgp_bfd_peer_param_type_set(peer, BFD_TYPE_NOT_CONFIGURED); ret = bgp_bfd_peer_param_type_set(peer, BFD_TYPE_NOT_CONFIGURED);
if (ret != 0) if (ret != 0)
return bgp_vty_return (vty, ret); return bgp_vty_return(vty, ret);
return CMD_SUCCESS; return CMD_SUCCESS;
} }
void void bgp_bfd_init(void)
bgp_bfd_init(void)
{ {
bfd_gbl_init(); bfd_gbl_init();
@ -707,9 +690,9 @@ bgp_bfd_init(void)
zclient->bfd_dest_replay = bgp_bfd_dest_replay; zclient->bfd_dest_replay = bgp_bfd_dest_replay;
/* "neighbor bfd" commands. */ /* "neighbor bfd" commands. */
install_element (BGP_NODE, &neighbor_bfd_cmd); install_element(BGP_NODE, &neighbor_bfd_cmd);
install_element (BGP_NODE, &neighbor_bfd_param_cmd); install_element(BGP_NODE, &neighbor_bfd_param_cmd);
install_element (BGP_NODE, &neighbor_bfd_type_cmd); install_element(BGP_NODE, &neighbor_bfd_type_cmd);
install_element (BGP_NODE, &no_neighbor_bfd_cmd); install_element(BGP_NODE, &no_neighbor_bfd_cmd);
install_element (BGP_NODE, &no_neighbor_bfd_type_cmd); install_element(BGP_NODE, &no_neighbor_bfd_type_cmd);
} }

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;
@ -82,49 +77,41 @@ attr_parse (struct stream *s, u_int16_t len)
lim = s->getp + len; lim = s->getp + len;
printf ("attr_parse s->getp %zd, len %d, lim %d\n", s->getp, len, lim); printf("attr_parse s->getp %zd, len %d, lim %d\n", s->getp, len, lim);
while (s->getp < lim) while (s->getp < lim) {
{ flag = stream_getc(s);
flag = stream_getc (s); type = stream_getc(s);
type = stream_getc (s);
if (flag & BGP_ATTR_FLAG_EXTLEN) if (flag & BGP_ATTR_FLAG_EXTLEN)
length = stream_getw (s); length = stream_getw(s);
else else
length = stream_getc (s); length = stream_getc(s);
printf ("FLAG: %d\n", flag); printf("FLAG: %d\n", flag);
printf ("TYPE: %d\n", type); printf("TYPE: %d\n", type);
printf ("Len: %d\n", length); printf("Len: %d\n", length);
switch (type) switch (type) {
{ case BGP_ATTR_ORIGIN: {
case BGP_ATTR_ORIGIN:
{
u_char origin; 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;
@ -151,164 +137,153 @@ main (int argc, char **argv)
u_int16_t viewno, seq_num; u_int16_t viewno, seq_num;
struct prefix_ipv4 p; struct prefix_ipv4 p;
s = stream_new (10000); s = stream_new(10000);
if (argc != 2) if (argc != 2) {
{ fprintf(stderr, "Usage: %s FILENAME\n", argv[0]);
fprintf (stderr, "Usage: %s FILENAME\n", argv[0]); exit(1);
exit (1);
} }
fp = fopen (argv[1], "r"); 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;
} }
/* Extract header. */ /* Extract header. */
now = stream_getl (s); now = stream_getl(s);
type = stream_getw (s); type = stream_getw(s);
subtype = stream_getw (s); subtype = stream_getw(s);
len = stream_getl (s); len = stream_getl(s);
printf ("TIME: %s", ctime (&now)); printf("TIME: %s", ctime(&now));
/* printf ("TYPE: %d/%d\n", type, subtype); */ /* printf ("TYPE: %d/%d\n", type, subtype); */
if (type == MSG_PROTOCOL_BGP4MP) if (type == MSG_PROTOCOL_BGP4MP)
printf ("TYPE: BGP4MP"); printf("TYPE: BGP4MP");
else if (type == MSG_PROTOCOL_BGP4MP_ET) else if (type == MSG_PROTOCOL_BGP4MP_ET)
printf ("TYPE: BGP4MP_ET"); printf("TYPE: BGP4MP_ET");
else if (type == MSG_TABLE_DUMP) else if (type == MSG_TABLE_DUMP)
printf ("TYPE: MSG_TABLE_DUMP"); printf("TYPE: MSG_TABLE_DUMP");
else else
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;
case AFI_IP6: case AFI_IP6:
printf ("/AFI_IP6\n"); printf("/AFI_IP6\n");
break; break;
default: default:
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;
case BGP4MP_MESSAGE: case BGP4MP_MESSAGE:
printf ("/MESSAGE\n"); printf("/MESSAGE\n");
break; break;
case BGP4MP_ENTRY: case BGP4MP_ENTRY:
printf ("/ENTRY\n"); printf("/ENTRY\n");
break; break;
case BGP4MP_SNAPSHOT: case BGP4MP_SNAPSHOT:
printf ("/SNAPSHOT\n"); printf("/SNAPSHOT\n");
break; break;
default: default:
printf ("/UNKNOWN %d", subtype); printf("/UNKNOWN %d", subtype);
break; break;
} }
} }
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;
u_int16_t attrlen; u_int16_t attrlen;
viewno = stream_getw (s); viewno = stream_getw(s);
seq_num = stream_getw (s); seq_num = stream_getw(s);
printf ("VIEW: %d\n", viewno); printf("VIEW: %d\n", viewno);
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),
printf ("PREFIX: %s/%d\n", inet_ntoa (p.prefix), p.prefixlen); 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),
printf ("ORIGINATED: %s", ctime (&originated)); source_as);
printf("ORIGINATED: %s", ctime(&originated));
attrlen = stream_getw (s); attrlen = stream_getw(s);
printf ("ATTRLEN: %d\n", attrlen); printf("ATTRLEN: %d\n", attrlen);
attr_parse (s, attrlen); attr_parse(s, attrlen);
printf ("STATUS: 0x%x\n", status); printf("STATUS: 0x%x\n", status);
}
} else {
source_as = stream_getw(s);
dest_as = stream_getw(s);
printf("source_as: %d\n", source_as);
printf("dest_as: %d\n", dest_as);
ifindex = stream_getw(s);
family = stream_getw(s);
printf("ifindex: %d\n", ifindex);
printf("family: %d\n", family);
sip.s_addr = stream_get_ipv4(s);
dip.s_addr = stream_get_ipv4(s);
printf("saddr: %s\n", inet_ntoa(sip));
printf("daddr: %s\n", inet_ntoa(dip));
printf("\n");
} }
} }
else fclose(fp);
{
source_as = stream_getw (s);
dest_as = stream_getw (s);
printf ("source_as: %d\n", source_as);
printf ("dest_as: %d\n", dest_as);
ifindex = stream_getw (s);
family = stream_getw (s);
printf ("ifindex: %d\n", ifindex);
printf ("family: %d\n", family);
sip.s_addr = stream_get_ipv4 (s);
dip.s_addr = stream_get_ipv4 (s);
printf ("saddr: %s\n", inet_ntoa (sip));
printf ("daddr: %s\n", inet_ntoa (dip));
printf ("\n");
}
}
fclose (fp);
return 0; return 0;
} }

File diff suppressed because it is too large Load Diff

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;
@ -131,42 +125,42 @@ struct community_list_handler
extern struct community_list_handler *bgp_clist; extern struct community_list_handler *bgp_clist;
/* Prototypes. */ /* Prototypes. */
extern struct community_list_handler *community_list_init (void); extern struct community_list_handler *community_list_init(void);
extern void community_list_terminate (struct community_list_handler *); extern void community_list_terminate(struct community_list_handler *);
extern int community_list_set (struct community_list_handler *ch, extern int community_list_set(struct community_list_handler *ch,
const char *name, const char *str, int direct, 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, int direct,
int style, int delete_all);
extern int extcommunity_list_set(struct community_list_handler *ch,
const char *name, const char *str, int direct,
int style);
extern int extcommunity_list_unset(struct community_list_handler *ch,
const char *name, const char *str, const char *name, const char *str,
int direct, int style, int delete_all); int direct, int style, int delete_all);
extern int extcommunity_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 extcommunity_list_unset (struct community_list_handler *ch, extern int lcommunity_list_unset(struct community_list_handler *ch,
const char *name, const char *str, const char *name, const char *str, int direct,
int direct, int style, int delete_all); int style);
extern int lcommunity_list_set (struct community_list_handler *ch,
const char *name, const char *str,
int direct, int style);
extern int lcommunity_list_unset (struct community_list_handler *ch,
const char *name, const char *str,
int direct, int style);
extern struct community_list_master * extern struct community_list_master *
community_list_master_lookup (struct community_list_handler *, int); community_list_master_lookup(struct community_list_handler *, int);
extern struct community_list * extern struct community_list *
community_list_lookup (struct community_list_handler *, const char *, int); community_list_lookup(struct community_list_handler *, const char *, int);
extern int community_list_match (struct community *, struct community_list *); extern int community_list_match(struct community *, struct community_list *);
extern int ecommunity_list_match (struct ecommunity *, struct community_list *); extern int ecommunity_list_match(struct ecommunity *, struct community_list *);
extern int lcommunity_list_match (struct lcommunity *, struct community_list *); extern int lcommunity_list_match(struct lcommunity *, struct community_list *);
extern int community_list_exact_match (struct community *, extern int community_list_exact_match(struct community *,
struct community_list *);
extern struct community *community_list_match_delete(struct community *,
struct community_list *); struct community_list *);
extern struct community *
community_list_match_delete (struct community *, struct community_list *);
extern struct lcommunity * extern struct lcommunity *
lcommunity_list_match_delete (struct lcommunity *lcom, lcommunity_list_match_delete(struct lcommunity *lcom,
struct community_list *list); struct community_list *list);
#endif /* _QUAGGA_BGP_CLIST_H */ #endif /* _QUAGGA_BGP_CLIST_H */

View File

@ -31,72 +31,66 @@
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;
} }
XFREE (MTYPE_COMMUNITY, com); XFREE(MTYPE_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));
val = htonl (val); val = htonl(val);
memcpy (com_lastval (com), &val, sizeof (u_int32_t)); memcpy(com_lastval(com), &val, sizeof(u_int32_t));
} }
/* 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;
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;
} }
return; return;
@ -106,14 +100,13 @@ 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,16 +114,15 @@ 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;
memcpy (&v1, a1, sizeof (u_int32_t)); memcpy(&v1, a1, sizeof(u_int32_t));
memcpy (&v2, a2, sizeof (u_int32_t)); memcpy(&v2, a2, sizeof(u_int32_t));
v1 = ntohl (v1); v1 = ntohl(v1);
v2 = ntohl (v2); v2 = ntohl(v2);
if (v1 < v2) if (v1 < v2)
return -1; return -1;
@ -139,57 +131,54 @@ 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;
val = htonl (val); val = htonl(val);
for (i = 0; i < com->size; i++) for (i = 0; i < com->size; i++)
if (memcmp (&val, com_nthval (com, i), sizeof (u_int32_t)) == 0) if (memcmp(&val, com_nthval(com, i), sizeof(u_int32_t)) == 0)
return 1; return 1;
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;
p = (u_char *) com->val; p = (u_char *)com->val;
p += (i * 4); p += (i * 4);
memcpy (&val, p, sizeof (u_int32_t)); memcpy(&val, p, sizeof(u_int32_t));
return ntohl (val); return ntohl(val);
} }
/* 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;
u_int32_t val; u_int32_t val;
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))
community_add_val (new, val); community_add_val(new, val);
} }
qsort (new->val, new->size, sizeof (u_int32_t), community_compare); qsort(new->val, new->size, sizeof(u_int32_t), community_compare);
return new; return new;
} }
@ -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,9 +213,8 @@ 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';
json_object_string_add(com->json, "string", ""); json_object_string_add(com->json, "string", "");
@ -240,79 +227,75 @@ 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;
case COMMUNITY_NO_EXPORT: case COMMUNITY_NO_EXPORT:
len += strlen (" no-export"); len += strlen(" no-export");
break; break;
case COMMUNITY_NO_ADVERTISE: case COMMUNITY_NO_ADVERTISE:
len += strlen (" no-advertise"); len += strlen(" no-advertise");
break; break;
case COMMUNITY_LOCAL_AS: case COMMUNITY_LOCAL_AS:
len += strlen (" local-AS"); len += strlen(" local-AS");
break; break;
default: default:
len += strlen (" 65536:65535"); len += strlen(" 65536:65535");
break; break;
} }
} }
/* Allocate memory. */ /* Allocate memory. */
str = pnt = XMALLOC (MTYPE_COMMUNITY_STR, len); str = pnt = XMALLOC(MTYPE_COMMUNITY_STR, len);
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);
if (first) if (first)
first = 0; first = 0;
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");
json_string = json_object_new_string("internet"); json_string = json_object_new_string("internet");
json_object_array_add(json_community_list, json_string); json_object_array_add(json_community_list, json_string);
break; break;
case COMMUNITY_NO_EXPORT: case COMMUNITY_NO_EXPORT:
strcpy (pnt, "no-export"); strcpy(pnt, "no-export");
pnt += strlen ("no-export"); pnt += strlen("no-export");
json_string = json_object_new_string("noExport"); json_string = json_object_new_string("noExport");
json_object_array_add(json_community_list, json_string); json_object_array_add(json_community_list, json_string);
break; break;
case COMMUNITY_NO_ADVERTISE: case COMMUNITY_NO_ADVERTISE:
strcpy (pnt, "no-advertise"); strcpy(pnt, "no-advertise");
pnt += strlen ("no-advertise"); pnt += strlen("no-advertise");
json_string = json_object_new_string("noAdvertise"); json_string = json_object_new_string("noAdvertise");
json_object_array_add(json_community_list, json_string); json_object_array_add(json_community_list, json_string);
break; break;
case COMMUNITY_LOCAL_AS: case COMMUNITY_LOCAL_AS:
strcpy (pnt, "local-AS"); strcpy(pnt, "local-AS");
pnt += strlen ("local-AS"); pnt += strlen("local-AS");
json_string = json_object_new_string("localAs"); json_string = json_object_new_string("localAs");
json_object_array_add(json_community_list, json_string); json_object_array_add(json_community_list, json_string);
break; break;
default: default:
as = (comval >> 16) & 0xFFFF; as = (comval >> 16) & 0xFFFF;
val = comval & 0xFFFF; val = comval & 0xFFFF;
sprintf (pnt, "%u:%d", as, val); sprintf(pnt, "%u:%d", as, val);
json_string = json_object_new_string(pnt); json_string = json_object_new_string(pnt);
json_object_array_add(json_community_list, json_string); json_object_array_add(json_community_list, json_string);
pnt += strlen (pnt); pnt += strlen(pnt);
break; break;
} }
} }
@ -324,35 +307,33 @@ 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;
/* Assert this community structure is not interned. */ /* Assert this community structure is not interned. */
assert (com->refcnt == 0); assert(com->refcnt == 0);
/* Lookup community hash. */ /* Lookup community hash. */
find = (struct community *) hash_get (comhash, com, hash_alloc_intern); find = (struct community *)hash_get(comhash, com, hash_alloc_intern);
/* Arguemnt com is allocated temporary. So when it is not used in /* Arguemnt com is allocated temporary. So when it is not used in
hash, it should be freed. */ hash, it should be freed. */
if (find != com) if (find != com)
community_free (com); community_free(com);
/* Increment refrence counter. */ /* Increment refrence counter. */
find->refcnt++; find->refcnt++;
/* Make string. */ /* Make string. */
if (! find->str) if (!find->str)
set_community_string (find); set_community_string(find);
return find; return find;
} }
/* 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,20 +341,18 @@ 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);
community_free (*com); community_free(*com);
*com = NULL; *com = NULL;
} }
} }
/* 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;
@ -386,52 +365,46 @@ community_parse (u_int32_t *pnt, u_short length)
tmp.size = length / 4; tmp.size = length / 4;
tmp.val = pnt; tmp.val = pnt;
new = community_uniq_sort (&tmp); new = community_uniq_sort(&tmp);
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;
if (! com->str) if (!com->str)
set_community_string (com); set_community_string(com);
return com->str; return com->str;
} }
/* 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;
@ -481,30 +452,30 @@ community_cmp (const struct community *com1, const struct community *com2)
return 0; return 0;
if (com1->size == com2->size) if (com1->size == com2->size)
if (memcmp (com1->val, com2->val, com1->size * 4) == 0) if (memcmp(com1->val, com2->val, com1->size * 4) == 0)
return 1; return 1;
return 0; return 0;
} }
/* 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;
return com1; return com1;
} }
/* 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,13 +485,12 @@ 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;
/* Skip white space. */ /* Skip white space. */
while (isspace ((int) *p)) while (isspace((int)*p))
p++; p++;
/* Check the end of the line. */ /* Check the end of the line. */
@ -528,34 +498,29 @@ 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");
return p; return p;
} }
@ -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,73 +580,66 @@ 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;
} }
community_add_val (com, val); community_add_val(com, val);
break; break;
case community_token_unknown: case community_token_unknown:
default: default:
if (com) if (com)
community_free (com); community_free(com);
return NULL; return NULL;
} }
} while (str); } while (str);
if (! com) if (!com)
return NULL; return NULL;
com_sort = community_uniq_sort (com); com_sort = community_uniq_sort(com);
community_free (com); community_free(com);
return com_sort; return com_sort;
} }
/* 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(
(int (*) (const void *, const void *))community_cmp, NULL); (unsigned int (*)(void *))community_hash_make,
(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;
@ -56,25 +55,27 @@ struct community
#define com_nthval(X,n) ((X)->val + (n)) #define com_nthval(X,n) ((X)->val + (n))
/* Prototypes of communities attribute functions. */ /* Prototypes of communities attribute functions. */
extern void community_init (void); extern void community_init(void);
extern void community_finish (void); extern void community_finish(void);
extern void community_free (struct community *); extern void community_free(struct community *);
extern struct community *community_uniq_sort (struct community *); extern struct community *community_uniq_sort(struct community *);
extern struct community *community_parse (u_int32_t *, u_short); extern struct community *community_parse(u_int32_t *, u_short);
extern struct community *community_intern (struct community *); extern struct community *community_intern(struct community *);
extern void community_unintern (struct community **); extern void community_unintern(struct community **);
extern char *community_str (struct community *); extern char *community_str(struct community *);
extern unsigned int community_hash_make (struct community *); extern unsigned int community_hash_make(struct community *);
extern struct community *community_str2com (const char *); extern struct community *community_str2com(const char *);
extern int community_match (const struct community *, const struct community *); extern int community_match(const struct community *, const struct community *);
extern int community_cmp (const struct community *, const struct community *); extern int community_cmp(const struct community *, const struct community *);
extern struct community *community_merge (struct community *, struct community *); extern struct community *community_merge(struct community *,
extern struct community *community_delete (struct community *, struct community *); struct community *);
extern struct community *community_dup (struct community *); extern struct community *community_delete(struct community *,
extern int community_include (struct community *, u_int32_t); struct community *);
extern void community_del_val (struct community *, u_int32_t *); extern struct community *community_dup(struct community *);
extern unsigned long community_count (void); extern int community_include(struct community *, u_int32_t);
extern struct hash *community_hash (void); extern void community_del_val(struct community *, u_int32_t *);
extern u_int32_t community_val_get (struct community *com, int i); extern unsigned long community_count(void);
extern struct hash *community_hash(void);
extern u_int32_t community_val_get(struct community *com, int i);
#endif /* _QUAGGA_BGP_COMMUNITY_H */ #endif /* _QUAGGA_BGP_COMMUNITY_H */

View File

@ -46,15 +46,15 @@ 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;
index = damp->reuse_index[i] - damp->reuse_index[0]; index = damp->reuse_index[i] - damp->reuse_index[0];
@ -63,12 +63,11 @@ 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;
index = bdi->index = bgp_reuse_index (bdi->penalty); index = bdi->index = bgp_reuse_index(bdi->penalty);
bdi->prev = NULL; bdi->prev = NULL;
bdi->next = damp->reuse_list[index]; bdi->next = damp->reuse_list[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,12 +88,11 @@ 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;
i = (int) ((double) tdiff / DELTA_T); i = (int)((double)tdiff / DELTA_T);
if (i == 0) if (i == 0)
return penalty; return penalty;
@ -103,13 +100,12 @@ bgp_damp_decay (time_t tdiff, int penalty)
if (i >= damp->decay_array_size) if (i >= damp->decay_array_size)
return 0; return 0;
return (int) (penalty * damp->decay_array[i]); return (int)(penalty * damp->decay_array[i]);
} }
/* 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;
@ -119,7 +115,7 @@ bgp_reuse_timer (struct thread *t)
thread_add_timer(bm->master, bgp_reuse_timer, NULL, DELTA_REUSE, thread_add_timer(bm->master, bgp_reuse_timer, NULL, DELTA_REUSE,
&damp->t_reuse); &damp->t_reuse);
t_now = bgp_clock (); t_now = bgp_clock();
/* 1. save a pointer to the current zeroth queue head and zero the /* 1. save a pointer to the current zeroth queue head and zero the
list head entry. */ list head entry. */
@ -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,57 +135,57 @@ 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
bdi->penalty = bgp_damp_decay (t_diff, bdi->penalty); * [t-diff] */
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,
bgp_process (bgp, bdi->rn, bdi->afi, bdi->safi); bdi->safi);
bgp_process(bgp, bdi->rn, bdi->afi, bdi->safi);
} }
if (bdi->penalty <= damp->reuse_limit / 2.0) if (bdi->penalty <= damp->reuse_limit / 2.0)
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);
} }
return 0; return 0;
} }
/* 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;
double last_penalty = 0; double last_penalty = 0;
t_now = bgp_clock (); t_now = bgp_clock();
/* Processing Unreachable Messages. */ /* Processing Unreachable Messages. */
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,27 +193,28 @@ 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;
bdi->index = -1; bdi->index = -1;
bdi->afi = afi; bdi->afi = afi;
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;
@ -226,42 +222,38 @@ bgp_damp_withdraw (struct bgp_info *binfo, struct bgp_node *rn,
bdi->flap++; bdi->flap++;
} }
assert ((rn == bdi->rn) && (binfo == bdi->binfo)); assert((rn == bdi->rn) && (binfo == bdi->binfo));
bdi->lastrecord = BGP_RECORD_WITHDRAW; bdi->lastrecord = BGP_RECORD_WITHDRAW;
bdi->t_updated = t_now; bdi->t_updated = t_now;
/* Make this route as historical status. */ /* Make this route as historical status. */
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);
} }
return BGP_DAMP_SUPPRESSED; return BGP_DAMP_SUPPRESSED;
} }
/* 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);
bgp_reuse_list_add (bdi); bgp_reuse_list_add(bdi);
} }
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;
@ -270,110 +262,100 @@ bgp_damp_update (struct bgp_info *binfo, struct bgp_node *rn,
if (!binfo->extra || !((bdi = binfo->extra->damp_info))) if (!binfo->extra || !((bdi = binfo->extra->damp_info)))
return BGP_DAMP_USED; return BGP_DAMP_USED;
t_now = bgp_clock (); t_now = bgp_clock();
bgp_info_unset_flag (rn, binfo, BGP_INFO_HISTORY); bgp_info_unset_flag(rn, binfo, BGP_INFO_HISTORY);
bdi->lastrecord = BGP_RECORD_UPDATE; bdi->lastrecord = BGP_RECORD_UPDATE;
bdi->penalty = bgp_damp_decay (t_now - bdi->t_updated, bdi->penalty); bdi->penalty = bgp_damp_decay(t_now - bdi->t_updated, bdi->penalty);
if (! CHECK_FLAG (bdi->binfo->flags, BGP_INFO_DAMPED) if (!CHECK_FLAG(bdi->binfo->flags, BGP_INFO_DAMPED)
&& (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)
bdi->t_updated = t_now; bdi->t_updated = t_now;
else else
bgp_damp_info_free (bdi, 0); bgp_damp_info_free(bdi, 0);
return status; return status;
} }
/* 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;
assert (binfo->extra && binfo->extra->damp_info); assert(binfo->extra && binfo->extra->damp_info);
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);
bdi->penalty = damp->reuse_limit; bdi->penalty = damp->reuse_limit;
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;
if (! bdi) if (!bdi)
return; return;
binfo = bdi->binfo; binfo = bdi->binfo;
binfo->extra->damp_info = NULL; binfo->extra->damp_info = NULL;
if (CHECK_FLAG (binfo->flags, BGP_INFO_DAMPED)) if (CHECK_FLAG(binfo->flags, BGP_INFO_DAMPED))
bgp_reuse_list_delete (bdi); bgp_reuse_list_delete(bdi);
else else
BGP_DAMP_LIST_DEL (damp, bdi); BGP_DAMP_LIST_DEL(damp, bdi);
bgp_info_unset_flag (bdi->rn, binfo, BGP_INFO_HISTORY|BGP_INFO_DAMPED); bgp_info_unset_flag(bdi->rn, binfo, BGP_INFO_HISTORY | BGP_INFO_DAMPED);
if (bdi->lastrecord == BGP_RECORD_WITHDRAW && withdraw) if (bdi->lastrecord == BGP_RECORD_WITHDRAW && withdraw)
bgp_info_delete (bdi->rn, binfo); bgp_info_delete(bdi->rn, binfo);
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,64 +369,71 @@ 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 =
damp->decay_array = XMALLOC (MTYPE_BGP_DAMP_ARRAY, ceil((double)damp->max_suppress_time / DELTA_T);
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;
if (i > REUSE_LIST_SIZE || i == 0) if (i > REUSE_LIST_SIZE || i == 0)
i = REUSE_LIST_SIZE; i = REUSE_LIST_SIZE;
damp->reuse_list_size = i; damp->reuse_list_size = i;
damp->reuse_list = XCALLOC (MTYPE_BGP_DAMP_ARRAY, damp->reuse_list = XCALLOC(MTYPE_BGP_DAMP_ARRAY,
damp->reuse_list_size damp->reuse_list_size
* sizeof (struct bgp_reuse_node *)); * sizeof(struct bgp_reuse_node *));
/* Reuse-array computations */ /* Reuse-array computations */
damp->reuse_index = XCALLOC (MTYPE_BGP_DAMP_ARRAY, damp->reuse_index = XCALLOC(MTYPE_BGP_DAMP_ARRAY,
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)
if ( reuse_max_ratio > j && j != 0 ) * log10(2.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;
bgp_damp_disable (bgp, afi, safi); bgp_damp_disable(bgp, afi, safi);
} }
SET_FLAG (bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING); SET_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING);
bgp_damp_parameter_set (half, reuse, suppress, max); bgp_damp_parameter_set(half, reuse, suppress, max);
/* Register reuse timer. */ /* Register reuse timer. */
thread_add_timer(bm->master, bgp_reuse_timer, NULL, DELTA_REUSE, thread_add_timer(bm->master, bgp_reuse_timer, NULL, DELTA_REUSE,
@ -453,161 +442,155 @@ 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);
/* Free reuse index array */ /* Free reuse index array */
XFREE (MTYPE_BGP_DAMP_ARRAY, damp->reuse_index); XFREE(MTYPE_BGP_DAMP_ARRAY, damp->reuse_index);
/* Free reuse list array. */ /* Free reuse list array. */
XFREE (MTYPE_BGP_DAMP_ARRAY, damp->reuse_list); XFREE(MTYPE_BGP_DAMP_ARRAY, damp->reuse_list);
} }
/* 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))
return 0; return 0;
/* Cancel reuse thread. */ /* Cancel reuse thread. */
if (damp->t_reuse ) if (damp->t_reuse)
thread_cancel (damp->t_reuse); thread_cancel(damp->t_reuse);
damp->t_reuse = NULL; damp->t_reuse = NULL;
/* Clean BGP dampening information. */ /* Clean BGP dampening information. */
bgp_damp_info_clean (); bgp_damp_info_clean();
/* Clear configuration */ /* Clear configuration */
bgp_damp_config_clean (&bgp_damp_cfg); bgp_damp_config_clean(&bgp_damp_cfg);
UNSET_FLAG (bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING); UNSET_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING);
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;
@ -623,42 +606,45 @@ bgp_damp_info_vty (struct vty *vty, struct bgp_info *binfo,
/* If dampening is not enabled or there is no dampening information, /* If dampening is not enabled or there is no dampening information,
return immediately. */ return immediately. */
if (! damp || ! bdi) if (!damp || !bdi)
return; return;
/* Calculate new penalty. */ /* Calculate new penalty. */
t_now = bgp_clock (); t_now = bgp_clock();
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;
@ -672,45 +658,38 @@ bgp_damp_reuse_time_vty (struct vty *vty, struct bgp_info *binfo,
/* If dampening is not enabled or there is no dampening information, /* If dampening is not enabled or there is no dampening information,
return immediately. */ return immediately. */
if (! damp || ! bdi) if (!damp || !bdi)
return NULL; return NULL;
/* Calculate new penalty. */ /* Calculate new penalty. */
t_now = bgp_clock (); t_now = bgp_clock();
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);
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;
@ -107,7 +105,7 @@ struct bgp_damp_config
struct bgp_damp_info *no_reuse_list; struct bgp_damp_info *no_reuse_list;
/* Reuse timer thread per-set base. */ /* Reuse timer thread per-set base. */
struct thread* t_reuse; struct thread *t_reuse;
}; };
#define BGP_DAMP_NONE 0 #define BGP_DAMP_NONE 0
@ -129,20 +127,22 @@ struct bgp_damp_config
#define REUSE_LIST_SIZE 256 #define REUSE_LIST_SIZE 256
#define REUSE_ARRAY_SIZE 1024 #define REUSE_ARRAY_SIZE 1024
extern int bgp_damp_enable (struct bgp *, afi_t, safi_t, time_t, unsigned int, extern int bgp_damp_enable(struct bgp *, afi_t, safi_t, time_t, unsigned int,
unsigned int, time_t); unsigned int, time_t);
extern int bgp_damp_disable (struct bgp *, afi_t, safi_t); extern int bgp_damp_disable(struct bgp *, afi_t, safi_t);
extern int bgp_damp_withdraw (struct bgp_info *, struct bgp_node *, extern int bgp_damp_withdraw(struct bgp_info *, struct bgp_node *, afi_t,
afi_t, safi_t, int); safi_t, int);
extern int bgp_damp_update (struct bgp_info *, struct bgp_node *, afi_t, safi_t); extern int bgp_damp_update(struct bgp_info *, struct bgp_node *, afi_t, safi_t);
extern int bgp_damp_scan (struct bgp_info *, afi_t, safi_t); extern int bgp_damp_scan(struct bgp_info *, afi_t, safi_t);
extern void bgp_damp_info_free (struct bgp_damp_info *, int); extern void bgp_damp_info_free(struct bgp_damp_info *, int);
extern void bgp_damp_info_clean (void); extern void bgp_damp_info_clean(void);
extern int bgp_damp_decay (time_t, int); extern int bgp_damp_decay(time_t, int);
extern void bgp_config_write_damp (struct vty *); extern void bgp_config_write_damp(struct vty *);
extern void bgp_damp_info_vty (struct vty *, struct bgp_info *, json_object *json_path); extern void bgp_damp_info_vty(struct vty *, struct bgp_info *,
extern const char * bgp_damp_reuse_time_vty (struct vty *, struct bgp_info *, json_object *json_path);
char *, size_t, u_char, json_object *); extern const char *bgp_damp_reuse_time_vty(struct vty *, struct bgp_info *,
extern int bgp_show_dampening_parameters (struct vty *vty, afi_t, safi_t); char *, size_t, u_char,
json_object *);
extern int bgp_show_dampening_parameters(struct vty *vty, afi_t, safi_t);
#endif /* _QUAGGA_BGP_DAMP_H */ #endif /* _QUAGGA_BGP_DAMP_H */

File diff suppressed because it is too large Load Diff

View File

@ -57,10 +57,10 @@ extern int Debug_Radix;
#define DETAIL 6 #define DETAIL 6
/* Prototypes. */ /* Prototypes. */
extern void bgp_debug_init (void); extern void bgp_debug_init(void);
extern void bgp_packet_dump (struct stream *); extern void bgp_packet_dump(struct stream *);
extern int debug (unsigned int option); extern int debug(unsigned int option);
extern unsigned long conf_bgp_debug_as4; extern unsigned long conf_bgp_debug_as4;
extern unsigned long conf_bgp_debug_neighbor_events; extern unsigned long conf_bgp_debug_neighbor_events;
@ -92,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;
}; };
@ -138,11 +137,11 @@ struct bgp_debug_filter
extern const char *bgp_type_str[]; extern const char *bgp_type_str[];
extern int bgp_dump_attr (struct attr *, char *, size_t); extern int bgp_dump_attr(struct attr *, char *, size_t);
extern int bgp_debug_peer_updout_enabled(char *host); extern int bgp_debug_peer_updout_enabled(char *host);
extern const char *bgp_notify_code_str(char); extern const char *bgp_notify_code_str(char);
extern const char *bgp_notify_subcode_str(char, char); extern const char *bgp_notify_subcode_str(char, char);
extern void bgp_notify_print (struct peer *, struct bgp_notify *, const char *); extern void bgp_notify_print(struct peer *, struct bgp_notify *, const char *);
extern const struct message bgp_status_msg[]; extern const struct message bgp_status_msg[];
extern int bgp_debug_neighbor_events(struct peer *peer); extern int bgp_debug_neighbor_events(struct peer *peer);
@ -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,15 +48,11 @@ 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 {
MSG_NULL, MSG_NULL,
@ -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;
@ -91,8 +85,8 @@ struct bgp_dump
struct thread *t_interval; struct thread *t_interval;
}; };
static int bgp_dump_unset (struct bgp_dump *bgp_dump); static int bgp_dump_unset(struct bgp_dump *bgp_dump);
static int bgp_dump_interval_func (struct thread *); static int bgp_dump_interval_func(struct thread *);
/* BGP packet dump output buffer. */ /* BGP packet dump output buffer. */
struct stream *bgp_dump_obuf; struct stream *bgp_dump_obuf;
@ -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;
@ -116,33 +109,30 @@ bgp_dump_open_file (struct bgp_dump *bgp_dump)
char realpath[MAXPATHLEN]; char realpath[MAXPATHLEN];
mode_t oldumask; mode_t oldumask;
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
} ret = strftime(realpath, MAXPATHLEN, bgp_dump->filename, tm);
else
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;
} }
if (bgp_dump->fp) if (bgp_dump->fp)
fclose (bgp_dump->fp); fclose(bgp_dump->fp);
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;
@ -204,29 +194,27 @@ bgp_dump_header (struct stream *obuf, int type, int subtype, int dump_type)
msecs = clock.tv_usec; msecs = clock.tv_usec;
/* Put dump packet header. */ /* Put dump packet header. */
stream_putl (obuf, secs); stream_putl(obuf, secs);
stream_putw (obuf, type); stream_putw(obuf, type);
stream_putw (obuf, subtype); stream_putw(obuf, subtype);
stream_putl (obuf, 0); /* len */ stream_putl(obuf, 0); /* len */
/* Adding microseconds for the MRT Extended Header */ /* Adding microseconds for the MRT Extended Header */
if (type == MSG_PROTOCOL_BGP4MP_ET) if (type == MSG_PROTOCOL_BGP4MP_ET)
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:
* "The Microsecond Timestamp is included in the computation * "The Microsecond Timestamp is included in the computation
* of the Length field value." (RFC6396 2011) * of the Length field value." (RFC6396 2011)
*/ */
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;
@ -234,70 +222,69 @@ bgp_dump_routes_index_table(struct bgp *bgp)
struct stream *obuf; struct stream *obuf;
obuf = bgp_dump_obuf; obuf = bgp_dump_obuf;
stream_reset (obuf); stream_reset(obuf);
/* MRT header */ /* MRT header */
bgp_dump_header (obuf, MSG_TABLE_DUMP_V2, TABLE_DUMP_V2_PEER_INDEX_TABLE, bgp_dump_header(obuf, MSG_TABLE_DUMP_V2, TABLE_DUMP_V2_PEER_INDEX_TABLE,
BGP_DUMP_ROUTES); BGP_DUMP_ROUTES);
/* Collector BGP ID */ /* Collector BGP ID */
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);
} }
/* Peer count ( plus one extra internal peer ) */ /* Peer count ( plus one extra internal peer ) */
stream_putw (obuf, listcount(bgp->peer) + 1); stream_putw(obuf, listcount(bgp->peer) + 1);
/* 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) */
stream_putl (obuf, 0); stream_putl(obuf, 0);
/* Peer ASN (0) */ /* Peer ASN (0) */
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) {
} stream_write(obuf, (u_char *)&peer->su.sin6.sin6_addr,
else if (sockunion_family(&peer->su) == AF_INET6)
{
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
stream_putl (obuf, peer->as); * always AS4 */
stream_putl(obuf, peer->as);
/* Store the peer number for this peer */ /* Store the peer number for this peer */
peer->table_dump_index = peerno; peer->table_dump_index = peerno;
@ -306,77 +293,78 @@ bgp_dump_routes_index_table(struct bgp *bgp)
bgp_dump_set_size(obuf, MSG_TABLE_DUMP_V2); bgp_dump_set_size(obuf, MSG_TABLE_DUMP_V2);
fwrite (STREAM_DATA (obuf), stream_get_endp (obuf), 1, bgp_dump_routes.fp); fwrite(STREAM_DATA(obuf), stream_get_endp(obuf), 1, bgp_dump_routes.fp);
fflush (bgp_dump_routes.fp); fflush(bgp_dump_routes.fp);
} }
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;
size_t endp; size_t endp;
obuf = bgp_dump_obuf; obuf = bgp_dump_obuf;
stream_reset (obuf); stream_reset(obuf);
/* 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 */
stream_putl (obuf, seq); stream_putl(obuf, seq);
/* Prefix length */ /* Prefix length */
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 */
sizep = stream_get_endp (obuf); sizep = stream_get_endp(obuf);
/* Entry count */ /* Entry count */
uint16_t entry_count = 0; uint16_t entry_count = 0;
/* Entry count, note that this is overwritten later */ /* Entry count, note that this is overwritten later */
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 */
stream_putw (obuf, info->peer->table_dump_index); stream_putw(obuf, info->peer->table_dump_index);
/* Originated */ /* Originated */
stream_putl (obuf, time(NULL) - (bgp_clock() - info->uptime)); stream_putl(obuf, time(NULL) - (bgp_clock() - info->uptime));
/* Dump attribute. */ /* Dump attribute. */
/* Skip prefix & AFI/SAFI for MP_NLRI */ /* Skip prefix & AFI/SAFI for MP_NLRI */
bgp_dump_routes_attr (obuf, info->attr, &rn->p); bgp_dump_routes_attr(obuf, info->attr, &rn->p);
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;
} }
@ -385,25 +373,25 @@ bgp_dump_route_node_record (int afi, struct bgp_node *rn,
} }
/* Overwrite the entry count, now that we know the right number */ /* Overwrite the entry count, now that we know the right number */
stream_putw_at (obuf, sizep, entry_count); stream_putw_at(obuf, sizep, entry_count);
bgp_dump_set_size (obuf, MSG_TABLE_DUMP_V2); bgp_dump_set_size(obuf, MSG_TABLE_DUMP_V2);
fwrite (STREAM_DATA (obuf), stream_get_endp (obuf), 1, bgp_dump_routes.fp); fwrite(STREAM_DATA(obuf), stream_get_endp(obuf), 1, bgp_dump_routes.fp);
return info; return info;
} }
/* 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;
struct bgp *bgp; struct bgp *bgp;
struct bgp_table *table; struct bgp_table *table;
bgp = bgp_get_default (); bgp = bgp_get_default();
if (!bgp) if (!bgp)
return seq; return seq;
@ -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,98 +408,91 @@ 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++;
} }
} }
fflush (bgp_dump_routes.fp); fflush(bgp_dump_routes.fp);
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
/* Close the file now. For a RIB dump there's no point in leaving * 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;
} }
} }
/* if interval is set reschedule */ /* if interval is set reschedule */
if (bgp_dump->interval > 0) if (bgp_dump->interval > 0)
bgp_dump_interval_add (bgp_dump, bgp_dump->interval); bgp_dump_interval_add(bgp_dump, bgp_dump->interval);
return 0; return 0;
} }
/* 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 {
} stream_putw(obuf, peer->as);
else stream_putw(obuf, peer->local_as);
{
stream_putw (obuf, peer->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);
/* Source IP Address and Destination IP Address. */ /* Source IP Address and Destination IP Address. */
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;
@ -520,25 +502,24 @@ bgp_dump_state (struct peer *peer, int status_old, int status_new)
/* Make dump stream. */ /* Make dump stream. */
obuf = bgp_dump_obuf; obuf = bgp_dump_obuf;
stream_reset (obuf); stream_reset(obuf);
bgp_dump_header (obuf, MSG_PROTOCOL_BGP4MP, BGP4MP_STATE_CHANGE_AS4, bgp_dump_header(obuf, MSG_PROTOCOL_BGP4MP, BGP4MP_STATE_CHANGE_AS4,
bgp_dump_all.type); bgp_dump_all.type);
bgp_dump_common (obuf, peer, 1);/* force this in as4speak*/ bgp_dump_common(obuf, peer, 1); /* force this in as4speak*/
stream_putw (obuf, status_old); stream_putw(obuf, status_old);
stream_putw (obuf, status_new); stream_putw(obuf, status_new);
/* Set length. */ /* Set length. */
bgp_dump_set_size (obuf, MSG_PROTOCOL_BGP4MP); bgp_dump_set_size(obuf, MSG_PROTOCOL_BGP4MP);
/* Write to the stream. */ /* Write to the stream. */
fwrite (STREAM_DATA (obuf), stream_get_endp (obuf), 1, bgp_dump_all.fp); fwrite(STREAM_DATA(obuf), stream_get_endp(obuf), 1, bgp_dump_all.fp);
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;
@ -549,46 +530,41 @@ bgp_dump_packet_func (struct bgp_dump *bgp_dump, struct peer *peer,
/* Make dump stream. */ /* Make dump stream. */
obuf = bgp_dump_obuf; obuf = bgp_dump_obuf;
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);
} else {
bgp_dump_header(obuf, MSG_PROTOCOL_BGP4MP, BGP4MP_MESSAGE,
bgp_dump->type); bgp_dump->type);
} }
else bgp_dump_common(obuf, peer, 0);
{
bgp_dump_header (obuf, MSG_PROTOCOL_BGP4MP, BGP4MP_MESSAGE,
bgp_dump->type);
}
bgp_dump_common (obuf, peer, 0);
/* Packet contents. */ /* Packet contents. */
stream_put (obuf, STREAM_DATA (packet), stream_get_endp (packet)); stream_put(obuf, STREAM_DATA(packet), stream_get_endp(packet));
/* Set length. */ /* Set length. */
bgp_dump_set_size (obuf, MSG_PROTOCOL_BGP4MP); bgp_dump_set_size(obuf, MSG_PROTOCOL_BGP4MP);
/* Write to the stream. */ /* Write to the stream. */
fwrite (STREAM_DATA (obuf), stream_get_endp (obuf), 1, bgp_dump->fp); fwrite(STREAM_DATA(obuf), stream_get_endp(obuf), 1, bgp_dump->fp);
fflush (bgp_dump->fp); fflush(bgp_dump->fp);
} }
/* 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);
/* bgp_dump_updates. */ /* bgp_dump_updates. */
if (type == BGP_MSG_UPDATE) if (type == BGP_MSG_UPDATE)
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;
@ -601,41 +577,33 @@ bgp_dump_parse_time (const char *str)
total = 0; total = 0;
seen_h = 0; seen_h = 0;
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)
return 0; return 0;
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;
} }
@ -686,46 +648,41 @@ bgp_dump_set (struct vty *vty, struct bgp_dump *bgp_dump,
bgp_dump->interval = interval; bgp_dump->interval = interval;
/* Set file name. */ /* Set file name. */
bgp_dump->filename = XSTRDUP (MTYPE_BGP_DUMP_STR, path); bgp_dump->filename = XSTRDUP(MTYPE_BGP_DUMP_STR, path);
/* Create interval thread. */ /* Create interval thread. */
bgp_dump_interval_add (bgp_dump, interval); bgp_dump_interval_add(bgp_dump, interval);
/* This should be called when interval is expired. */ /* This should be called when interval is expired. */
bgp_dump_open_file (bgp_dump); bgp_dump_open_file(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;
} }
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;
@ -776,7 +732,7 @@ DEFUN (dump_bgp_all,
if (argc == idx_interval + 1) if (argc == idx_interval + 1)
interval = argv[idx_interval]->arg; interval = argv[idx_interval]->arg;
return bgp_dump_set (vty, bgp_dump_struct, bgp_dump_type, return bgp_dump_set(vty, bgp_dump_struct, bgp_dump_type,
argv[idx_path]->arg, interval); argv[idx_path]->arg, interval);
} }
@ -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;
@ -819,16 +774,11 @@ DEFUN (no_dump_bgp_all,
break; break;
} }
return bgp_dump_unset (bgp_dump_struct); return bgp_dump_unset(bgp_dump_struct);
} }
/* 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,72 +806,69 @@ 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);
install_element (CONFIG_NODE, &dump_bgp_all_cmd); install_element(CONFIG_NODE, &dump_bgp_all_cmd);
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);
bgp_dump_unset (&bgp_dump_routes); bgp_dump_unset(&bgp_dump_routes);
stream_free (bgp_dump_obuf); stream_free(bgp_dump_obuf);
bgp_dump_obuf = NULL; bgp_dump_obuf = NULL;
} }

View File

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

File diff suppressed because it is too large Load Diff

View File

@ -32,12 +32,15 @@
#define ECOMMUNITY_ROUTE_TARGET 0x02 #define ECOMMUNITY_ROUTE_TARGET 0x02
#define ECOMMUNITY_SITE_ORIGIN 0x03 #define ECOMMUNITY_SITE_ORIGIN 0x03
/* Low-order octet of the Extended Communities type field for EVPN types */
#define ECOMMUNITY_EVPN_SUBTYPE_MACMOBILITY 0x00 #define ECOMMUNITY_EVPN_SUBTYPE_MACMOBILITY 0x00
#define ECOMMUNITY_EVPN_SUBTYPE_ESI_LABEL 0x01 #define ECOMMUNITY_EVPN_SUBTYPE_ESI_LABEL 0x01
#define ECOMMUNITY_EVPN_SUBTYPE_ES_IMPORT_RT 0x02 #define ECOMMUNITY_EVPN_SUBTYPE_ES_IMPORT_RT 0x02
#define ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC 0x03 #define ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC 0x03
#define ECOMMUNITY_EVPN_SUBTYPE_DEF_GW 0x0d #define ECOMMUNITY_EVPN_SUBTYPE_DEF_GW 0x0d
#define ECOMMUNITY_EVPN_SUBTYPE_MACMOBILITY_FLAG_STICKY 0x01
/* Low-order octet of the Extended Communities type field for OPAQUE types */ /* Low-order octet of the Extended Communities type field for OPAQUE types */
#define ECOMMUNITY_OPAQUE_SUBTYPE_ENCAP 0x0c #define ECOMMUNITY_OPAQUE_SUBTYPE_ENCAP 0x0c
@ -53,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,34 +71,83 @@ 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)
extern void ecommunity_init (void); /*
extern void ecommunity_finish (void); * Encode BGP Route Target AS:nn.
extern void ecommunity_free (struct ecommunity **); */
extern struct ecommunity *ecommunity_parse (u_int8_t *, u_short); static inline void encode_route_target_as(as_t as, u_int32_t val,
extern struct ecommunity *ecommunity_dup (struct ecommunity *); struct ecommunity_val *eval)
extern struct ecommunity *ecommunity_merge (struct ecommunity *, struct ecommunity *); {
extern struct ecommunity *ecommunity_uniq_sort (struct ecommunity *); eval->val[0] = ECOMMUNITY_ENCODE_AS;
extern struct ecommunity *ecommunity_intern (struct ecommunity *); eval->val[1] = ECOMMUNITY_ROUTE_TARGET;
extern int ecommunity_cmp (const void *, const void *); eval->val[2] = (as >> 8) & 0xff;
extern void ecommunity_unintern (struct ecommunity **); eval->val[3] = as & 0xff;
extern unsigned int ecommunity_hash_make (void *); eval->val[4] = (val >> 24) & 0xff;
extern struct ecommunity *ecommunity_str2com (const char *, int, int); eval->val[5] = (val >> 16) & 0xff;
extern char *ecommunity_ecom2str (struct ecommunity *, int, int); eval->val[6] = (val >> 8) & 0xff;
extern int ecommunity_match (const struct ecommunity *, const struct ecommunity *); eval->val[7] = val & 0xff;
extern char *ecommunity_str (struct ecommunity *); }
extern struct ecommunity_val *ecommunity_lookup (const struct ecommunity *, uint8_t, uint8_t );
extern int ecommunity_add_val (struct ecommunity *ecom, struct ecommunity_val *eval); /*
* Encode BGP Route Target IP:nn.
*/
static inline void encode_route_target_ip(struct in_addr ip, u_int16_t val,
struct ecommunity_val *eval)
{
eval->val[0] = ECOMMUNITY_ENCODE_IP;
eval->val[1] = ECOMMUNITY_ROUTE_TARGET;
memcpy(&eval->val[2], &ip, sizeof(struct in_addr));
eval->val[6] = (val >> 8) & 0xff;
eval->val[7] = val & 0xff;
}
/*
* Encode BGP Route Target AS4:nn.
*/
static inline void encode_route_target_as4(as_t as, u_int16_t val,
struct ecommunity_val *eval)
{
eval->val[0] = ECOMMUNITY_ENCODE_AS4;
eval->val[1] = ECOMMUNITY_ROUTE_TARGET;
eval->val[2] = (as >> 24) & 0xff;
eval->val[3] = (as >> 16) & 0xff;
eval->val[4] = (as >> 8) & 0xff;
eval->val[5] = as & 0xff;
eval->val[6] = (val >> 8) & 0xff;
eval->val[7] = val & 0xff;
}
extern void ecommunity_init(void);
extern void ecommunity_finish(void);
extern void ecommunity_free(struct ecommunity **);
extern struct ecommunity *ecommunity_parse(u_int8_t *, u_short);
extern struct ecommunity *ecommunity_dup(struct ecommunity *);
extern struct ecommunity *ecommunity_merge(struct ecommunity *,
struct ecommunity *);
extern struct ecommunity *ecommunity_uniq_sort(struct ecommunity *);
extern struct ecommunity *ecommunity_intern(struct ecommunity *);
extern int ecommunity_cmp(const void *, const void *);
extern void ecommunity_unintern(struct ecommunity **);
extern unsigned int ecommunity_hash_make(void *);
extern struct ecommunity *ecommunity_str2com(const char *, int, int);
extern char *ecommunity_ecom2str(struct ecommunity *, int, int);
extern int ecommunity_match(const struct ecommunity *,
const struct ecommunity *);
extern char *ecommunity_str(struct ecommunity *);
extern struct ecommunity_val *ecommunity_lookup(const struct ecommunity *,
uint8_t, uint8_t);
extern int ecommunity_add_val(struct ecommunity *ecom,
struct ecommunity_val *eval);
/* for vpn */ /* for vpn */
extern struct ecommunity *ecommunity_new (void); extern struct ecommunity *ecommunity_new(void);
extern int ecommunity_add_val (struct ecommunity *, struct ecommunity_val *); extern int ecommunity_add_val(struct ecommunity *, struct ecommunity_val *);
extern int ecommunity_strip (struct ecommunity *ecom, uint8_t type, uint8_t subtype); extern int ecommunity_strip(struct ecommunity *ecom, uint8_t type,
extern struct ecommunity *ecommunity_new (void); uint8_t subtype);
extern struct ecommunity *ecommunity_new(void);
#endif /* _QUAGGA_BGP_ECOMMUNITY_H */ #endif /* _QUAGGA_BGP_ECOMMUNITY_H */

File diff suppressed because it is too large Load Diff

View File

@ -19,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,31 +19,36 @@
#ifndef _QUAGGA_BGP_ENCAP_TYPES_H #ifndef _QUAGGA_BGP_ENCAP_TYPES_H
#define _QUAGGA_BGP_ENCAP_TYPES_H #define _QUAGGA_BGP_ENCAP_TYPES_H
/* from http://www.iana.org/assignments/bgp-parameters/bgp-parameters.xhtml#tunnel-types */ #include "bgpd/bgp_ecommunity.h"
/* from
* http://www.iana.org/assignments/bgp-parameters/bgp-parameters.xhtml#tunnel-types
*/
typedef enum { typedef enum {
BGP_ENCAP_TYPE_RESERVED=0, BGP_ENCAP_TYPE_RESERVED = 0,
BGP_ENCAP_TYPE_L2TPV3_OVER_IP=1, BGP_ENCAP_TYPE_L2TPV3_OVER_IP = 1,
BGP_ENCAP_TYPE_GRE=2, BGP_ENCAP_TYPE_GRE = 2,
BGP_ENCAP_TYPE_TRANSMIT_TUNNEL_ENDPOINT=3, BGP_ENCAP_TYPE_TRANSMIT_TUNNEL_ENDPOINT = 3,
BGP_ENCAP_TYPE_IPSEC_IN_TUNNEL_MODE=4, BGP_ENCAP_TYPE_IPSEC_IN_TUNNEL_MODE = 4,
BGP_ENCAP_TYPE_IP_IN_IP_TUNNEL_WITH_IPSEC_TRANSPORT_MODE=5, BGP_ENCAP_TYPE_IP_IN_IP_TUNNEL_WITH_IPSEC_TRANSPORT_MODE = 5,
BGP_ENCAP_TYPE_MPLS_IN_IP_TUNNEL_WITH_IPSEC_TRANSPORT_MODE=6, BGP_ENCAP_TYPE_MPLS_IN_IP_TUNNEL_WITH_IPSEC_TRANSPORT_MODE = 6,
BGP_ENCAP_TYPE_IP_IN_IP=7, BGP_ENCAP_TYPE_IP_IN_IP = 7,
BGP_ENCAP_TYPE_VXLAN=8, BGP_ENCAP_TYPE_VXLAN = 8,
BGP_ENCAP_TYPE_NVGRE=9, BGP_ENCAP_TYPE_NVGRE = 9,
BGP_ENCAP_TYPE_MPLS=10, /* NOTE: Encap SAFI&Attribute not used */ BGP_ENCAP_TYPE_MPLS = 10, /* NOTE: Encap SAFI&Attribute not used */
BGP_ENCAP_TYPE_MPLS_IN_GRE=11, BGP_ENCAP_TYPE_MPLS_IN_GRE = 11,
BGP_ENCAP_TYPE_VXLAN_GPE=12, BGP_ENCAP_TYPE_VXLAN_GPE = 12,
BGP_ENCAP_TYPE_MPLS_IN_UDP=13, BGP_ENCAP_TYPE_MPLS_IN_UDP = 13,
BGP_ENCAP_TYPE_PBB BGP_ENCAP_TYPE_PBB
} bgp_encap_types; } bgp_encap_types;
typedef enum { typedef enum {
BGP_ENCAP_SUBTLV_TYPE_ENCAPSULATION=1, BGP_ENCAP_SUBTLV_TYPE_ENCAPSULATION = 1,
BGP_ENCAP_SUBTLV_TYPE_PROTO_TYPE=2, BGP_ENCAP_SUBTLV_TYPE_PROTO_TYPE = 2,
BGP_ENCAP_SUBTLV_TYPE_IPSEC_TA=3, BGP_ENCAP_SUBTLV_TYPE_IPSEC_TA = 3,
BGP_ENCAP_SUBTLV_TYPE_COLOR=4, BGP_ENCAP_SUBTLV_TYPE_COLOR = 4,
BGP_ENCAP_SUBTLV_TYPE_REMOTE_ENDPOINT=6 /* speculative, IANA assignment TBD */ BGP_ENCAP_SUBTLV_TYPE_REMOTE_ENDPOINT =
6 /* speculative, IANA assignment TBD */
} bgp_encap_subtlv_types; } bgp_encap_subtlv_types;
/* /*
@ -60,10 +65,10 @@ struct bgp_tea_subtlv_encap_gre_key {
}; };
struct bgp_tea_subtlv_encap_pbb { struct bgp_tea_subtlv_encap_pbb {
uint32_t flag_isid:1; uint32_t flag_isid : 1;
uint32_t flag_vid:1; uint32_t flag_vid : 1;
uint32_t isid:24; uint32_t isid : 24;
uint16_t vid:12; uint16_t vid : 12;
uint8_t macaddr[6]; uint8_t macaddr[6];
}; };
@ -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;
@ -49,15 +47,14 @@ struct as_list_master
struct as_list_list str; struct as_list_list str;
/* Hook function which is executed when new access_list is added. */ /* Hook function which is executed when new access_list is added. */
void (*add_hook) (char *); void (*add_hook)(char *);
/* Hook function which is executed when access_list is deleted. */ /* Hook function which is executed when access_list is deleted. */
void (*delete_hook) (const char *); void (*delete_hook)(const char *);
}; };
/* 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,60 +79,55 @@ 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);
if (asfilter->reg_str) if (asfilter->reg_str)
XFREE (MTYPE_AS_FILTER_STR, asfilter->reg_str); XFREE(MTYPE_AS_FILTER_STR, asfilter->reg_str);
XFREE (MTYPE_AS_FILTER, asfilter); XFREE(MTYPE_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;
asfilter = as_filter_new (); asfilter = as_filter_new();
asfilter->reg = reg; asfilter->reg = reg;
asfilter->type = type; asfilter->type = type;
asfilter->reg_str = XSTRDUP (MTYPE_AS_FILTER_STR, reg_str); asfilter->reg_str = XSTRDUP(MTYPE_AS_FILTER_STR, reg_str);
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;
for (asfilter = aslist->head; asfilter; asfilter = asfilter->next) for (asfilter = aslist->head; asfilter; asfilter = asfilter->next)
if (strcmp (reg_str, asfilter->reg_str) == 0) if (strcmp(reg_str, asfilter->reg_str) == 0)
return asfilter; return asfilter;
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;
@ -149,13 +140,11 @@ 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;
@ -163,37 +152,33 @@ as_list_lookup (const char *name)
return NULL; return NULL;
for (aslist = as_list_master.num.head; aslist; aslist = aslist->next) for (aslist = as_list_master.num.head; aslist; aslist = aslist->next)
if (strcmp (aslist->name, name) == 0) if (strcmp(aslist->name, name) == 0)
return aslist; return aslist;
for (aslist = as_list_master.str.head; aslist; aslist = aslist->next) for (aslist = as_list_master.str.head; aslist; aslist = aslist->next)
if (strcmp (aslist->name, name) == 0) if (strcmp(aslist->name, name) == 0)
return aslist; return aslist;
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;
} }
XFREE (MTYPE_AS_LIST, aslist); XFREE(MTYPE_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;
@ -202,34 +187,30 @@ as_list_insert (const char *name)
struct as_list_list *list; struct as_list_list *list;
/* Allocate new access_list and copy given name. */ /* Allocate new access_list and copy given name. */
aslist = as_list_new (); aslist = as_list_new();
aslist->name = XSTRDUP(MTYPE_AS_STR, name); aslist->name = XSTRDUP(MTYPE_AS_STR, name);
assert (aslist->name); assert(aslist->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
break; break;
} }
/* 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. */
list = &as_list_master.num; list = &as_list_master.num;
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. */
@ -237,20 +218,18 @@ as_list_insert (const char *name)
/* Set point to insertion point. */ /* Set point to insertion point. */
for (point = list->head; point; point = point->next) for (point = list->head; point; point = point->next)
if (strcmp (point->name, name) >= 0) if (strcmp(point->name, name) >= 0)
break; break;
} }
/* 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,23 +255,20 @@ 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;
aslist = as_list_lookup (name); aslist = as_list_lookup(name);
if (aslist == NULL) if (aslist == NULL)
aslist = as_list_insert (name); aslist = as_list_insert(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,16 +278,14 @@ 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);
} }
if (aslist->type == ACCESS_TYPE_NUMBER) if (aslist->type == ACCESS_TYPE_NUMBER)
@ -330,11 +303,10 @@ as_list_delete (struct as_list *aslist)
else else
list->head = aslist->next; list->head = aslist->next;
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);
@ -357,70 +329,63 @@ as_list_filter_delete (struct as_list *aslist, struct as_filter *asfilter)
else else
aslist->head = asfilter->next; aslist->head = asfilter->next;
as_filter_free (asfilter); as_filter_free(asfilter);
/* If access_list becomes empty delete it from access_master. */ /* If access_list becomes empty delete it from access_master. */
if (as_list_empty (aslist)) if (as_list_empty(aslist))
as_list_delete (aslist); as_list_delete(aslist);
/* Run hook function. */ /* Run hook function. */
if (as_list_master.delete_hook) if (as_list_master.delete_hook)
(*as_list_master.delete_hook) (name); (*as_list_master.delete_hook)(name);
if (name) if (name)
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;
return 0; return 0;
} }
/* 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;
aspath = (struct aspath *) object; aspath = (struct aspath *)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;
} }
return AS_FILTER_DENY; return AS_FILTER_DENY;
} }
/* 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;
} }
return 0; return 0;
@ -445,35 +410,36 @@ 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_CONFIG_FAILED;
return CMD_WARNING;
} }
asfilter = as_filter_make (regex, regstr, type); asfilter = as_filter_make(regex, regstr, type);
XFREE (MTYPE_TMP, regstr); XFREE(MTYPE_TMP, regstr);
/* Install new filter to the access_list. */ /* Install new filter to the access_list. */
aslist = as_list_get (alname); aslist = as_list_get(alname);
/* Duplicate insertion check. */; /* Duplicate insertion check. */;
if (as_list_dup_check (aslist, asfilter)) if (as_list_dup_check(aslist, asfilter))
as_filter_free (asfilter); as_filter_free(asfilter);
else else
as_list_filter_add (aslist, asfilter); as_list_filter_add(aslist, asfilter);
return CMD_SUCCESS; return CMD_SUCCESS;
} }
@ -497,52 +463,50 @@ 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. */
if (argv_find (argv, argc, "permit", &idx)) if (argv_find(argv, argc, "permit", &idx))
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. */
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_CONFIG_FAILED;
return CMD_WARNING;
} }
/* Lookup asfilter. */ /* Lookup asfilter. */
asfilter = as_filter_lookup (aslist, regstr, type); asfilter = as_filter_lookup(aslist, regstr, type);
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);
return CMD_SUCCESS; return CMD_SUCCESS;
} }
@ -559,61 +523,57 @@ DEFUN (no_ip_as_path_all,
int idx_word = 4; int idx_word = 4;
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);
/* Run hook function. */ /* Run hook function. */
if (as_list_master.delete_hook) if (as_list_master.delete_hook)
(*as_list_master.delete_hook) (argv[idx_word]->arg); (*as_list_master.delete_hook)(argv[idx_word]->arg);
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);
} }
} }
@ -630,9 +590,9 @@ DEFUN (show_ip_as_path_access_list,
int idx_word = 3; int idx_word = 3;
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) if (aslist)
as_list_show (vty, aslist); as_list_show(vty, aslist);
return CMD_SUCCESS; return CMD_SUCCESS;
} }
@ -644,79 +604,69 @@ DEFUN (show_ip_as_path_access_list_all,
IP_STR IP_STR
"List AS path access lists\n") "List AS path access lists\n")
{ {
as_list_show_all (vty); as_list_show_all(vty);
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++;
} }
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);
install_element (CONFIG_NODE, &ip_as_path_cmd); install_element(CONFIG_NODE, &ip_as_path_cmd);
install_element (CONFIG_NODE, &no_ip_as_path_cmd); install_element(CONFIG_NODE, &no_ip_as_path_cmd);
install_element (CONFIG_NODE, &no_ip_as_path_all_cmd); install_element(CONFIG_NODE, &no_ip_as_path_all_cmd);
install_element (VIEW_NODE, &show_ip_as_path_access_list_cmd); install_element(VIEW_NODE, &show_ip_as_path_access_list_cmd);
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);
} }
assert (as_list_master.num.head == NULL); assert(as_list_master.num.head == NULL);
assert (as_list_master.num.tail == NULL); assert(as_list_master.num.tail == NULL);
assert (as_list_master.str.head == NULL); assert(as_list_master.str.head == NULL);
assert (as_list_master.str.tail == NULL); assert(as_list_master.str.tail == NULL);
} }

View File

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

File diff suppressed because it is too large Load Diff

View File

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

View File

@ -41,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,57 +62,54 @@ 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);
bgp_process (bgp, rn, afi, safi); bgp_process(bgp, rn, afi, safi);
return 1; return 1;
} }
u_char * mpls_label_t bgp_adv_label(struct bgp_node *rn, struct bgp_info *ri,
bgp_adv_label (struct bgp_node *rn, struct bgp_info *ri, struct peer *to, struct peer *to, afi_t afi, safi_t safi)
afi_t afi, safi_t safi)
{ {
struct peer *from; struct peer *from;
u_char *remote_label; mpls_label_t remote_label;
int reflect; int reflect;
if (!rn || !ri || !to) if (!rn || !ri || !to)
return NULL; return MPLS_INVALID_LABEL;
remote_label = ri->extra ? ri->extra->tag : NULL; remote_label = ri->extra ? ri->extra->label : MPLS_INVALID_LABEL;
from = ri->peer; from = ri->peer;
reflect = ((from->sort == BGP_PEER_IBGP) && (to->sort == BGP_PEER_IBGP)); reflect =
((from->sort == BGP_PEER_IBGP) && (to->sort == BGP_PEER_IBGP));
if (reflect && !CHECK_FLAG(to->af_flags[afi][safi], if (reflect
&& !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;
@ -139,62 +133,66 @@ bgp_reg_dereg_for_label (struct bgp_node *rn, struct bgp_info *ri,
p = &(rn->p); p = &(rn->p);
s = zclient->obuf; s = zclient->obuf;
stream_reset (s); stream_reset(s);
command = (reg) ? ZEBRA_FEC_REGISTER : ZEBRA_FEC_UNREGISTER; command = (reg) ? ZEBRA_FEC_REGISTER : ZEBRA_FEC_UNREGISTER;
zclient_create_header (s, command, VRF_DEFAULT); zclient_create_header(s, command, VRF_DEFAULT);
flags_pos = stream_get_endp (s); /* save position of 'flags' */ flags_pos = stream_get_endp(s); /* save position of 'flags' */
stream_putw(s, flags); /* initial flags */ stream_putw(s, flags); /* initial flags */
stream_putw(s, PREFIX_FAMILY(p)); stream_putw(s, PREFIX_FAMILY(p));
stream_put_prefix(s, p); stream_put_prefix(s, p);
if (reg) if (reg) {
{ assert(ri);
assert (ri); if (ri->attr->flag & ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID)) {
if (ri->attr->flag & ATTR_FLAG_BIT (BGP_ATTR_PREFIX_SID)) if (ri->attr->label_index != BGP_INVALID_LABEL_INDEX) {
{
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 */
stream_putw_at (s, 0, stream_get_endp (s)); stream_putw_at(s, 0, stream_get_endp(s));
stream_putw_at (s, flags_pos, flags); stream_putw_at(s, flags_pos, flags);
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,52 +217,50 @@ 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)
return -1; return -1;
addpath_id = ntohl(*((uint32_t*) pnt)); addpath_id = ntohl(*((uint32_t *)pnt));
pnt += BGP_ADDPATH_ID_LEN; pnt += BGP_ADDPATH_ID_LEN;
} }
/* Fetch prefix length. */ /* Fetch prefix length. */
prefixlen = *pnt++; prefixlen = *pnt++;
p.family = afi2family (packet->afi); p.family = afi2family(packet->afi);
psize = PSIZE (prefixlen); psize = PSIZE(prefixlen);
/* sanity check against packet data */ /* sanity check against packet data */
if ((pnt + psize) > lim) if ((pnt + psize) > lim) {
{ zlog_err(
zlog_err ("%s [Error] Update packet error / L-U (prefix length %d exceeds packet size %u)", "%s [Error] Update packet error / L-U (prefix length %d exceeds packet size %u)",
peer->host, peer->host, prefixlen, (uint)(lim - pnt));
prefixlen, (uint)(lim-pnt));
return -1; return -1;
} }
/* Fill in the labels */ /* Fill in the labels */
llen = bgp_nlri_get_labels(peer, pnt, psize, label); llen = bgp_nlri_get_labels(peer, pnt, psize, &label);
// zlog_debug("rcvd label [%x/%x/%x], llen=%d\n", label[0], label[1], label[2], llen);
p.prefixlen = prefixlen - BSIZE(llen); p.prefixlen = prefixlen - BSIZE(llen);
/* There needs to be at least one label */ /* There needs to be at least one label */
if (prefixlen < 24) if (prefixlen < 24) {
{ zlog_err(
zlog_err ("%s [Error] Update packet error" "%s [Error] Update packet error"
" (wrong label length %d)", " (wrong label length %d)",
peer->host, prefixlen); peer->host, prefixlen);
bgp_notify_send (peer, BGP_NOTIFY_UPDATE_ERR, bgp_notify_send(peer, BGP_NOTIFY_UPDATE_ERR,
BGP_NOTIFY_UPDATE_INVAL_NETWORK); BGP_NOTIFY_UPDATE_INVAL_NETWORK);
return -1; return -1;
} }
@ -274,65 +270,69 @@ bgp_nlri_parse_label (struct peer *peer, struct attr *attr,
return -1; return -1;
/* Fetch prefix from NLRI packet */ /* Fetch prefix from NLRI packet */
memcpy (&p.u.prefix, pnt + llen, psize - llen); memcpy(&p.u.prefix, pnt + llen, psize - llen);
/* Check address. */ /* Check address. */
if (afi == AFI_IP && safi == SAFI_LABELED_UNICAST) if (afi == AFI_IP && safi == SAFI_LABELED_UNICAST) {
{ if (IN_CLASSD(ntohl(p.u.prefix4.s_addr))) {
if (IN_CLASSD (ntohl (p.u.prefix4.s_addr)))
{
/* From RFC4271 Section 6.3: /* From RFC4271 Section 6.3:
* *
* If a prefix in the NLRI field is semantically incorrect * If a prefix in the NLRI field is semantically
* (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(
peer->host, inet_ntoa (p.u.prefix4)); "%s: IPv4 labeled-unicast NLRI is multicast address %s, ignoring",
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

@ -29,85 +29,83 @@ struct bgp_node;
struct bgp_info; struct bgp_info;
struct peer; struct peer;
extern void bgp_reg_dereg_for_label (struct bgp_node *rn, struct bgp_info *ri, extern void bgp_reg_dereg_for_label(struct bgp_node *rn, struct bgp_info *ri,
int reg); int reg);
extern int bgp_parse_fec_update(void); extern int bgp_parse_fec_update(void);
extern u_char * bgp_adv_label(struct bgp_node *rn, struct bgp_info *ri, extern mpls_label_t bgp_adv_label(struct bgp_node *rn, struct bgp_info *ri,
struct peer *to, afi_t afi, safi_t safi); struct peer *to, afi_t afi, safi_t safi);
extern int bgp_nlri_parse_label (struct peer *peer, struct attr *attr, extern int bgp_nlri_parse_label(struct peer *peer, struct attr *attr,
struct bgp_nlri *packet); struct bgp_nlri *packet);
static inline int static inline int bgp_labeled_safi(safi_t safi)
bgp_labeled_safi (safi_t safi)
{ {
if ((safi == SAFI_LABELED_UNICAST) || (safi == SAFI_MPLS_VPN) || /* NOTE: This API really says a label (tag) MAY be present. Not all EVPN
(safi == SAFI_EVPN)) * routes will have a label.
*/
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,29 +34,26 @@
static struct hash *lcomhash; static struct hash *lcomhash;
/* Allocate a new lcommunities. */ /* Allocate a new lcommunities. */
static struct lcommunity * static struct lcommunity *lcommunity_new(void)
lcommunity_new (void)
{ {
return (struct lcommunity *) XCALLOC (MTYPE_LCOMMUNITY, return (struct lcommunity *)XCALLOC(MTYPE_LCOMMUNITY,
sizeof (struct lcommunity)); sizeof(struct lcommunity));
} }
/* Allocate lcommunities. */ /* Allocate lcommunities. */
void void lcommunity_free(struct lcommunity **lcom)
lcommunity_free (struct lcommunity **lcom)
{ {
if ((*lcom)->val) if ((*lcom)->val)
XFREE (MTYPE_LCOMMUNITY_VAL, (*lcom)->val); XFREE(MTYPE_LCOMMUNITY_VAL, (*lcom)->val);
if ((*lcom)->str) if ((*lcom)->str)
XFREE (MTYPE_LCOMMUNITY_STR, (*lcom)->str); XFREE(MTYPE_LCOMMUNITY_STR, (*lcom)->str);
XFREE (MTYPE_LCOMMUNITY, *lcom); XFREE(MTYPE_LCOMMUNITY, *lcom);
lcom = NULL; lcom = NULL;
} }
static void static void lcommunity_hash_free(struct lcommunity *lcom)
lcommunity_hash_free (struct lcommunity *lcom)
{ {
lcommunity_free (&lcom); lcommunity_free(&lcom);
} }
/* Add a new Large Communities value to Large Communities /* Add a new Large Communities value to Large Communities
@ -64,27 +61,25 @@ lcommunity_hash_free (struct lcommunity *lcom)
structure, we don't add the value. Newly added value is sorted by structure, we don't add the value. Newly added value is sorted by
numerical order. When the value is added to the structure return 1 numerical order. When the value is added to the structure return 1
else return 0. */ else return 0. */
static int static int lcommunity_add_val(struct lcommunity *lcom,
lcommunity_add_val (struct lcommunity *lcom, struct lcommunity_val *lval) struct lcommunity_val *lval)
{ {
u_int8_t *p; u_int8_t *p;
int ret; int ret;
int c; int c;
/* When this is fist value, just add it. */ /* When this is fist value, just add it. */
if (lcom->val == NULL) if (lcom->val == NULL) {
{
lcom->size++; lcom->size++;
lcom->val = XMALLOC (MTYPE_LCOMMUNITY_VAL, lcom_length (lcom)); lcom->val = XMALLOC(MTYPE_LCOMMUNITY_VAL, lcom_length(lcom));
memcpy (lcom->val, lval->val, LCOMMUNITY_SIZE); memcpy(lcom->val, lval->val, LCOMMUNITY_SIZE);
return 1; return 1;
} }
/* If the value already exists in the structure return 0. */ /* If the value already exists in the structure return 0. */
c = 0; c = 0;
for (p = lcom->val; c < lcom->size; p += LCOMMUNITY_SIZE, c++) for (p = lcom->val; c < lcom->size; p += LCOMMUNITY_SIZE, c++) {
{ ret = memcmp(p, lval->val, LCOMMUNITY_SIZE);
ret = memcmp (p, lval->val, LCOMMUNITY_SIZE);
if (ret == 0) if (ret == 0)
return 0; return 0;
if (ret > 0) if (ret > 0)
@ -93,12 +88,13 @@ 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,
(lcom->size - 1 - c) * LCOMMUNITY_SIZE); (lcom->size - 1 - c) * LCOMMUNITY_SIZE);
memcpy (lcom->val + c * LCOMMUNITY_SIZE, lval->val, LCOMMUNITY_SIZE); memcpy(lcom->val + c * LCOMMUNITY_SIZE, lval->val, LCOMMUNITY_SIZE);
return 1; return 1;
} }
@ -106,29 +102,27 @@ 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;
struct lcommunity_val *lval; struct lcommunity_val *lval;
if (! lcom) if (!lcom)
return NULL; return NULL;
new = lcommunity_new (); new = lcommunity_new();
for (i = 0; i < lcom->size; i++) for (i = 0; i < lcom->size; i++) {
{ lval = (struct lcommunity_val *)(lcom->val
lval = (struct lcommunity_val *) (lcom->val + (i * LCOMMUNITY_SIZE)); + (i * LCOMMUNITY_SIZE));
lcommunity_add_val (new, lval); lcommunity_add_val(new, lval);
} }
return new; return new;
} }
/* Parse Large Communites Attribute in BGP packet. */ /* Parse Large Communites Attribute in BGP packet. */
struct lcommunity * struct lcommunity *lcommunity_parse(u_int8_t *pnt, u_short length)
lcommunity_parse (u_int8_t *pnt, u_short length)
{ {
struct lcommunity tmp; struct lcommunity tmp;
struct lcommunity *new; struct lcommunity *new;
@ -144,80 +138,79 @@ lcommunity_parse (u_int8_t *pnt, u_short length)
/* Create a new Large Communities Attribute by uniq and sort each /* Create a new Large Communities Attribute by uniq and sort each
Large Communities value */ Large Communities value */
new = lcommunity_uniq_sort (&tmp); new = lcommunity_uniq_sort(&tmp);
return lcommunity_intern (new); return lcommunity_intern(new);
} }
/* Duplicate the Large Communities Attribute structure. */ /* Duplicate the Large Communities Attribute structure. */
struct lcommunity * struct lcommunity *lcommunity_dup(struct lcommunity *lcom)
lcommunity_dup (struct lcommunity *lcom)
{ {
struct lcommunity *new; struct lcommunity *new;
new = XCALLOC (MTYPE_LCOMMUNITY, sizeof (struct lcommunity)); new = XCALLOC(MTYPE_LCOMMUNITY, sizeof(struct lcommunity));
new->size = lcom->size; new->size = lcom->size;
if (new->size) if (new->size) {
{ new->val = XMALLOC(MTYPE_LCOMMUNITY_VAL,
new->val = XMALLOC (MTYPE_LCOMMUNITY_VAL, lcom->size * LCOMMUNITY_SIZE); lcom->size * LCOMMUNITY_SIZE);
memcpy (new->val, lcom->val, lcom->size * LCOMMUNITY_SIZE); memcpy(new->val, lcom->val, lcom->size * LCOMMUNITY_SIZE);
} } else
else
new->val = NULL; new->val = NULL;
return new; return new;
} }
/* Retrun string representation of communities attribute. */ /* Retrun string representation of communities attribute. */
char * char *lcommunity_str(struct lcommunity *lcom)
lcommunity_str (struct lcommunity *lcom)
{ {
if (! lcom->str) if (!lcom->str)
lcom->str = lcommunity_lcom2str (lcom, LCOMMUNITY_FORMAT_DISPLAY); lcom->str =
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;
assert (lcom->refcnt == 0); assert(lcom->refcnt == 0);
find = (struct lcommunity *) hash_get (lcomhash, lcom, hash_alloc_intern); find = (struct lcommunity *)hash_get(lcomhash, lcom, hash_alloc_intern);
if (find != lcom) if (find != lcom)
lcommunity_free (&lcom); lcommunity_free(&lcom);
find->refcnt++; find->refcnt++;
if (! find->str) if (!find->str)
find->str = lcommunity_lcom2str (find, LCOMMUNITY_FORMAT_DISPLAY); find->str =
lcommunity_lcom2str(find, LCOMMUNITY_FORMAT_DISPLAY);
return find; return find;
} }
/* Unintern Large Communities Attribute. */ /* Unintern Large Communities Attribute. */
void void lcommunity_unintern(struct lcommunity **lcom)
lcommunity_unintern (struct lcommunity **lcom)
{ {
struct lcommunity *ret; struct lcommunity *ret;
@ -225,19 +218,17 @@ 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);
lcommunity_free (lcom); lcommunity_free(lcom);
} }
} }
/* Utility function to make hash key. */ /* Utility function to make hash key. */
unsigned int unsigned int lcommunity_hash_make(void *arg)
lcommunity_hash_make (void *arg)
{ {
const struct lcommunity *lcom = arg; const struct lcommunity *lcom = arg;
int size = lcom->size * LCOMMUNITY_SIZE; int size = lcom->size * LCOMMUNITY_SIZE;
@ -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,55 +255,50 @@ 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);
lcomhash = NULL; lcomhash = NULL;
} }
/* Large Communities token enum. */ /* Large Communities token enum. */
enum lcommunity_token enum lcommunity_token {
{
lcommunity_token_unknown = 0, lcommunity_token_unknown = 0,
lcommunity_token_val, lcommunity_token_val,
}; };
/* Get next Large Communities token from the string. */ /* Get next Large Communities token from the string. */
static const char * static const char *lcommunity_gettoken(const char *str,
lcommunity_gettoken (const char *str, struct lcommunity_val *lval, struct lcommunity_val *lval,
enum lcommunity_token *token) enum lcommunity_token *token)
{ {
const char *p = str; const char *p = str;
/* Skip white space. */ /* Skip white space. */
while (isspace ((int) *p)) while (isspace((int)*p)) {
{
p++; p++;
str++; str++;
} }
@ -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,34 +372,30 @@ 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();
lcommunity_add_val (lcom, &lval); lcommunity_add_val(lcom, &lval);
break; break;
case lcommunity_token_unknown: case lcommunity_token_unknown:
default: default:
if (lcom) if (lcom)
lcommunity_free (&lcom); lcommunity_free(&lcom);
return NULL; return NULL;
} }
} }
return lcom; return lcom;
} }
int int lcommunity_include(struct lcommunity *lcom, u_char *ptr)
lcommunity_include (struct lcommunity *lcom, u_char *ptr)
{ {
int i; int i;
u_char *lcom_ptr; u_char *lcom_ptr;
@ -431,7 +403,7 @@ lcommunity_include (struct lcommunity *lcom, u_char *ptr)
lcom_ptr = lcom->val; lcom_ptr = lcom->val;
for (i = 0; i < lcom->size; i++) { for (i = 0; i < lcom->size; i++) {
lcom_ptr += (i * LCOMMUNITY_SIZE); lcom_ptr += (i * LCOMMUNITY_SIZE);
if (memcmp (ptr, lcom_ptr, LCOMMUNITY_SIZE) == 0) if (memcmp(ptr, lcom_ptr, LCOMMUNITY_SIZE) == 0)
return 1; return 1;
} }
return 0; return 0;
@ -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,29 +424,27 @@ 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;
} }
/* Prepare buffer. */ /* Prepare buffer. */
str_buf = XMALLOC (MTYPE_LCOMMUNITY_STR, LCOMMUNITY_STR_DEFAULT_LEN + 1); str_buf = XMALLOC(MTYPE_LCOMMUNITY_STR, LCOMMUNITY_STR_DEFAULT_LEN + 1);
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. */
if (! first) if (!first)
str_buf[str_pnt++] = ' '; str_buf[str_pnt++] = ' ';
pnt = lcom->val + (i * 12); pnt = lcom->val + (i * 12);
@ -495,7 +464,7 @@ lcommunity_lcom2str (struct lcommunity *lcom, int format)
localdata2 |= (*pnt++ << 8); localdata2 |= (*pnt++ << 8);
localdata2 |= (*pnt++); localdata2 |= (*pnt++);
len = sprintf( str_buf + str_pnt, "%u:%u:%u", globaladmin, len = sprintf(str_buf + str_pnt, "%u:%u:%u", globaladmin,
localdata1, localdata2); localdata1, localdata2);
str_pnt += len; str_pnt += len;
first = 0; first = 0;
@ -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,32 +503,33 @@ 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;
if (! lcom->val) if (!lcom->val)
return; return;
while (i < lcom->size) while (i < lcom->size) {
{ if (memcmp(lcom->val + i * LCOMMUNITY_SIZE, ptr,
if (memcmp (lcom->val + i*LCOMMUNITY_SIZE, ptr, LCOMMUNITY_SIZE) == 0) LCOMMUNITY_SIZE)
{ == 0) {
c = lcom->size -i -1; c = lcom->size - i - 1;
if (c > 0) if (c > 0)
memmove (lcom->val + i*LCOMMUNITY_SIZE, lcom->val + (i + 1)*LCOMMUNITY_SIZE, c * LCOMMUNITY_SIZE); memmove(lcom->val + i * LCOMMUNITY_SIZE,
lcom->val + (i + 1) * LCOMMUNITY_SIZE,
c * LCOMMUNITY_SIZE);
lcom->size--; lcom->size--;
if (lcom->size > 0) if (lcom->size > 0)
lcom->val = XREALLOC (MTYPE_COMMUNITY_VAL, lcom->val, lcom->val =
lcom_length (lcom)); XREALLOC(MTYPE_COMMUNITY_VAL, lcom->val,
else lcom_length(lcom));
{ else {
XFREE (MTYPE_COMMUNITY_VAL, lcom->val); XFREE(MTYPE_COMMUNITY_VAL, lcom->val);
lcom->val = NULL; lcom->val = NULL;
} }
return; return;

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,29 +45,30 @@ 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];
}; };
#define lcom_length(X) ((X)->size * LCOMMUNITY_SIZE) #define lcom_length(X) ((X)->size * LCOMMUNITY_SIZE)
extern void lcommunity_init (void); extern void lcommunity_init(void);
extern void lcommunity_finish (void); extern void lcommunity_finish(void);
extern void lcommunity_free (struct lcommunity **); extern void lcommunity_free(struct lcommunity **);
extern struct lcommunity *lcommunity_parse (u_int8_t *, u_short); extern struct lcommunity *lcommunity_parse(u_int8_t *, u_short);
extern struct lcommunity *lcommunity_dup (struct lcommunity *); extern struct lcommunity *lcommunity_dup(struct lcommunity *);
extern struct lcommunity *lcommunity_merge (struct lcommunity *, struct lcommunity *); extern struct lcommunity *lcommunity_merge(struct lcommunity *,
extern struct lcommunity *lcommunity_uniq_sort (struct lcommunity *); struct lcommunity *);
extern struct lcommunity *lcommunity_intern (struct lcommunity *); extern struct lcommunity *lcommunity_uniq_sort(struct lcommunity *);
extern int lcommunity_cmp (const void *, const void *); extern struct lcommunity *lcommunity_intern(struct lcommunity *);
extern void lcommunity_unintern (struct lcommunity **); extern int lcommunity_cmp(const void *, const void *);
extern unsigned int lcommunity_hash_make (void *); extern void lcommunity_unintern(struct lcommunity **);
extern struct hash *lcommunity_hash (void); extern unsigned int lcommunity_hash_make(void *);
extern struct lcommunity *lcommunity_str2com (const char *); extern struct hash *lcommunity_hash(void);
extern char *lcommunity_lcom2str (struct lcommunity *, int); extern struct lcommunity *lcommunity_str2com(const char *);
extern int lcommunity_match (const struct lcommunity *, const struct lcommunity *); extern char *lcommunity_lcom2str(struct lcommunity *, int);
extern char *lcommunity_str (struct lcommunity *); extern int lcommunity_match(const struct lcommunity *,
extern int lcommunity_include (struct lcommunity *lcom, u_char *ptr); const struct lcommunity *);
extern void lcommunity_del_val (struct lcommunity *lcom, u_char *ptr); extern char *lcommunity_str(struct lcommunity *);
extern int lcommunity_include(struct lcommunity *lcom, u_char *ptr);
extern void lcommunity_del_val(struct lcommunity *lcom, u_char *ptr);
#endif /* _QUAGGA_BGP_LCOMMUNITY_H */ #endif /* _QUAGGA_BGP_LCOMMUNITY_H */

View File

@ -60,27 +60,24 @@
#endif #endif
/* bgpd options, we use GNU getopt library. */ /* bgpd options, we use GNU getopt library. */
static const struct option longopts[] = static const struct option longopts[] = {
{ {"bgp_port", required_argument, NULL, 'p'},
{ "bgp_port", required_argument, NULL, 'p'}, {"listenon", required_argument, NULL, 'l'},
{ "listenon", required_argument, NULL, 'l'}, {"retain", no_argument, NULL, 'r'},
{ "retain", no_argument, NULL, 'r'}, {"no_kernel", no_argument, NULL, 'n'},
{ "no_kernel", no_argument, NULL, 'n'}, {"skip_runas", no_argument, NULL, 'S'},
{ "skip_runas", no_argument, NULL, 'S'}, {"ecmp", required_argument, NULL, 'e'},
{ "ecmp", required_argument, NULL, 'e'}, {0}};
{ 0 }
};
/* signal definitions */ /* signal definitions */
void sighup (void); void sighup(void);
void sigint (void); void sigint(void);
void sigusr1 (void); void sigusr1(void);
static void bgp_exit (int); static void bgp_exit(int);
static void bgp_vrf_terminate (void); static void bgp_vrf_terminate(void);
static struct quagga_signal_t bgp_signals[] = static struct quagga_signal_t bgp_signals[] = {
{
{ {
.signal = SIGHUP, .signal = SIGHUP,
.handler = &sighup, .handler = &sighup,
@ -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,43 +120,39 @@ 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");
/* Terminate all thread. */ /* Terminate all thread. */
bgp_terminate (); bgp_terminate();
bgp_reset (); bgp_reset();
zlog_info ("bgpd restarting!"); zlog_info("bgpd restarting!");
/* Reload config file. */ /* Reload config file. */
vty_read_config (bgpd_di.config_file, config_default); vty_read_config(bgpd_di.config_file, config_default);
/* Try to return to normal operation. */ /* Try to return to normal operation. */
} }
/* SIGINT handler. */ /* SIGINT handler. */
__attribute__((__noreturn__)) void __attribute__((__noreturn__)) void sigint(void)
sigint (void)
{ {
zlog_notice ("Terminating on signal"); zlog_notice("Terminating on signal");
if (! retain_mode) if (!retain_mode) {
{ bgp_terminate();
bgp_terminate ();
if (bgpd_privs.user) /* NULL if skip_runas flag set */ if (bgpd_privs.user) /* NULL if skip_runas flag set */
zprivs_terminate (&bgpd_privs); zprivs_terminate(&bgpd_privs);
} }
bgp_exit (0); bgp_exit(0);
exit (0); exit(0);
} }
/* SIGUSR1 handler. */ /* SIGUSR1 handler. */
void void sigusr1(void)
sigusr1 (void)
{ {
zlog_rotate(); zlog_rotate();
} }
@ -175,129 +164,117 @@ sigusr1 (void)
Zebra route removal and protocol teardown are not meant to be done here. Zebra route removal and protocol teardown are not meant to be done here.
For example, "retain_mode" may be set. For example, "retain_mode" may be set.
*/ */
static __attribute__((__noreturn__)) void static __attribute__((__noreturn__)) void bgp_exit(int status)
bgp_exit (int status)
{ {
struct bgp *bgp; struct bgp *bgp;
struct listnode *node, *nnode; struct listnode *node, *nnode;
/* it only makes sense for this to be called on a clean exit */ /* it only makes sense for this to be called on a clean exit */
assert (status == 0); assert(status == 0);
bfd_gbl_exit(); bfd_gbl_exit();
bgp_close(); bgp_close();
if (retain_mode) if (retain_mode)
if_add_hook (IF_DELETE_HOOK, NULL); if_add_hook(IF_DELETE_HOOK, NULL);
/* reverse bgp_master_init */ /* reverse bgp_master_init */
for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp)) for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp))
bgp_delete (bgp); bgp_delete(bgp);
/* reverse bgp_dump_init */ /* reverse bgp_dump_init */
bgp_dump_finish (); bgp_dump_finish();
/* reverse bgp_route_init */ /* reverse bgp_route_init */
bgp_route_finish (); bgp_route_finish();
/* cleanup route maps */ /* cleanup route maps */
bgp_route_map_terminate(); bgp_route_map_terminate();
/* reverse bgp_attr_init */ /* reverse bgp_attr_init */
bgp_attr_finish (); bgp_attr_finish();
/* reverse access_list_init */ /* reverse access_list_init */
access_list_add_hook (NULL); access_list_add_hook(NULL);
access_list_delete_hook (NULL); access_list_delete_hook(NULL);
access_list_reset (); access_list_reset();
/* reverse bgp_filter_init */ /* reverse bgp_filter_init */
as_list_add_hook (NULL); as_list_add_hook(NULL);
as_list_delete_hook (NULL); as_list_delete_hook(NULL);
bgp_filter_reset (); bgp_filter_reset();
/* reverse prefix_list_init */ /* reverse prefix_list_init */
prefix_list_add_hook (NULL); prefix_list_add_hook(NULL);
prefix_list_delete_hook (NULL); prefix_list_delete_hook(NULL);
prefix_list_reset (); prefix_list_reset();
/* reverse community_list_init */ /* reverse community_list_init */
community_list_terminate (bgp_clist); community_list_terminate(bgp_clist);
bgp_vrf_terminate (); bgp_vrf_terminate();
cmd_terminate (); cmd_terminate();
vty_terminate (); vty_terminate();
#if ENABLE_BGP_VNC #if ENABLE_BGP_VNC
vnc_zebra_destroy(); vnc_zebra_destroy();
#endif #endif
bgp_zebra_destroy(); bgp_zebra_destroy();
if (bgp_nexthop_buf)
stream_free (bgp_nexthop_buf);
if (bgp_ifindices_buf)
stream_free (bgp_ifindices_buf);
if (bgp_label_buf)
stream_free (bgp_label_buf);
/* reverse bgp_master_init */ /* reverse bgp_master_init */
if (bm->master) if (bm->master)
thread_master_free (bm->master); thread_master_free(bm->master);
closezlog (); closezlog();
list_delete (bm->bgp); list_delete(bm->bgp);
memset (bm, 0, sizeof (*bm)); memset(bm, 0, sizeof(*bm));
if (bgp_debug_count()) if (bgp_debug_count())
log_memstats_stderr ("bgpd"); log_memstats_stderr("bgpd");
exit (status); exit(status);
} }
static int static int bgp_vrf_new(struct vrf *vrf)
bgp_vrf_new (struct vrf *vrf)
{ {
if (BGP_DEBUG (zebra, ZEBRA)) if (BGP_DEBUG(zebra, ZEBRA))
zlog_debug ("VRF Created: %s(%d)", vrf->name, vrf->vrf_id); zlog_debug("VRF Created: %s(%d)", vrf->name, vrf->vrf_id);
return 0; return 0;
} }
static int static int bgp_vrf_delete(struct vrf *vrf)
bgp_vrf_delete (struct vrf *vrf)
{ {
if (BGP_DEBUG (zebra, ZEBRA)) if (BGP_DEBUG(zebra, ZEBRA))
zlog_debug ("VRF Deletion: %s(%d)", vrf->name, vrf->vrf_id); zlog_debug("VRF Deletion: %s(%d)", vrf->name, vrf->vrf_id);
return 0; return 0;
} }
static int static int bgp_vrf_enable(struct vrf *vrf)
bgp_vrf_enable (struct vrf *vrf)
{ {
struct bgp *bgp; struct bgp *bgp;
vrf_id_t old_vrf_id; vrf_id_t old_vrf_id;
if (BGP_DEBUG (zebra, ZEBRA)) if (BGP_DEBUG(zebra, ZEBRA))
zlog_debug("VRF enable add %s id %d", vrf->name, vrf->vrf_id); zlog_debug("VRF enable add %s id %d", vrf->name, vrf->vrf_id);
bgp = bgp_lookup_by_name (vrf->name); bgp = bgp_lookup_by_name(vrf->name);
if (bgp) if (bgp) {
{
old_vrf_id = bgp->vrf_id; old_vrf_id = bgp->vrf_id;
/* We have instance configured, link to VRF and make it "up". */ /* We have instance configured, link to VRF and make it "up". */
bgp_vrf_link (bgp, vrf); bgp_vrf_link(bgp, vrf);
/* Update any redistribute vrf bitmaps if the vrf_id changed */ /* Update any redistribute vrf bitmaps if the vrf_id changed */
if (old_vrf_id != bgp->vrf_id) if (old_vrf_id != bgp->vrf_id)
bgp_update_redist_vrf_bitmaps(bgp, old_vrf_id); bgp_update_redist_vrf_bitmaps(bgp, old_vrf_id);
bgp_instance_up (bgp); bgp_instance_up(bgp);
} }
return 0; return 0;
} }
static int static int bgp_vrf_disable(struct vrf *vrf)
bgp_vrf_disable (struct vrf *vrf)
{ {
struct bgp *bgp; struct bgp *bgp;
vrf_id_t old_vrf_id; vrf_id_t old_vrf_id;
@ -305,55 +282,46 @@ bgp_vrf_disable (struct vrf *vrf)
if (vrf->vrf_id == VRF_DEFAULT) if (vrf->vrf_id == VRF_DEFAULT)
return 0; return 0;
if (BGP_DEBUG (zebra, ZEBRA)) if (BGP_DEBUG(zebra, ZEBRA))
zlog_debug("VRF disable %s id %d", vrf->name, vrf->vrf_id); zlog_debug("VRF disable %s id %d", vrf->name, vrf->vrf_id);
bgp = bgp_lookup_by_name (vrf->name); bgp = bgp_lookup_by_name(vrf->name);
if (bgp) if (bgp) {
{
old_vrf_id = bgp->vrf_id; old_vrf_id = bgp->vrf_id;
/* We have instance configured, unlink from VRF and make it "down". */ /* We have instance configured, unlink from VRF and make it
bgp_vrf_unlink (bgp, vrf); * "down". */
bgp_vrf_unlink(bgp, vrf);
/* Update any redistribute vrf bitmaps if the vrf_id changed */ /* Update any redistribute vrf bitmaps if the vrf_id changed */
if (old_vrf_id != bgp->vrf_id) if (old_vrf_id != bgp->vrf_id)
bgp_update_redist_vrf_bitmaps(bgp, old_vrf_id); bgp_update_redist_vrf_bitmaps(bgp, old_vrf_id);
bgp_instance_down (bgp); bgp_instance_down(bgp);
} }
/* Note: This is a callback, the VRF will be deleted by the caller. */ /* Note: This is a callback, the VRF will be deleted by the caller. */
return 0; return 0;
} }
static void static void bgp_vrf_init(void)
bgp_vrf_init (void)
{ {
vrf_init (bgp_vrf_new, vrf_init(bgp_vrf_new, bgp_vrf_enable, bgp_vrf_disable, bgp_vrf_delete);
bgp_vrf_enable,
bgp_vrf_disable,
bgp_vrf_delete);
} }
static void static void bgp_vrf_terminate(void)
bgp_vrf_terminate (void)
{ {
vrf_terminate (); vrf_terminate();
} }
FRR_DAEMON_INFO(bgpd, BGP, FRR_DAEMON_INFO(bgpd, BGP, .vty_port = BGP_VTY_PORT,
.vty_port = BGP_VTY_PORT,
.proghelp = "Implementation of the BGP routing protocol.", .proghelp = "Implementation of the BGP routing protocol.",
.signals = bgp_signals, .signals = bgp_signals, .n_signals = array_size(bgp_signals),
.n_signals = array_size(bgp_signals),
.privs = &bgpd_privs, .privs = &bgpd_privs, )
)
/* Main routine of bgpd. Treatment of argument and start bgp finite /* Main routine of bgpd. Treatment of argument and start bgp finite
state machine is handled at here. */ state machine is handled at here. */
int int main(int argc, char **argv)
main (int argc, char **argv)
{ {
int opt; int opt;
int tmp_port; int tmp_port;
@ -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,29 +342,29 @@ 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':
tmp_port = atoi (optarg); tmp_port = atoi(optarg);
if (tmp_port <= 0 || tmp_port > 0xffff) if (tmp_port <= 0 || tmp_port > 0xffff)
bgp_port = BGP_PORT_DEFAULT; bgp_port = BGP_PORT_DEFAULT;
else else
bgp_port = tmp_port; bgp_port = tmp_port;
break; break;
case 'e': case 'e':
multipath_num = atoi (optarg); multipath_num = atoi(optarg);
if (multipath_num > MULTIPATH_NUM || 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;
@ -412,32 +382,31 @@ main (int argc, char **argv)
skip_runas = 1; skip_runas = 1;
break; break;
default: default:
frr_help_exit (1); frr_help_exit(1);
break; break;
} }
} }
if (skip_runas) if (skip_runas)
memset (&bgpd_privs, 0, sizeof (bgpd_privs)); memset(&bgpd_privs, 0, sizeof(bgpd_privs));
/* BGP master init. */ /* BGP master init. */
bgp_master_init (frr_init ()); bgp_master_init(frr_init());
bm->port = bgp_port; bm->port = bgp_port;
bm->address = bgp_address; bm->address = bgp_address;
if (no_fib_flag) if (no_fib_flag)
bgp_option_set (BGP_OPT_NO_FIB); bgp_option_set(BGP_OPT_NO_FIB);
/* Initializations. */ /* Initializations. */
bgp_vrf_init (); bgp_vrf_init();
/* BGP related initialization. */ /* BGP related initialization. */
bgp_init (); bgp_init();
snprintf (bgpd_di.startinfo, sizeof (bgpd_di.startinfo), ", bgp@%s:%d", snprintf(bgpd_di.startinfo, sizeof(bgpd_di.startinfo), ", bgp@%s:%d",
(bm->address ? bm->address : "<all>"), (bm->address ? bm->address : "<all>"), bm->port);
bm->port);
frr_config_fork (); frr_config_fork();
frr_run (bm->master); frr_run(bm->master);
/* Not reached. */ /* Not reached. */
return (0); return (0);

View File

@ -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; compare = IPV4_ADDR_CMP(&bi1->attr->nexthop, &bi2->attr->nexthop);
ae2 = bi2->attr->extra; if (!compare) {
if (bi1->attr->mp_nexthop_len == bi2->attr->mp_nexthop_len) {
compare = IPV4_ADDR_CMP (&bi1->attr->nexthop, &bi2->attr->nexthop); switch (bi1->attr->mp_nexthop_len) {
if (!compare && ae1 && ae2)
{
if (ae1->mp_nexthop_len == ae2->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;
@ -181,10 +173,9 @@ bgp_info_mpath_cmp (void *val1, void *val2)
bi1 = val1; bi1 = val1;
bi2 = val2; bi2 = 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,11 +196,10 @@ 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));
mp_list->cmp = bgp_info_mpath_cmp; mp_list->cmp = bgp_info_mpath_cmp;
} }
@ -217,11 +208,10 @@ 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,11 +219,10 @@ 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,14 +243,12 @@ 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);
*mpath = NULL; *mpath = NULL;
} }
} }
@ -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,13 +278,13 @@ 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;
prev = bgp_info_mpath_get (prev_info); prev = bgp_info_mpath_get(prev_info);
mpath = bgp_info_mpath_get (binfo); mpath = bgp_info_mpath_get(binfo);
if (!prev || !mpath) if (!prev || !mpath)
return; return;
@ -309,7 +294,7 @@ bgp_info_mpath_enqueue (struct bgp_info *prev_info, struct bgp_info *binfo)
prev->mp_next->mp_prev = mpath; prev->mp_next->mp_prev = mpath;
prev->mp_next = mpath; prev->mp_next = mpath;
SET_FLAG (binfo->flags, BGP_INFO_MULTIPATH); SET_FLAG(binfo->flags, BGP_INFO_MULTIPATH);
} }
/* /*
@ -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)
@ -328,7 +312,7 @@ bgp_info_mpath_dequeue (struct bgp_info *binfo)
if (mpath->mp_next) if (mpath->mp_next)
mpath->mp_next->mp_prev = mpath->mp_prev; mpath->mp_next->mp_prev = mpath->mp_prev;
mpath->mp_next = mpath->mp_prev = NULL; mpath->mp_next = mpath->mp_prev = NULL;
UNSET_FLAG (binfo->flags, BGP_INFO_MULTIPATH); UNSET_FLAG(binfo->flags, BGP_INFO_MULTIPATH);
} }
/* /*
@ -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,10 +332,9 @@ 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,13 +354,12 @@ 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)
return; return;
mpath = bgp_info_mpath_get (binfo); mpath = bgp_info_mpath_get(binfo);
if (!mpath) if (!mpath)
return; return;
mpath->mp_count = count; mpath->mp_count = count;
@ -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,13 +383,12 @@ 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)
return; return;
mpath = bgp_info_mpath_get (binfo); mpath = bgp_info_mpath_get(binfo);
if (!mpath) if (!mpath)
return; return;
mpath->mp_attr = attr; mpath->mp_attr = attr;
@ -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)
{ {
@ -440,33 +417,33 @@ bgp_info_mpath_update (struct bgp_node *rn, struct bgp_info *new_best,
cur_mpath = NULL; cur_mpath = NULL;
old_mpath_count = 0; old_mpath_count = 0;
prev_mpath = new_best; prev_mpath = new_best;
mp_node = listhead (mp_list); mp_node = listhead(mp_list);
debug = bgp_debug_bestpath(&rn->p); debug = bgp_debug_bestpath(&rn->p);
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); bgp_info_mpath_dequeue(old_best);
bgp_info_mpath_dequeue (old_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);
/* /*
* We perform an ordered walk through both lists in parallel. * We perform an ordered walk through both lists in parallel.
@ -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;
/* /*
@ -491,46 +467,49 @@ bgp_info_mpath_update (struct bgp_node *rn, struct bgp_info *new_best,
if (!cur_mpath && (mpath_count >= maxpaths)) if (!cur_mpath && (mpath_count >= maxpaths))
break; break;
mp_next_node = mp_node ? listnextnode (mp_node) : NULL; mp_next_node = mp_node ? listnextnode(mp_node) : NULL;
next_mpath = cur_mpath ? bgp_info_mpath_next (cur_mpath) : NULL; next_mpath = cur_mpath ? bgp_info_mpath_next(cur_mpath) : NULL;
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,62 +518,73 @@ 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,
nh_buf[0], sizeof (nh_buf[0])), &cur_mpath->attr->nexthop,
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);
bgp_info_mpath_enqueue (prev_mpath, new_mpath); bgp_info_mpath_enqueue(prev_mpath, new_mpath);
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,15 +592,17 @@ 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
SET_FLAG (new_best->flags, BGP_INFO_MULTIPATH_CHG); || (bgp_info_mpath_count(new_best) != old_mpath_count))
SET_FLAG(new_best->flags, BGP_INFO_MULTIPATH_CHG);
} }
} }
@ -620,23 +612,22 @@ 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);
} }
bgp_info_mpath_count_set (dmed_best, 0); bgp_info_mpath_count_set(dmed_best, 0);
UNSET_FLAG (dmed_best->flags, BGP_INFO_MULTIPATH_CHG); UNSET_FLAG(dmed_best->flags, BGP_INFO_MULTIPATH_CHG);
assert (bgp_info_mpath_first (dmed_best) == 0); assert(bgp_info_mpath_first(dmed_best) == 0);
} }
/* /*
@ -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,123 +653,113 @@ 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);
} }
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_info_mpath_attr_set(new_best, NULL);
bgp_attr_unintern (&new_attr); SET_FLAG(new_best->flags, BGP_INFO_ATTR_CHANGED);
bgp_info_mpath_attr_set (new_best, NULL);
SET_FLAG (new_best->flags, BGP_INFO_ATTR_CHANGED);
} }
return; return;
} }
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_free (commerge); community_uniq_sort(commerge);
} community_free(commerge);
else } else
community = community_dup (mpinfo->attr->community); community = community_dup(
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) lcomm = lcommunity_uniq_sort(lcommerge);
{ lcommunity_free(&lcommerge);
lcommerge = lcommunity_merge (lcomm, ae->lcommunity); } else
lcomm = lcommunity_uniq_sort (lcommerge); lcomm = lcommunity_dup(
lcommunity_free (&lcommerge); mpinfo->attr->lcommunity);
}
else
lcomm = lcommunity_dup (ae->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); attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES);
ae->ecommunity = ecomm;
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
} bgp_attr_unintern(&new_attr);
else
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;
@ -44,34 +43,34 @@ struct bgp_info_mpath
}; };
/* Functions to support maximum-paths configuration */ /* Functions to support maximum-paths configuration */
extern int bgp_maximum_paths_set (struct bgp *, afi_t, safi_t, int, u_int16_t, extern int bgp_maximum_paths_set(struct bgp *, afi_t, safi_t, int, u_int16_t,
u_int16_t); u_int16_t);
extern int bgp_maximum_paths_unset (struct bgp *, afi_t, safi_t, int); extern int bgp_maximum_paths_unset(struct bgp *, afi_t, safi_t, int);
/* Functions used by bgp_best_selection to record current /* Functions used by bgp_best_selection to record current
* multipath selections * multipath selections
*/ */
extern int bgp_info_nexthop_cmp (struct bgp_info *bi1, struct bgp_info *bi2); extern int bgp_info_nexthop_cmp(struct bgp_info *bi1, struct bgp_info *bi2);
extern void bgp_mp_list_init (struct list *); extern void bgp_mp_list_init(struct list *);
extern void bgp_mp_list_clear (struct list *); extern void bgp_mp_list_clear(struct list *);
extern void bgp_mp_list_add (struct list *, struct bgp_info *); extern void bgp_mp_list_add(struct list *, struct bgp_info *);
extern void bgp_mp_dmed_deselect (struct bgp_info *); extern void bgp_mp_dmed_deselect(struct bgp_info *);
extern void bgp_info_mpath_update (struct bgp_node *, struct bgp_info *, extern void bgp_info_mpath_update(struct bgp_node *, struct bgp_info *,
struct bgp_info *, struct list *, struct bgp_info *, struct list *,
struct bgp_maxpaths_cfg *); struct bgp_maxpaths_cfg *);
extern void bgp_info_mpath_aggregate_update (struct bgp_info *, extern void bgp_info_mpath_aggregate_update(struct bgp_info *,
struct bgp_info *); struct bgp_info *);
/* Unlink and free multipath information associated with a bgp_info */ /* Unlink and free multipath information associated with a bgp_info */
extern void bgp_info_mpath_dequeue (struct bgp_info *); extern void bgp_info_mpath_dequeue(struct bgp_info *);
extern void bgp_info_mpath_free (struct bgp_info_mpath **); extern void bgp_info_mpath_free(struct bgp_info_mpath **);
/* Walk list of multipaths associated with a best path */ /* Walk list of multipaths associated with a best path */
extern struct bgp_info *bgp_info_mpath_first (struct bgp_info *); extern struct bgp_info *bgp_info_mpath_first(struct bgp_info *);
extern struct bgp_info *bgp_info_mpath_next (struct bgp_info *); extern struct bgp_info *bgp_info_mpath_next(struct bgp_info *);
/* Accessors for multipath information */ /* Accessors for multipath information */
extern u_int32_t bgp_info_mpath_count (struct bgp_info *); extern u_int32_t bgp_info_mpath_count(struct bgp_info *);
extern struct attr *bgp_info_mpath_attr (struct bgp_info *); extern struct attr *bgp_info_mpath_attr(struct bgp_info *);
#endif /* _QUAGGA_BGP_MPATH_H */ #endif /* _QUAGGA_BGP_MPATH_H */

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,7 @@
/* MPLS-VPN /* MPLS-VPN
* Copyright (C) 2000 Kunihiro Ishiguro <kunihiro@zebra.org> * Copyright (C) 2000 Kunihiro Ishiguro <kunihiro@zebra.org>
* *
* This file is part of GNU Zebra. * This file is part of GxNU Zebra.
* *
* GNU Zebra is free software; you can redistribute it and/or modify it * GNU Zebra is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the * under the terms of the GNU General Public License as published by the
@ -22,18 +22,10 @@
#define _QUAGGA_BGP_MPLSVPN_H #define _QUAGGA_BGP_MPLSVPN_H
#include "bgpd/bgp_route.h" #include "bgpd/bgp_route.h"
#include "bgpd/bgp_rd.h"
#define RD_TYPE_AS 0
#define RD_TYPE_IP 1
#define RD_TYPE_AS4 2
#if ENABLE_BGP_VNC
#define RD_TYPE_VNC_ETH 0xff00 /* VNC L2VPN */
#endif
#define RD_ADDRSTRLEN 28
#ifdef MPLS_LABEL_MAX #ifdef MPLS_LABEL_MAX
# undef MPLS_LABEL_MAX #undef MPLS_LABEL_MAX
#endif #endif
typedef enum { typedef enum {
@ -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 extern void bgp_mplsvpn_init(void);
{ extern int bgp_nlri_parse_vpn(struct peer *, struct attr *, struct bgp_nlri *);
u_int16_t type; extern u_int32_t decode_label(mpls_label_t *);
as_t as; extern void encode_label(mpls_label_t, mpls_label_t *);
u_int32_t val;
};
struct rd_ip extern int argv_find_and_parse_vpnvx(struct cmd_token **argv, int argc,
{ int *index, afi_t *afi);
u_int16_t type; extern int bgp_show_mpls_vpn(struct vty *vty, afi_t afi, struct prefix_rd *prd,
struct in_addr ip; enum bgp_show_type type, void *output_arg,
u_int16_t val; int tags, u_char use_json);
};
#if ENABLE_BGP_VNC
struct rd_vnc_eth
{
u_int16_t type;
uint8_t local_nve_id;
struct ethaddr macaddr;
};
#endif
extern u_int16_t decode_rd_type (u_char *);
extern void encode_rd_type (u_int16_t, u_char *);
extern void bgp_mplsvpn_init (void);
extern int bgp_nlri_parse_vpn (struct peer *, struct attr *, struct bgp_nlri *);
extern u_int32_t decode_label (u_char *);
extern void encode_label(u_int32_t, u_char *);
extern void decode_rd_as (u_char *, struct rd_as *);
extern void decode_rd_as4 (u_char *, struct rd_as *);
extern void decode_rd_ip (u_char *, struct rd_ip *);
#if ENABLE_BGP_VNC
extern void
decode_rd_vnc_eth (u_char *pnt, struct rd_vnc_eth *rd_vnc_eth);
#endif
extern int str2prefix_rd (const char *, struct prefix_rd *);
extern char *prefix_rd2str (struct prefix_rd *, char *, size_t);
extern int
argv_find_and_parse_vpnvx(struct cmd_token **argv, int argc, int *index, afi_t *afi);
extern int bgp_show_mpls_vpn (struct vty *vty, afi_t afi, struct prefix_rd *prd,
enum bgp_show_type type, void *output_arg, int tags, u_char use_json);
#endif /* _QUAGGA_BGP_MPLSVPN_H */ #endif /* _QUAGGA_BGP_MPLSVPN_H */

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;
@ -67,130 +66,124 @@ bgp_md5_set_socket (int socket, union sockunion *su, const char *password)
union sockunion su2; union sockunion su2;
#endif /* HAVE_TCP_MD5SIG */ #endif /* HAVE_TCP_MD5SIG */
assert (socket >= 0); assert(socket >= 0);
#if HAVE_DECL_TCP_MD5SIG #if HAVE_DECL_TCP_MD5SIG
/* Ensure there is no extraneous port information. */ /* Ensure there is no extraneous port information. */
memcpy (&su2, su, sizeof (union sockunion)); memcpy(&su2, su, sizeof(union sockunion));
if (su2.sa.sa_family == AF_INET) if (su2.sa.sa_family == AF_INET)
su2.sin.sin_port = 0; su2.sin.sin_port = 0;
else else
su2.sin6.sin6_port = 0; su2.sin6.sin6_port = 0;
ret = sockopt_tcp_signature (socket, &su2, password); ret = sockopt_tcp_signature(socket, &su2, password);
en = errno; en = errno;
#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;
} }
ret = bgp_md5_set_socket (socket, su, password); ret = bgp_md5_set_socket(socket, su, password);
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__);
#endif /* HAVE_TCP_MD5SIG */ #endif /* HAVE_TCP_MD5SIG */
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;
} }
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__);
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(
{ "%s: Can't set TxTTL on peer (rtrid %s) socket, err = %d",
zlog_err ("%s: Can't set TxTTL on peer (rtrid %s) socket, err = %d", __func__, inet_ntop(AF_INET, &peer->remote_id,
__func__, buf, sizeof(buf)),
inet_ntop (AF_INET, &peer->remote_id, 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,17 +199,17 @@ 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) */
*bgp_inst = bgp_get_default (); *bgp_inst = bgp_get_default();
return !*bgp_inst; return !*bgp_inst;
#else #else
@ -229,25 +222,22 @@ 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);
return -1; return -1;
#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;
@ -288,13 +275,12 @@ bgp_accept (struct thread *thread)
char buf[SU_ADDRSTRLEN]; char buf[SU_ADDRSTRLEN];
struct bgp *bgp = NULL; struct bgp *bgp = NULL;
sockunion_init (&su); sockunion_init(&su);
/* 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;
} }
listener->thread = NULL; listener->thread = NULL;
@ -302,65 +288,63 @@ bgp_accept (struct thread *thread)
&listener->thread); &listener->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(
inet_sutop (&su, buf)); "[Event] Could not get instance for incoming conn from %s",
close (bgp_sock); inet_sutop(&su, buf));
close(bgp_sock);
return -1; return -1;
} }
/* Set socket send buffer size */ /* Set socket send buffer size */
setsockopt_so_sendbuf (bgp_sock, BGP_SOCKET_SNDBUF_SIZE); setsockopt_so_sendbuf(bgp_sock, BGP_SOCKET_SNDBUF_SIZE);
/* 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);
return 0; return 0;
} }
} }
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));
} }
close (bgp_sock); close(bgp_sock);
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(
inet_sutop (&su, buf)); "[Event] connection from %s rejected due to admin shutdown",
close (bgp_sock); inet_sutop(&su, buf));
close(bgp_sock);
return -1; return -1;
} }
@ -370,53 +354,55 @@ 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;
} }
if (bgp_debug_neighbor_events(peer1)) if (bgp_debug_neighbor_events(peer1))
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,
peer1->as, peer1->as_type, 0, 0, NULL); peer1->as, peer1->as_type, 0, 0, NULL);
peer->su = su; peer->su = su;
hash_release(peer->bgp->peerhash, peer); hash_release(peer->bgp->peerhash, peer);
hash_get(peer->bgp->peerhash, peer, hash_alloc_intern); hash_get(peer->bgp->peerhash, peer, hash_alloc_intern);
peer_xfer_config(peer, peer1); peer_xfer_config(peer, peer1);
UNSET_FLAG (peer->flags, PEER_FLAG_CONFIG_NODE); UNSET_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE);
peer->doppelganger = peer1; peer->doppelganger = peer1;
peer1->doppelganger = peer; peer1->doppelganger = peer;
@ -425,32 +411,31 @@ bgp_accept (struct thread *thread)
bgp_fsm_change_status(peer, Active); bgp_fsm_change_status(peer, Active);
BGP_TIMER_OFF(peer->t_start); /* created in peer_create() */ BGP_TIMER_OFF(peer->t_start); /* created in peer_create() */
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;
SET_FLAG (peer1->sflags, PEER_STATUS_NSF_WAIT); SET_FLAG(peer1->sflags, PEER_STATUS_NSF_WAIT);
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);
} }
return 0; return 0;
} }
/* 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;
@ -458,11 +443,11 @@ bgp_bind (struct peer *peer)
char *name = NULL; char *name = NULL;
/* If not bound to an interface or part of a VRF, we don't care. */ /* If not bound to an interface or part of a VRF, we don't care. */
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;
@ -479,30 +465,29 @@ bgp_bind (struct peer *peer)
return 0; return 0;
if (bgp_debug_neighbor_events(peer)) if (bgp_debug_neighbor_events(peer))
zlog_debug ("%s Binding to interface %s", peer->host, name); zlog_debug("%s Binding to interface %s", peer->host, name);
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",
zlog_debug ("bind to interface %s failed, errno=%d", name, myerrno); 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;
@ -510,55 +495,52 @@ bgp_update_address (struct interface *ifp, const union sockunion *dst,
struct listnode *node; struct listnode *node;
int common; int common;
sockunion2hostprefix (dst, &d); sockunion2hostprefix(dst, &d);
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);
} }
} }
if (!sel) if (!sel)
return 1; return 1;
prefix2sockunion (sel, addr); prefix2sockunion(sel, addr);
return 0; return 0;
} }
/* 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;
int ret = 0; int ret = 0;
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;
if (bgp_update_address (ifp, &peer->su, &addr)) if (bgp_update_address(ifp, &peer->su, &addr))
return -1; return -1;
ret = sockunion_bind (peer->fd, &addr, 0, &addr); ret = sockunion_bind(peer->fd, &addr, 0, &addr);
} }
/* 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,95 +548,94 @@ 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;
} }
/* Make socket for the peer. */ /* Make socket for the peer. */
peer->fd = sockunion_socket (&peer->su); peer->fd = sockunion_socket(&peer->su);
if (peer->fd < 0) if (peer->fd < 0)
return -1; return -1;
set_nonblocking (peer->fd); set_nonblocking(peer->fd);
/* Set socket send buffer size */ /* Set socket send buffer size */
setsockopt_so_sendbuf (peer->fd, BGP_SOCKET_SNDBUF_SIZE); setsockopt_so_sendbuf(peer->fd, BGP_SOCKET_SNDBUF_SIZE);
if (bgp_set_socket_ttl (peer, peer->fd) < 0) if (bgp_set_socket_ttl(peer, peer->fd) < 0)
return -1; return -1;
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))
zlog_err ("%s: could not raise privs", __func__); zlog_err("%s: could not raise privs", __func__);
if (sockunion_family (&peer->su) == AF_INET) if (sockunion_family(&peer->su) == AF_INET)
setsockopt_ipv4_tos (peer->fd, IPTOS_PREC_INTERNETCONTROL); setsockopt_ipv4_tos(peer->fd, IPTOS_PREC_INTERNETCONTROL);
else if (sockunion_family (&peer->su) == AF_INET6) else if (sockunion_family(&peer->su) == AF_INET6)
setsockopt_ipv6_tclass (peer->fd, IPTOS_PREC_INTERNETCONTROL); setsockopt_ipv6_tclass(peer->fd, IPTOS_PREC_INTERNETCONTROL);
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__);
#endif #endif
if (peer->password) if (peer->password)
bgp_md5_set_connect (peer->fd, &peer->su, peer->password); bgp_md5_set_connect(peer->fd, &peer->su, peer->password);
/* Bind socket. */ /* Bind socket. */
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)
peer->su_remote = sockunion_getpeername (peer->fd); return -1;
if (!peer->su_remote) return -1; peer->su_remote = sockunion_getpeername(peer->fd);
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(
zlog_err ("%s: nexthop_set failed, resetting connection - intf %p", "%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,58 +645,55 @@ 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;
sockopt_reuseaddr (sock); sockopt_reuseaddr(sock);
sockopt_reuseport (sock); sockopt_reuseport(sock);
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__);
#ifdef IPTOS_PREC_INTERNETCONTROL #ifdef IPTOS_PREC_INTERNETCONTROL
if (sa->sa_family == AF_INET) if (sa->sa_family == AF_INET)
setsockopt_ipv4_tos (sock, IPTOS_PREC_INTERNETCONTROL); setsockopt_ipv4_tos(sock, IPTOS_PREC_INTERNETCONTROL);
else if (sa->sa_family == AF_INET6) else if (sa->sa_family == AF_INET6)
setsockopt_ipv6_tclass (sock, IPTOS_PREC_INTERNETCONTROL); setsockopt_ipv6_tclass(sock, IPTOS_PREC_INTERNETCONTROL);
#endif #endif
sockopt_v6only (sa->sa_family, sock); sockopt_v6only(sa->sa_family, sock);
ret = bind (sock, sa, salen); ret = bind(sock, sa, salen);
en = errno; en = errno;
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;
} }
listener = XMALLOC (MTYPE_BGP_LISTENER, sizeof(*listener)); listener = XMALLOC(MTYPE_BGP_LISTENER, sizeof(*listener));
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,
listnode_add (bm->listen_sockets, listener); &listener->thread);
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;
@ -727,52 +705,49 @@ bgp_socket (unsigned short port, const char *address)
int ret, count; int ret, count;
char port_str[BUFSIZ]; char port_str[BUFSIZ];
snprintf (port_str, sizeof(port_str), "%d", port); snprintf(port_str, sizeof(port_str), "%d", port);
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
sockopt_ttl (ainfo->ai_family, sock, MAXTTL); * ttl=255 */
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);
if (ret == 0) if (ret == 0)
++count; ++count;
else else
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;
} }
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,11 +755,10 @@ 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); XFREE(MTYPE_BGP_LISTENER, listener);
XFREE (MTYPE_BGP_LISTENER, listener);
} }
} }

View File

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

View File

@ -47,88 +47,78 @@
#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);
} }
} }
/* BGP own address structure */ /* BGP own address structure */
struct bgp_addr struct bgp_addr {
{
struct in_addr addr; struct in_addr addr;
int refcnt; int refcnt;
}; };
static void * static void *bgp_address_hash_alloc(void *p)
bgp_address_hash_alloc (void *p)
{ {
const struct in_addr *val = (const struct in_addr *)p; const struct in_addr *val = (const struct in_addr *)p;
struct bgp_addr *addr; struct bgp_addr *addr;
addr = XMALLOC (MTYPE_BGP_ADDR, sizeof (struct bgp_addr)); addr = XMALLOC(MTYPE_BGP_ADDR, sizeof(struct bgp_addr));
addr->refcnt = 0; addr->refcnt = 0;
addr->addr.s_addr = val->s_addr; addr->addr.s_addr = val->s_addr;
return addr; return addr;
} }
static void static void bgp_address_hash_free(void *addr)
bgp_address_hash_free (void *addr)
{ {
XFREE (MTYPE_BGP_ADDR, addr); XFREE(MTYPE_BGP_ADDR, addr);
} }
static unsigned int static unsigned int bgp_address_hash_key_make(void *p)
bgp_address_hash_key_make (void *p)
{ {
const struct bgp_addr *addr = p; const struct bgp_addr *addr = p;
return jhash_1word(addr->addr.s_addr, 0); return jhash_1word(addr->addr.s_addr, 0);
} }
static int static int bgp_address_hash_cmp(const void *p1, const void *p2)
bgp_address_hash_cmp (const void *p1, const void *p2)
{ {
const struct bgp_addr *addr1 = p1; const struct bgp_addr *addr1 = p1;
const struct bgp_addr *addr2 = p2; const struct bgp_addr *addr2 = p2;
@ -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,51 +141,46 @@ 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;
tmp.addr = p->u.prefix4; tmp.addr = p->u.prefix4;
addr = hash_get (bgp->address_hash, &tmp, bgp_address_hash_alloc); addr = hash_get(bgp->address_hash, &tmp, bgp_address_hash_alloc);
if (!addr) if (!addr)
return; return;
addr->refcnt++; addr->refcnt++;
} }
static void static void bgp_address_del(struct bgp *bgp, struct prefix *p)
bgp_address_del (struct bgp *bgp, struct prefix *p)
{ {
struct bgp_addr tmp; struct bgp_addr tmp;
struct bgp_addr *addr; struct bgp_addr *addr;
tmp.addr = p->u.prefix4; tmp.addr = p->u.prefix4;
addr = hash_lookup (bgp->address_hash, &tmp); addr = hash_lookup(bgp->address_hash, &tmp);
/* may have been deleted earlier by bgp_interface_down() */ /* may have been deleted earlier by bgp_interface_down() */
if (addr == NULL) if (addr == NULL)
return; return;
addr->refcnt--; addr->refcnt--;
if (addr->refcnt == 0) if (addr->refcnt == 0) {
{ hash_release(bgp->address_hash, addr);
hash_release (bgp->address_hash, addr); XFREE(MTYPE_BGP_ADDR, addr);
XFREE (MTYPE_BGP_ADDR, addr);
} }
} }
struct bgp_connected_ref struct bgp_connected_ref {
{
unsigned int refcnt; unsigned int refcnt;
}; };
void void bgp_connected_add(struct bgp *bgp, struct connected *ifc)
bgp_connected_add (struct bgp *bgp, struct connected *ifc)
{ {
struct prefix p; struct prefix p;
struct prefix *addr; struct prefix *addr;
@ -209,67 +192,61 @@ 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))
return; return;
bgp_address_add (bgp, addr); bgp_address_add(bgp, addr);
rn = bgp_node_get (bgp->connected_table[AFI_IP], (struct prefix *) &p); rn = bgp_node_get(bgp->connected_table[AFI_IP],
if (rn->info) (struct prefix *)&p);
{ if (rn->info) {
bc = rn->info; bc = rn->info;
bc->refcnt++; bc->refcnt++;
} } else {
else bc = XCALLOC(MTYPE_BGP_CONN,
{ sizeof(struct bgp_connected_ref));
bc = XCALLOC (MTYPE_BGP_CONN, sizeof (struct bgp_connected_ref));
bc->refcnt = 1; bc->refcnt = 1;
rn->info = bc; rn->info = bc;
} }
for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer)) for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
{ if (peer->conf_if
if (peer->conf_if && (strcmp (peer->conf_if, ifc->ifp->name) == 0) && && (strcmp(peer->conf_if, ifc->ifp->name) == 0)
peer->status != Established && && peer->status != Established
!CHECK_FLAG(peer->flags, PEER_FLAG_IFPEER_V6ONLY)) && !CHECK_FLAG(peer->flags,
{ PEER_FLAG_IFPEER_V6ONLY)) {
if (peer_active(peer)) if (peer_active(peer))
BGP_EVENT_ADD (peer, BGP_Stop); BGP_EVENT_ADD(peer, BGP_Stop);
BGP_EVENT_ADD (peer, BGP_Start); BGP_EVENT_ADD(peer, BGP_Start);
} }
} }
} } else if (addr->family == AF_INET6) {
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))
return; return;
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,71 +256,65 @@ 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))
return; return;
bgp_address_del (bgp, addr); bgp_address_del(bgp, addr);
rn = bgp_node_lookup (bgp->connected_table[AFI_IP], &p); rn = bgp_node_lookup(bgp->connected_table[AFI_IP], &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;
} }
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))
return; return;
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],
if (! rn) (struct prefix *)&p);
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;
} }
bgp_unlock_node (rn); bgp_unlock_node(rn);
bgp_unlock_node (rn); bgp_unlock_node(rn);
} }
} }
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)
return 1; return 1;
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;
@ -354,7 +325,7 @@ bgp_multiaccess_check_v4 (struct in_addr nexthop, struct peer *peer)
p.prefixlen = IPV4_MAX_BITLEN; p.prefixlen = IPV4_MAX_BITLEN;
p.u.prefix4 = nexthop; p.u.prefix4 = nexthop;
rn1 = bgp_node_match (peer->bgp->connected_table[AFI_IP], &p); rn1 = bgp_node_match(peer->bgp->connected_table[AFI_IP], &p);
if (!rn1) if (!rn1)
return 0; return 0;
@ -362,9 +333,8 @@ bgp_multiaccess_check_v4 (struct in_addr nexthop, struct peer *peer)
p.prefixlen = IPV4_MAX_BITLEN; p.prefixlen = IPV4_MAX_BITLEN;
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,101 +356,133 @@ 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",
sizeof (buf)), inet_ntop(
ifindex2ifname(nexthop->ifindex, bgp->vrf_id)); AF_INET6,
&nexthop->gate
.ipv6,
buf,
sizeof(buf)),
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",
sizeof (buf)), inet_ntop(
ifindex2ifname(nexthop->ifindex, bgp->vrf_id)); AF_INET,
&nexthop->gate
.ipv4,
buf,
sizeof(buf)),
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", vty_out(vty, " Last update: %s", ctime(&tbuf));
inet_ntop(rn->p.family, &rn->p.u.prefix, buf, sizeof(buf))); vty_out(vty, "\n");
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, VTYNL);
} }
} }
} }
} }
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;
if (name) if (name)
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;
} }
bgp_show_nexthops (vty, bgp, detail); bgp_show_nexthops(vty, bgp, 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);
} }
} }
@ -496,9 +497,9 @@ DEFUN (show_ip_bgp_nexthop,
"Show detailed information\n") "Show detailed information\n")
{ {
int idx = 0; int idx = 0;
char *vrf = argv_find (argv, argc, "WORD", &idx) ? argv[idx]->arg : NULL; char *vrf = argv_find(argv, argc, "WORD", &idx) ? argv[idx]->arg : NULL;
int detail = argv_find (argv, argc, "detail", &idx) ? 1 : 0; int detail = argv_find(argv, argc, "detail", &idx) ? 1 : 0;
return show_ip_bgp_nexthop_table (vty, vrf, detail); return show_ip_bgp_nexthop_table(vty, vrf, detail);
} }
DEFUN (show_ip_bgp_instance_all_nexthop, DEFUN (show_ip_bgp_instance_all_nexthop,
@ -510,46 +511,43 @@ DEFUN (show_ip_bgp_instance_all_nexthop,
BGP_INSTANCE_ALL_HELP_STR BGP_INSTANCE_ALL_HELP_STR
"BGP nexthop table\n") "BGP nexthop table\n")
{ {
bgp_show_all_instances_nexthops_vty (vty); bgp_show_all_instances_nexthops_vty(vty);
return CMD_SUCCESS; return CMD_SUCCESS;
} }
void void bgp_scan_init(struct bgp *bgp)
bgp_scan_init (struct bgp *bgp)
{ {
afi_t afi; afi_t afi;
for (afi = AFI_IP; afi < AFI_MAX; afi++) for (afi = AFI_IP; afi < AFI_MAX; afi++) {
{ bgp->nexthop_cache_table[afi] =
bgp->nexthop_cache_table[afi] = bgp_table_init (afi, SAFI_UNICAST); bgp_table_init(afi, SAFI_UNICAST);
bgp->connected_table[afi] = bgp_table_init (afi, SAFI_UNICAST); bgp->connected_table[afi] = bgp_table_init(afi, SAFI_UNICAST);
bgp->import_check_table[afi] = bgp_table_init (afi, SAFI_UNICAST); bgp->import_check_table[afi] =
bgp_table_init(afi, SAFI_UNICAST);
} }
} }
void void bgp_scan_vty_init(void)
bgp_scan_vty_init (void)
{ {
install_element (VIEW_NODE, &show_ip_bgp_nexthop_cmd); install_element(VIEW_NODE, &show_ip_bgp_nexthop_cmd);
install_element (VIEW_NODE, &show_ip_bgp_instance_all_nexthop_cmd); install_element(VIEW_NODE, &show_ip_bgp_instance_all_nexthop_cmd);
} }
void void bgp_scan_finish(struct bgp *bgp)
bgp_scan_finish (struct bgp *bgp)
{ {
afi_t afi; afi_t afi;
for (afi = AFI_IP; afi < AFI_MAX; afi++) for (afi = AFI_IP; afi < AFI_MAX; afi++) {
{
/* Only the current one needs to be reset. */ /* Only the current one needs to be reset. */
bgp_nexthop_cache_reset (bgp->nexthop_cache_table[afi]); bgp_nexthop_cache_reset(bgp->nexthop_cache_table[afi]);
bgp_table_unlock (bgp->nexthop_cache_table[afi]); bgp_table_unlock(bgp->nexthop_cache_table[afi]);
bgp->nexthop_cache_table[afi] = NULL; bgp->nexthop_cache_table[afi] = NULL;
bgp_table_unlock (bgp->connected_table[afi]); bgp_table_unlock(bgp->connected_table[afi]);
bgp->connected_table[afi] = NULL; bgp->connected_table[afi] = NULL;
bgp_table_unlock (bgp->import_check_table[afi]); bgp_table_unlock(bgp->import_check_table[afi]);
bgp->import_check_table[afi] = NULL; bgp->import_check_table[afi] = NULL;
} }
} }

View File

@ -25,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;
@ -68,13 +66,13 @@ struct bgp_nexthop_cache
struct bgp *bgp; struct bgp *bgp;
}; };
extern int bgp_nexthop_lookup (afi_t, struct peer *peer, struct bgp_info *, extern int bgp_nexthop_lookup(afi_t, struct peer *peer, struct bgp_info *,
int *, int *); int *, int *);
extern void bgp_connected_add (struct bgp *bgp, struct connected *c); extern void bgp_connected_add(struct bgp *bgp, struct connected *c);
extern void bgp_connected_delete (struct bgp *bgp, struct connected *c); extern void bgp_connected_delete(struct bgp *bgp, struct connected *c);
extern int bgp_multiaccess_check_v4 (struct in_addr, struct peer *); extern int bgp_multiaccess_check_v4(struct in_addr, struct peer *);
extern int bgp_config_write_scan_time (struct vty *); extern int bgp_config_write_scan_time(struct vty *);
extern int bgp_nexthop_self (struct bgp *, struct attr *); extern int bgp_nexthop_self(struct bgp *, struct in_addr);
extern struct bgp_nexthop_cache *bnc_new(void); extern struct bgp_nexthop_cache *bnc_new(void);
extern void bnc_free(struct bgp_nexthop_cache *bnc); extern void bnc_free(struct bgp_nexthop_cache *bnc);
extern void bnc_nexthop_free(struct bgp_nexthop_cache *bnc); extern void bnc_nexthop_free(struct bgp_nexthop_cache *bnc);
@ -82,7 +80,7 @@ extern char *bnc_str(struct bgp_nexthop_cache *bnc, char *buf, int size);
extern void bgp_scan_init(struct bgp *bgp); extern void bgp_scan_init(struct bgp *bgp);
extern void bgp_scan_finish(struct bgp *bgp); extern void bgp_scan_finish(struct bgp *bgp);
extern void bgp_scan_vty_init(void); extern void bgp_scan_vty_init(void);
extern void bgp_address_init (struct bgp *bgp); extern void bgp_address_init(struct bgp *bgp);
extern void bgp_address_destroy (struct bgp *bgp); extern void bgp_address_destroy(struct bgp *bgp);
#endif /* _QUAGGA_BGP_NEXTHOP_H */ #endif /* _QUAGGA_BGP_NEXTHOP_H */

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 (LIST_EMPTY(&(bnc->paths)) && !bnc->nht_info) {
{ if (BGP_DEBUG(nht, NHT)) {
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;
@ -111,21 +106,20 @@ bgp_unlink_nexthop (struct bgp_info *path)
path_nh_map(path, NULL, 0); path_nh_map(path, NULL, 0);
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;
struct bgp_nexthop_cache *bnc; struct bgp_nexthop_cache *bnc;
afi_t afi = family2afi(peer->su.sa.sa_family); afi_t afi = family2afi(peer->su.sa.sa_family);
if (! sockunion2hostprefix (&peer->su, &p)) if (!sockunion2hostprefix(&peer->su, &p))
return; return;
rn = bgp_node_get (peer->bgp->nexthop_cache_table[afi], &p); rn = bgp_node_get(peer->bgp->nexthop_cache_table[afi], &p);
if (!rn->info) if (!rn->info)
return; return;
@ -135,11 +129,10 @@ bgp_unlink_nexthop_by_peer (struct peer *peer)
/* cleanup the peer reference */ /* cleanup the peer reference */
bnc->nht_info = NULL; bnc->nht_info = NULL;
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,53 +140,52 @@ 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)
rn = bgp_node_get (bgp->import_check_table[afi], &p); rn = bgp_node_get(bgp->import_check_table[afi], &p);
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",
@ -202,62 +194,58 @@ 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);
path_nh_map(ri, bnc, 1); /* updates NHT ri list reference */ path_nh_map(ri, bnc, 1); /* updates NHT ri list reference */
@ -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;
@ -291,37 +277,37 @@ bgp_delete_connected_nexthop (afi_t afi, struct peer *peer)
return; return;
/* We don't register link local address for NHT */ /* We don't register link local address for NHT */
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; return;
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;
} }
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;
@ -348,10 +333,11 @@ bgp_parse_nexthop_update (int command, vrf_id_t vrf_id)
int i; int i;
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,10 +346,9 @@ 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;
case AF_INET6: case AF_INET6:
stream_get(&p.u.prefix6, s, 16); stream_get(&p.u.prefix6, s, 16);
@ -373,49 +358,49 @@ 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);
return; return;
} }
bnc = rn->info; bnc = rn->info;
bgp_unlock_node (rn); bgp_unlock_node(rn);
bnc->last_update = bgp_clock(); bnc->last_update = bgp_clock();
bnc->change_flags = 0; bnc->change_flags = 0;
stream_getc (s); // Distance but not currently used stream_getc(s); // Distance but not currently used
metric = stream_getl (s); metric = stream_getl(s);
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)
bnc->change_flags |= BGP_NEXTHOP_METRIC_CHANGED; bnc->change_flags |= BGP_NEXTHOP_METRIC_CHANGED;
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,55 +409,51 @@ 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);
break; break;
case NEXTHOP_TYPE_IFINDEX: case NEXTHOP_TYPE_IFINDEX:
nexthop->ifindex = stream_getl (s); nexthop->ifindex = stream_getl(s);
break; break;
case NEXTHOP_TYPE_IPV4_IFINDEX: case NEXTHOP_TYPE_IPV4_IFINDEX:
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);
break; break;
case NEXTHOP_TYPE_IPV6: case NEXTHOP_TYPE_IPV6:
stream_get (&nexthop->gate.ipv6, s, 16); stream_get(&nexthop->gate.ipv6, s, 16);
nexthop->ifindex = stream_getl (s); nexthop->ifindex = stream_getl(s);
break; break;
case NEXTHOP_TYPE_IPV6_IFINDEX: case NEXTHOP_TYPE_IPV6_IFINDEX:
stream_get (&nexthop->gate.ipv6, s, 16); stream_get(&nexthop->gate.ipv6, s, 16);
nexthop->ifindex = stream_getl (s); nexthop->ifindex = stream_getl(s);
break; break;
default: default:
/* do nothing */ /* do nothing */
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(
nexthop2str (nexthop, buf, sizeof (buf))); " nhop via %s",
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;
@ -586,20 +558,19 @@ sendmsg_zebra_rnh (struct bgp_nexthop_cache *bnc, int command)
p = &(bnc->node->p); p = &(bnc->node->p);
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;
case AF_INET6: case AF_INET6:
stream_put(s, &(p->u.prefix6), 16); stream_put(s, &(p->u.prefix6), 16);
@ -607,18 +578,18 @@ sendmsg_zebra_rnh (struct bgp_nexthop_cache *bnc, int command)
default: default:
break; break;
} }
stream_putw_at (s, 0, stream_get_endp (s)); stream_putw_at(s, 0, stream_get_endp(s));
ret = zclient_send_message(zclient); ret = zclient_send_message(zclient);
/* TBD: handle the failure */ /* TBD: handle the failure */
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,62 +651,61 @@ 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;
assert (rn && bgp_node_table (rn)); assert(rn && bgp_node_table(rn));
afi = family2afi(rn->p.family); afi = family2afi(rn->p.family);
table = bgp_node_table (rn); table = bgp_node_table(rn);
safi = table->safi; safi = table->safi;
/* 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 {
} bgp_info_set_flag(rn, path, BGP_INFO_VALID);
else bgp_aggregate_increment(bgp, &rn->p, path, afi,
{ safi);
bgp_info_set_flag (rn, path, BGP_INFO_VALID);
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.
@ -54,7 +54,7 @@ extern int bgp_find_or_add_nexthop(struct bgp *bgp, afi_t a,
* p - path structure. * p - path structure.
*/ */
extern void bgp_unlink_nexthop(struct bgp_info *p); extern void bgp_unlink_nexthop(struct bgp_info *p);
void bgp_unlink_nexthop_by_peer (struct peer *); void bgp_unlink_nexthop_by_peer(struct peer *);
/** /**
* bgp_delete_connected_nexthop() - Reset the 'peer' pointer for a connected * bgp_delete_connected_nexthop() - Reset the 'peer' pointer for a connected
@ -64,6 +64,6 @@ void bgp_unlink_nexthop_by_peer (struct peer *);
* afi - afi: AFI_IP or AF_IP6 * afi - afi: AFI_IP or AF_IP6
* peer - Ptr to peer * peer - Ptr to peer
*/ */
extern void bgp_delete_connected_nexthop (afi_t afi, struct peer *peer); extern void bgp_delete_connected_nexthop(afi_t afi, struct peer *peer);
#endif /* _BGP_NHT_H */ #endif /* _BGP_NHT_H */

File diff suppressed because it is too large Load Diff

View File

@ -22,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
@ -99,9 +93,10 @@ struct capability_gr
#define RESTART_R_BIT 0x8000 #define RESTART_R_BIT 0x8000
#define RESTART_F_BIT 0x80 #define RESTART_F_BIT 0x80
extern int bgp_open_option_parse (struct peer *, u_char, int *); extern int bgp_open_option_parse(struct peer *, u_char, int *);
extern void bgp_open_capability (struct stream *, struct peer *); extern void bgp_open_capability(struct stream *, struct peer *);
extern void bgp_capability_vty_out (struct vty *, struct peer *, u_char, json_object *); extern void bgp_capability_vty_out(struct vty *, struct peer *, u_char,
extern as_t peek_for_as4_capability (struct peer *, u_char); json_object *);
extern as_t peek_for_as4_capability(struct peer *, u_char);
#endif /* _QUAGGA_BGP_OPEN_H */ #endif /* _QUAGGA_BGP_OPEN_H */

File diff suppressed because it is too large Load Diff

View File

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

209
bgpd/bgp_rd.c Normal file
View File

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

70
bgpd/bgp_rd.h Normal file
View File

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

View File

@ -35,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;
@ -47,49 +46,44 @@ bgp_regcomp (const char *regstr)
int ret; int ret;
regex_t *regex; regex_t *regex;
len = strlen (regstr); len = strlen(regstr);
for (i = 0; i < len; i++) for (i = 0; i < len; i++)
if (regstr[i] == '_') if (regstr[i] == '_')
magic++; magic++;
magic_str = XMALLOC (MTYPE_TMP, len + (14 * magic) + 1); magic_str = XMALLOC(MTYPE_TMP, len + (14 * magic) + 1);
for (i = 0, j = 0; i < len; i++) for (i = 0, j = 0; i < len; i++) {
{ if (regstr[i] == '_') {
if (regstr[i] == '_') memcpy(magic_str + j, magic_regexp,
{ strlen(magic_regexp));
memcpy (magic_str + j, magic_regexp, strlen (magic_regexp)); j += strlen(magic_regexp);
j += strlen (magic_regexp); } else
}
else
magic_str[j++] = regstr[i]; magic_str[j++] = regstr[i];
} }
magic_str[j] = '\0'; magic_str[j] = '\0';
regex = XMALLOC (MTYPE_BGP_REGEXP, sizeof (regex_t)); regex = XMALLOC(MTYPE_BGP_REGEXP, sizeof(regex_t));
ret = regcomp (regex, magic_str, REG_EXTENDED|REG_NOSUB); ret = regcomp(regex, magic_str, REG_EXTENDED | REG_NOSUB);
XFREE (MTYPE_TMP, magic_str); XFREE(MTYPE_TMP, magic_str);
if (ret != 0) if (ret != 0) {
{ XFREE(MTYPE_BGP_REGEXP, regex);
XFREE (MTYPE_BGP_REGEXP, regex);
return NULL; return NULL;
} }
return regex; return regex;
} }
int int bgp_regexec(regex_t *regex, struct aspath *aspath)
bgp_regexec (regex_t *regex, struct aspath *aspath)
{ {
return regexec (regex, aspath->str, 0, NULL, 0); return regexec(regex, aspath->str, 0, NULL, 0);
} }
void void bgp_regex_free(regex_t *regex)
bgp_regex_free (regex_t *regex)
{ {
regfree (regex); regfree(regex);
XFREE (MTYPE_BGP_REGEXP, regex); XFREE(MTYPE_BGP_REGEXP, regex);
} }

View File

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

File diff suppressed because it is too large Load Diff

View File

@ -27,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,27 +229,27 @@ 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))
/* Flags which indicate a route is unuseable in some form */ /* Flags which indicate a route is unuseable in some form */
#define BGP_INFO_UNUSEABLE \ #define BGP_INFO_UNUSEABLE \
(BGP_INFO_HISTORY|BGP_INFO_DAMPED|BGP_INFO_REMOVED) (BGP_INFO_HISTORY | BGP_INFO_DAMPED | BGP_INFO_REMOVED)
/* Macro to check BGP information is alive or not. Sadly, /* Macro to check BGP information is alive or not. Sadly,
* not equivalent to just checking previous, because of the * not equivalent to just checking previous, because of the
* sense of the additional VALID flag. * sense of the additional VALID flag.
*/ */
#define BGP_INFO_HOLDDOWN(BI) \ #define BGP_INFO_HOLDDOWN(BI) \
(! CHECK_FLAG ((BI)->flags, BGP_INFO_VALID) \ (!CHECK_FLAG((BI)->flags, BGP_INFO_VALID) \
|| CHECK_FLAG ((BI)->flags, BGP_INFO_UNUSEABLE)) || CHECK_FLAG((BI)->flags, BGP_INFO_UNUSEABLE))
#define DISTRIBUTE_IN_NAME(F) ((F)->dlist[FILTER_IN].name) #define DISTRIBUTE_IN_NAME(F) ((F)->dlist[FILTER_IN].name)
#define DISTRIBUTE_IN(F) ((F)->dlist[FILTER_IN].alist) #define DISTRIBUTE_IN(F) ((F)->dlist[FILTER_IN].alist)
@ -265,122 +277,129 @@ struct bgp_static
/* path PREFIX (addpath rxid NUMBER) */ /* path PREFIX (addpath rxid NUMBER) */
#define PATH_ADDPATH_STR_BUFFER PREFIX2STR_BUFFER + 32 #define PATH_ADDPATH_STR_BUFFER PREFIX2STR_BUFFER + 32
enum bgp_path_type enum bgp_path_type { BGP_PATH_ALL, BGP_PATH_BESTPATH, BGP_PATH_MULTIPATH };
{
BGP_PATH_ALL,
BGP_PATH_BESTPATH,
BGP_PATH_MULTIPATH
};
static inline void static inline void bgp_bump_version(struct bgp_node *node)
bgp_bump_version (struct bgp_node *node)
{ {
node->version = bgp_table_next_version(bgp_node_table(node)); node->version = bgp_table_next_version(bgp_node_table(node));
} }
static inline int static inline int bgp_fibupd_safi(safi_t safi)
bgp_fibupd_safi (safi_t safi)
{ {
if (safi == SAFI_UNICAST || if (safi == SAFI_UNICAST || safi == SAFI_MULTICAST
safi == SAFI_MULTICAST || || safi == SAFI_LABELED_UNICAST)
safi == SAFI_LABELED_UNICAST)
return 1; return 1;
return 0; return 0;
} }
/* Prototypes. */ /* Prototypes. */
extern void bgp_process_queue_init (void); extern void bgp_process_queue_init(void);
extern void bgp_route_init (void); extern void bgp_route_init(void);
extern void bgp_route_finish (void); extern void bgp_route_finish(void);
extern void bgp_cleanup_routes (struct bgp *); extern void bgp_cleanup_routes(struct bgp *);
extern void bgp_announce_route (struct peer *, afi_t, safi_t); extern void bgp_announce_route(struct peer *, afi_t, safi_t);
extern void bgp_stop_announce_route_timer(struct peer_af *paf); extern void bgp_stop_announce_route_timer(struct peer_af *paf);
extern void bgp_announce_route_all (struct peer *); extern void bgp_announce_route_all(struct peer *);
extern void bgp_default_originate (struct peer *, afi_t, safi_t, int); extern void bgp_default_originate(struct peer *, afi_t, safi_t, int);
extern void bgp_soft_reconfig_in (struct peer *, afi_t, safi_t); extern void bgp_soft_reconfig_in(struct peer *, afi_t, safi_t);
extern void bgp_clear_route (struct peer *, afi_t, safi_t); extern void bgp_clear_route(struct peer *, afi_t, safi_t);
extern void bgp_clear_route_all (struct peer *); extern void bgp_clear_route_all(struct peer *);
extern void bgp_clear_adj_in (struct peer *, afi_t, safi_t); extern void bgp_clear_adj_in(struct peer *, afi_t, safi_t);
extern void bgp_clear_stale_route (struct peer *, afi_t, safi_t); extern void bgp_clear_stale_route(struct peer *, afi_t, safi_t);
extern struct bgp_node *bgp_afi_node_get (struct bgp_table *table, afi_t afi, extern struct bgp_node *bgp_afi_node_get(struct bgp_table *table, afi_t afi,
safi_t safi, struct prefix *p, safi_t safi, struct prefix *p,
struct prefix_rd *prd); struct prefix_rd *prd);
extern struct bgp_info *bgp_info_lock (struct bgp_info *); extern struct bgp_info *bgp_info_lock(struct bgp_info *);
extern struct bgp_info *bgp_info_unlock (struct bgp_info *); extern struct bgp_info *bgp_info_unlock(struct bgp_info *);
extern void bgp_info_add (struct bgp_node *rn, struct bgp_info *ri); extern void bgp_info_add(struct bgp_node *rn, struct bgp_info *ri);
extern void bgp_info_delete (struct bgp_node *rn, struct bgp_info *ri); extern void bgp_info_reap(struct bgp_node *rn, struct bgp_info *ri);
extern struct bgp_info_extra *bgp_info_extra_get (struct bgp_info *); extern void bgp_info_delete(struct bgp_node *rn, struct bgp_info *ri);
extern void bgp_info_set_flag (struct bgp_node *, struct bgp_info *, u_int32_t); extern struct bgp_info_extra *bgp_info_extra_get(struct bgp_info *);
extern void bgp_info_unset_flag (struct bgp_node *, struct bgp_info *, u_int32_t); extern void bgp_info_set_flag(struct bgp_node *, struct bgp_info *, u_int32_t);
extern void bgp_info_path_with_addpath_rx_str (struct bgp_info *ri, char *buf); extern void bgp_info_unset_flag(struct bgp_node *, struct bgp_info *,
u_int32_t);
extern void bgp_info_path_with_addpath_rx_str(struct bgp_info *ri, char *buf);
extern int bgp_nlri_parse_ip (struct peer *, struct attr *, struct bgp_nlri *); extern int bgp_nlri_parse_ip(struct peer *, struct attr *, struct bgp_nlri *);
extern int bgp_maximum_prefix_overflow (struct peer *, afi_t, safi_t, int); extern int bgp_maximum_prefix_overflow(struct peer *, afi_t, safi_t, int);
extern void bgp_redistribute_add (struct bgp *, struct prefix *, const struct in_addr *, extern void bgp_redistribute_add(struct bgp *, struct prefix *,
const struct 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,
extern void bgp_redistribute_withdraw (struct bgp *, afi_t, int, u_short); 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 */
extern void bgp_process (struct bgp *, struct bgp_node *, afi_t, safi_t); extern void bgp_process(struct bgp *, struct bgp_node *, afi_t, safi_t);
/* /*
* Add an end-of-initial-update marker to the process queue. This is just a * Add an end-of-initial-update marker to the process queue. This is just a
* queue element with NULL bgp node. * queue element with NULL bgp node.
*/ */
extern void bgp_add_eoiu_mark (struct bgp *); extern void bgp_add_eoiu_mark(struct bgp *);
extern int bgp_config_write_table_map (struct vty *, struct bgp *, afi_t, safi_t, extern int bgp_config_write_table_map(struct vty *, struct bgp *, afi_t, safi_t,
int *);
extern int bgp_config_write_network(struct vty *, struct bgp *, afi_t, safi_t,
int *);
extern int bgp_config_write_distance(struct vty *, struct bgp *, afi_t, safi_t,
int *); int *);
extern int bgp_config_write_network (struct vty *, struct bgp *, afi_t, safi_t, int *);
extern int bgp_config_write_distance (struct vty *, struct bgp *, afi_t, safi_t, int *);
extern void bgp_aggregate_increment (struct bgp *, struct prefix *, struct bgp_info *, 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);
@ -389,17 +408,36 @@ extern int subgroup_announce_check(struct bgp_node *rn, struct bgp_info *ri,
struct update_subgroup *subgrp, struct update_subgroup *subgrp,
struct prefix *p, struct attr *attr); struct prefix *p, struct attr *attr);
extern void bgp_peer_clear_node_queue_drain_immediate (struct peer *peer); extern void bgp_peer_clear_node_queue_drain_immediate(struct peer *peer);
extern void bgp_process_queues_drain_immediate (void); extern void bgp_process_queues_drain_immediate(void);
/* for encap/vpn */ /* for encap/vpn */
extern struct bgp_node * extern struct bgp_node *bgp_afi_node_get(struct bgp_table *, afi_t, safi_t,
bgp_afi_node_get (struct bgp_table *, afi_t , safi_t , struct prefix *, struct prefix *, struct prefix_rd *);
struct prefix_rd *); extern struct bgp_node *bgp_afi_node_lookup(struct bgp_table *table, afi_t afi,
extern struct bgp_info *bgp_info_new (void); safi_t safi, struct prefix *p,
extern void bgp_info_restore (struct bgp_node *, struct bgp_info *); struct prefix_rd *prd);
extern struct bgp_info *bgp_info_new(void);
extern void bgp_info_restore(struct bgp_node *, struct bgp_info *);
extern int bgp_info_cmp_compatible (struct bgp *, struct bgp_info *, extern int bgp_info_cmp_compatible(struct bgp *, struct bgp_info *,
struct bgp_info *, afi_t, safi_t ); struct bgp_info *, char *pfx_buf, afi_t afi,
safi_t safi);
extern void bgp_best_selection(struct bgp *bgp, struct bgp_node *rn,
struct bgp_maxpaths_cfg *mpath_cfg,
struct bgp_info_pair *result, afi_t afi,
safi_t safi);
extern void bgp_zebra_clear_route_change_flags(struct bgp_node *rn);
extern int bgp_zebra_has_route_changed(struct bgp_node *rn,
struct bgp_info *selected);
extern void route_vty_out_detail_header(struct vty *vty, struct bgp *bgp,
struct bgp_node *rn,
struct prefix_rd *prd, afi_t afi,
safi_t safi, json_object *json);
extern void route_vty_out_detail(struct vty *vty, struct bgp *bgp,
struct prefix *p, struct bgp_info *binfo,
afi_t afi, safi_t safi,
json_object *json_paths);
#endif /* _QUAGGA_BGP_ROUTE_H */ #endif /* _QUAGGA_BGP_ROUTE_H */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

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

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,16 +67,15 @@ struct bgp_node
* *
* Structure that holds state for iterating over a bgp table. * Structure that holds state for iterating over a bgp table.
*/ */
typedef struct bgp_table_iter_t_ typedef struct bgp_table_iter_t_ {
{
struct bgp_table *table; struct bgp_table *table;
route_table_iter_t rt_iter; route_table_iter_t rt_iter;
} bgp_table_iter_t; } bgp_table_iter_t;
extern struct bgp_table *bgp_table_init (afi_t, safi_t); extern struct bgp_table *bgp_table_init(afi_t, safi_t);
extern void bgp_table_lock (struct bgp_table *); extern void bgp_table_lock(struct bgp_table *);
extern void bgp_table_unlock (struct bgp_table *); extern void bgp_table_unlock(struct bgp_table *);
extern void bgp_table_finish (struct bgp_table **); extern void bgp_table_finish(struct bgp_table **);
/* /*
@ -85,10 +83,9 @@ extern void bgp_table_finish (struct bgp_table **);
* *
* Returns the bgp_node structure corresponding to a route_node. * Returns the bgp_node structure corresponding to a route_node.
*/ */
static inline struct bgp_node * static inline struct bgp_node *bgp_node_from_rnode(struct route_node *rnode)
bgp_node_from_rnode (struct route_node *rnode)
{ {
return (struct bgp_node *) rnode; return (struct bgp_node *)rnode;
} }
/* /*
@ -96,10 +93,9 @@ bgp_node_from_rnode (struct route_node *rnode)
* *
* Returns the route_node structure corresponding to a bgp_node. * Returns the route_node structure corresponding to a bgp_node.
*/ */
static inline struct route_node * static inline struct route_node *bgp_node_to_rnode(struct bgp_node *node)
bgp_node_to_rnode (struct bgp_node *node)
{ {
return (struct route_node *) node; return (struct route_node *)node;
} }
/* /*
@ -107,10 +103,9 @@ bgp_node_to_rnode (struct bgp_node *node)
* *
* Returns the bgp_table that the given node is in. * Returns the bgp_table that the given node is in.
*/ */
static inline struct bgp_table * static inline struct bgp_table *bgp_node_table(struct bgp_node *node)
bgp_node_table (struct bgp_node *node)
{ {
return bgp_node_to_rnode (node)->table->info; return bgp_node_to_rnode(node)->table->info;
} }
/* /*
@ -118,19 +113,17 @@ bgp_node_table (struct bgp_node *node)
* *
* Gets the parent node of the given node without locking it. * Gets the parent node of the given node without locking it.
*/ */
static inline struct bgp_node * static inline struct bgp_node *bgp_node_parent_nolock(struct bgp_node *node)
bgp_node_parent_nolock (struct bgp_node *node)
{ {
return bgp_node_from_rnode (node->parent); return bgp_node_from_rnode(node->parent);
} }
/* /*
* bgp_unlock_node * bgp_unlock_node
*/ */
static inline void static inline void bgp_unlock_node(struct bgp_node *node)
bgp_unlock_node (struct bgp_node *node)
{ {
route_unlock_node (bgp_node_to_rnode (node)); route_unlock_node(bgp_node_to_rnode(node));
} }
/* /*
@ -141,181 +134,171 @@ bgp_unlock_node (struct bgp_node *node)
* @see bgp_table_top * @see bgp_table_top
*/ */
static inline struct bgp_node * static inline struct bgp_node *
bgp_table_top_nolock (const struct bgp_table *const table) bgp_table_top_nolock(const struct bgp_table *const table)
{ {
return bgp_node_from_rnode (table->route_table->top); return bgp_node_from_rnode(table->route_table->top);
} }
/* /*
* bgp_table_top * bgp_table_top
*/ */
static inline struct bgp_node * static inline struct bgp_node *
bgp_table_top (const struct bgp_table *const table) bgp_table_top(const struct bgp_table *const table)
{ {
return bgp_node_from_rnode (route_top (table->route_table)); return bgp_node_from_rnode(route_top(table->route_table));
} }
/* /*
* bgp_route_next * bgp_route_next
*/ */
static inline struct bgp_node * static inline struct bgp_node *bgp_route_next(struct bgp_node *node)
bgp_route_next (struct bgp_node *node)
{ {
return bgp_node_from_rnode (route_next (bgp_node_to_rnode (node))); return bgp_node_from_rnode(route_next(bgp_node_to_rnode(node)));
} }
/* /*
* bgp_route_next_until * bgp_route_next_until
*/ */
static inline struct bgp_node * static inline struct bgp_node *bgp_route_next_until(struct bgp_node *node,
bgp_route_next_until (struct bgp_node *node, struct bgp_node *limit) struct bgp_node *limit)
{ {
struct route_node *rnode; struct route_node *rnode;
rnode = route_next_until (bgp_node_to_rnode (node), rnode = route_next_until(bgp_node_to_rnode(node),
bgp_node_to_rnode (limit)); bgp_node_to_rnode(limit));
return bgp_node_from_rnode (rnode); return bgp_node_from_rnode(rnode);
} }
/* /*
* bgp_node_get * bgp_node_get
*/ */
static inline struct bgp_node * static inline struct bgp_node *bgp_node_get(struct bgp_table *const table,
bgp_node_get (struct bgp_table *const table, struct prefix *p) struct prefix *p)
{ {
return bgp_node_from_rnode (route_node_get (table->route_table, p)); return bgp_node_from_rnode(route_node_get(table->route_table, p));
} }
/* /*
* bgp_node_lookup * bgp_node_lookup
*/ */
static inline struct bgp_node * static inline struct bgp_node *
bgp_node_lookup (const struct bgp_table *const table, struct prefix *p) bgp_node_lookup(const struct bgp_table *const table, struct prefix *p)
{ {
return bgp_node_from_rnode (route_node_lookup (table->route_table, p)); return bgp_node_from_rnode(route_node_lookup(table->route_table, p));
} }
/* /*
* bgp_lock_node * bgp_lock_node
*/ */
static inline struct bgp_node * static inline struct bgp_node *bgp_lock_node(struct bgp_node *node)
bgp_lock_node (struct bgp_node *node)
{ {
return bgp_node_from_rnode (route_lock_node (bgp_node_to_rnode (node))); return bgp_node_from_rnode(route_lock_node(bgp_node_to_rnode(node)));
} }
/* /*
* bgp_node_match * bgp_node_match
*/ */
static inline struct bgp_node * static inline struct bgp_node *bgp_node_match(const struct bgp_table *table,
bgp_node_match (const struct bgp_table *table, struct prefix *p) struct prefix *p)
{ {
return bgp_node_from_rnode (route_node_match (table->route_table, p)); return bgp_node_from_rnode(route_node_match(table->route_table, p));
} }
/* /*
* bgp_node_match_ipv4 * bgp_node_match_ipv4
*/ */
static inline struct bgp_node * static inline struct bgp_node *
bgp_node_match_ipv4 (const struct bgp_table *table, struct in_addr *addr) bgp_node_match_ipv4(const struct bgp_table *table, struct in_addr *addr)
{ {
return bgp_node_from_rnode (route_node_match_ipv4 (table->route_table, return bgp_node_from_rnode(
addr)); route_node_match_ipv4(table->route_table, addr));
} }
/* /*
* bgp_node_match_ipv6 * bgp_node_match_ipv6
*/ */
static inline struct bgp_node * static inline struct bgp_node *
bgp_node_match_ipv6 (const struct bgp_table *table, struct in6_addr *addr) bgp_node_match_ipv6(const struct bgp_table *table, struct in6_addr *addr)
{ {
return bgp_node_from_rnode (route_node_match_ipv6 (table->route_table, return bgp_node_from_rnode(
addr)); route_node_match_ipv6(table->route_table, addr));
} }
static inline unsigned long static inline unsigned long bgp_table_count(const struct bgp_table *const table)
bgp_table_count (const struct bgp_table *const table)
{ {
return route_table_count (table->route_table); return route_table_count(table->route_table);
} }
/* /*
* bgp_table_get_next * bgp_table_get_next
*/ */
static inline struct bgp_node * static inline struct bgp_node *bgp_table_get_next(const struct bgp_table *table,
bgp_table_get_next (const struct bgp_table *table, struct prefix *p) struct prefix *p)
{ {
return bgp_node_from_rnode (route_table_get_next (table->route_table, p)); return bgp_node_from_rnode(route_table_get_next(table->route_table, p));
} }
/* /*
* bgp_table_iter_init * bgp_table_iter_init
*/ */
static inline void static inline void bgp_table_iter_init(bgp_table_iter_t *iter,
bgp_table_iter_init (bgp_table_iter_t * iter, struct bgp_table *table) struct bgp_table *table)
{ {
bgp_table_lock (table); bgp_table_lock(table);
iter->table = table; iter->table = table;
route_table_iter_init (&iter->rt_iter, table->route_table); route_table_iter_init(&iter->rt_iter, table->route_table);
} }
/* /*
* bgp_table_iter_next * bgp_table_iter_next
*/ */
static inline struct bgp_node * static inline struct bgp_node *bgp_table_iter_next(bgp_table_iter_t *iter)
bgp_table_iter_next (bgp_table_iter_t * iter)
{ {
return bgp_node_from_rnode (route_table_iter_next (&iter->rt_iter)); return bgp_node_from_rnode(route_table_iter_next(&iter->rt_iter));
} }
/* /*
* bgp_table_iter_cleanup * bgp_table_iter_cleanup
*/ */
static inline void static inline void bgp_table_iter_cleanup(bgp_table_iter_t *iter)
bgp_table_iter_cleanup (bgp_table_iter_t * iter)
{ {
route_table_iter_cleanup (&iter->rt_iter); route_table_iter_cleanup(&iter->rt_iter);
bgp_table_unlock (iter->table); bgp_table_unlock(iter->table);
iter->table = NULL; iter->table = NULL;
} }
/* /*
* bgp_table_iter_pause * bgp_table_iter_pause
*/ */
static inline void static inline void bgp_table_iter_pause(bgp_table_iter_t *iter)
bgp_table_iter_pause (bgp_table_iter_t * iter)
{ {
route_table_iter_pause (&iter->rt_iter); route_table_iter_pause(&iter->rt_iter);
} }
/* /*
* bgp_table_iter_is_done * bgp_table_iter_is_done
*/ */
static inline int static inline int bgp_table_iter_is_done(bgp_table_iter_t *iter)
bgp_table_iter_is_done (bgp_table_iter_t * iter)
{ {
return route_table_iter_is_done (&iter->rt_iter); return route_table_iter_is_done(&iter->rt_iter);
} }
/* /*
* bgp_table_iter_started * bgp_table_iter_started
*/ */
static inline int static inline int bgp_table_iter_started(bgp_table_iter_t *iter)
bgp_table_iter_started (bgp_table_iter_t * iter)
{ {
return route_table_iter_started (&iter->rt_iter); return route_table_iter_started(&iter->rt_iter);
} }
/* This would benefit from a real atomic operation... /* This would benefit from a real atomic operation...
* until then. */ * until then. */
static inline uint64_t static inline uint64_t bgp_table_next_version(struct bgp_table *table)
bgp_table_next_version (struct bgp_table *table)
{ {
return ++table->version; return ++table->version;
} }
static inline uint64_t static inline uint64_t bgp_table_version(struct bgp_table *table)
bgp_table_version (struct bgp_table *table)
{ {
return table->version; return table->version;
} }

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,18 +69,16 @@ typedef struct
#define BPKT_ATTRVEC_FLAGS_RMAP_IPV6_GNH_CHANGED (1 << 5) #define BPKT_ATTRVEC_FLAGS_RMAP_IPV6_GNH_CHANGED (1 << 5)
#define BPKT_ATTRVEC_FLAGS_RMAP_IPV6_LNH_CHANGED (1 << 6) #define BPKT_ATTRVEC_FLAGS_RMAP_IPV6_LNH_CHANGED (1 << 6)
typedef struct bpacket_attr_vec_arr typedef struct bpacket_attr_vec_arr {
{
bpacket_attr_vec entries[BGP_ATTR_VEC_MAX]; bpacket_attr_vec entries[BGP_ATTR_VEC_MAX];
} bpacket_attr_vec_arr; } bpacket_attr_vec_arr;
struct bpacket struct bpacket {
{
/* for being part of an update subgroup's message list */ /* for being part of an update subgroup's message list */
TAILQ_ENTRY (bpacket) pkt_train; TAILQ_ENTRY(bpacket) pkt_train;
/* list of peers (well, peer_afs) that the packet needs to be sent to */ /* list of peers (well, peer_afs) that the packet needs to be sent to */
LIST_HEAD (pkt_peer_list, peer_af) peers; LIST_HEAD(pkt_peer_list, peer_af) peers;
struct stream *buffer; struct stream *buffer;
bpacket_attr_vec_arr arr; bpacket_attr_vec_arr arr;
@ -100,9 +86,8 @@ 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
/* A dummy packet that is used to thread all peers that have /* A dummy packet that is used to thread all peers that have
@ -116,13 +101,12 @@ 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;
/* list of subgroups that belong to the update group */ /* list of subgroups that belong to the update group */
LIST_HEAD (subgrp_list, update_subgroup) subgrps; LIST_HEAD(subgrp_list, update_subgroup) subgrps;
/* lazy way to store configuration common to all peers /* lazy way to store configuration common to all peers
hash function will compute from this data */ hash function will compute from this data */
@ -169,20 +153,18 @@ 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;
/* list of peers that belong to the subgroup */ /* list of peers that belong to the subgroup */
LIST_HEAD (peer_list, peer_af) peers; LIST_HEAD(peer_list, peer_af) peers;
int peer_count; int peer_count;
/* for being part of an update group's subgroup list */ /* for being part of an update group's subgroup list */
LIST_ENTRY (update_subgroup) updgrp_train; LIST_ENTRY(update_subgroup) updgrp_train;
struct bpacket_queue pkt_queue; struct bpacket_queue pkt_queue;
@ -191,7 +173,7 @@ struct update_subgroup
* It essentially represents the snapshot of every prefix that * It essentially represents the snapshot of every prefix that
* has been advertised to the members of the subgroup * has been advertised to the members of the subgroup
*/ */
TAILQ_HEAD (adjout_queue, bgp_adj_out) adjq; TAILQ_HEAD(adjout_queue, bgp_adj_out) adjq;
/* packet buffer for update generation */ /* packet buffer for update generation */
struct stream *work; struct stream *work;
@ -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)
@ -361,128 +341,115 @@ struct updwalk_context
/* Prototypes. */ /* Prototypes. */
/* bgp_updgrp.c */ /* bgp_updgrp.c */
extern void update_bgp_group_init (struct bgp *); extern void update_bgp_group_init(struct bgp *);
extern void udpate_bgp_group_free (struct bgp *); extern void udpate_bgp_group_free(struct bgp *);
extern void extern void update_group_show(struct bgp *bgp, afi_t afi, safi_t safi,
update_group_show (struct bgp *bgp, afi_t afi, safi_t safi, struct vty *vty, uint64_t subgrp_id); struct vty *vty, uint64_t subgrp_id);
extern void update_group_show_stats (struct bgp *bgp, struct vty *vty); extern void update_group_show_stats(struct bgp *bgp, struct vty *vty);
extern void update_group_adjust_peer (struct peer_af *paf); extern void update_group_adjust_peer(struct peer_af *paf);
extern int update_group_adjust_soloness (struct peer *peer, int set); extern int update_group_adjust_soloness(struct peer *peer, int set);
extern void extern void update_subgroup_remove_peer(struct update_subgroup *,
update_subgroup_remove_peer (struct update_subgroup *, struct peer_af *); struct peer_af *);
extern struct bgp_table *update_subgroup_rib (struct update_subgroup *); extern struct bgp_table *update_subgroup_rib(struct update_subgroup *);
extern void extern void update_subgroup_split_peer(struct peer_af *, struct update_group *);
update_subgroup_split_peer (struct peer_af *, struct update_group *); extern int update_subgroup_check_merge(struct update_subgroup *, const char *);
extern int 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
extern void update_group_start_advtimer (struct bgp *bgp); update_group_refresh_default_originate_route_map(struct thread *thread);
extern void update_group_start_advtimer(struct bgp *bgp);
extern void update_subgroup_inherit_info (struct update_subgroup *to, extern void update_subgroup_inherit_info(struct update_subgroup *to,
struct update_subgroup *from); struct update_subgroup *from);
/* bgp_updgrp_packet.c */ /* bgp_updgrp_packet.c */
extern struct bpacket *bpacket_alloc (void); extern struct bpacket *bpacket_alloc(void);
extern void bpacket_free (struct bpacket *pkt); extern void bpacket_free(struct bpacket *pkt);
extern void bpacket_queue_init (struct bpacket_queue *q); extern void bpacket_queue_init(struct bpacket_queue *q);
extern void bpacket_queue_cleanup (struct bpacket_queue *q); extern void bpacket_queue_cleanup(struct bpacket_queue *q);
extern void bpacket_queue_sanity_check (struct bpacket_queue *q); extern void bpacket_queue_sanity_check(struct bpacket_queue *q);
extern struct bpacket *bpacket_queue_add (struct bpacket_queue *q, extern struct bpacket *bpacket_queue_add(struct bpacket_queue *q,
struct stream *s, struct stream *s,
struct bpacket_attr_vec_arr struct bpacket_attr_vec_arr *vecarr);
*vecarr); struct bpacket *bpacket_queue_remove(struct bpacket_queue *q);
struct bpacket *bpacket_queue_remove (struct bpacket_queue *q); extern struct bpacket *bpacket_queue_first(struct bpacket_queue *q);
extern struct bpacket *bpacket_queue_first (struct bpacket_queue *q); struct bpacket *bpacket_queue_last(struct bpacket_queue *q);
struct bpacket *bpacket_queue_last (struct bpacket_queue *q); unsigned int bpacket_queue_length(struct bpacket_queue *q);
unsigned int bpacket_queue_length (struct bpacket_queue *q); unsigned int bpacket_queue_hwm_length(struct bpacket_queue *q);
unsigned int bpacket_queue_hwm_length (struct bpacket_queue *q); int bpacket_queue_is_full(struct bgp *bgp, struct bpacket_queue *q);
int bpacket_queue_is_full (struct bgp *bgp, struct bpacket_queue *q); extern void bpacket_queue_advance_peer(struct peer_af *paf);
extern void bpacket_queue_advance_peer (struct peer_af *paf); extern void bpacket_queue_remove_peer(struct peer_af *paf);
extern void bpacket_queue_remove_peer (struct peer_af *paf); extern void bpacket_add_peer(struct bpacket *pkt, struct peer_af *paf);
extern void bpacket_add_peer (struct bpacket *pkt, struct peer_af *paf); unsigned int bpacket_queue_virtual_length(struct peer_af *paf);
unsigned int bpacket_queue_virtual_length (struct peer_af *paf); extern void bpacket_queue_show_vty(struct bpacket_queue *q, struct vty *vty);
extern void bpacket_queue_show_vty (struct bpacket_queue *q, struct vty *vty); int subgroup_packets_to_build(struct update_subgroup *subgrp);
int subgroup_packets_to_build (struct update_subgroup *subgrp); extern struct bpacket *subgroup_update_packet(struct update_subgroup *s);
extern struct bpacket *subgroup_update_packet (struct update_subgroup *s); extern struct bpacket *subgroup_withdraw_packet(struct update_subgroup *s);
extern struct bpacket *subgroup_withdraw_packet (struct update_subgroup *s); extern struct stream *bpacket_reformat_for_peer(struct bpacket *pkt,
extern struct stream *bpacket_reformat_for_peer (struct bpacket *pkt,
struct peer_af *paf); struct peer_af *paf);
extern void bpacket_attr_vec_arr_reset (struct bpacket_attr_vec_arr *vecarr); extern void bpacket_attr_vec_arr_reset(struct bpacket_attr_vec_arr *vecarr);
extern void bpacket_attr_vec_arr_set_vec (struct bpacket_attr_vec_arr *vecarr, extern void bpacket_attr_vec_arr_set_vec(struct bpacket_attr_vec_arr *vecarr,
bpacket_attr_vec_type type, bpacket_attr_vec_type type,
struct stream *s, struct 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, extern void update_group_show_advertised(struct bgp *bgp, afi_t afi,
safi_t safi, struct vty *vty, safi_t safi, struct vty *vty,
uint64_t id); uint64_t id);
extern void update_group_show_advertised (struct bgp *bgp, afi_t afi, extern void update_group_show_packet_queue(struct bgp *bgp, afi_t afi,
safi_t safi, struct vty *vty, safi_t safi, struct vty *vty,
uint64_t id); uint64_t id);
extern void update_group_show_packet_queue (struct bgp *bgp, afi_t afi, extern void subgroup_announce_route(struct update_subgroup *subgrp);
safi_t safi, struct vty *vty, extern void subgroup_announce_all(struct update_subgroup *subgrp);
uint64_t id);
extern void subgroup_announce_route (struct update_subgroup *subgrp);
extern void subgroup_announce_all (struct update_subgroup *subgrp);
extern void extern void subgroup_default_originate(struct update_subgroup *subgrp,
subgroup_default_originate (struct update_subgroup *subgrp, int withdraw); int withdraw);
extern void extern void group_announce_route(struct bgp *bgp, afi_t afi, safi_t safi,
group_announce_route (struct bgp *bgp, afi_t afi, safi_t safi,
struct bgp_node *rn, struct bgp_info *ri); struct bgp_node *rn, struct bgp_info *ri);
extern void subgroup_clear_table (struct update_subgroup *subgrp); extern void subgroup_clear_table(struct update_subgroup *subgrp);
extern void update_group_announce (struct bgp *bgp); extern void update_group_announce(struct bgp *bgp);
extern void update_group_announce_rrclients (struct bgp *bgp); extern void update_group_announce_rrclients(struct bgp *bgp);
extern void peer_af_announce_route (struct peer_af *paf, int combine); extern void peer_af_announce_route(struct peer_af *paf, int combine);
extern struct bgp_adj_out *bgp_adj_out_alloc (struct update_subgroup *subgrp, extern struct bgp_adj_out *bgp_adj_out_alloc(struct update_subgroup *subgrp,
struct bgp_node *rn, struct bgp_node *rn,
u_int32_t addpath_tx_id); u_int32_t addpath_tx_id);
extern void bgp_adj_out_remove_subgroup (struct bgp_node *rn, extern void bgp_adj_out_remove_subgroup(struct bgp_node *rn,
struct bgp_adj_out *adj, struct bgp_adj_out *adj,
struct update_subgroup *subgrp); struct update_subgroup *subgrp);
extern void 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);
extern int bgp_addpath_tx_path (struct peer *peer, afi_t afi, safi_t safi, extern int bgp_addpath_tx_path(struct peer *peer, afi_t afi, safi_t safi,
struct bgp_info *ri); struct bgp_info *ri);
/* /*
@ -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)
{ {
/* /*
@ -502,7 +468,7 @@ bpacket_queue_is_empty (struct bpacket_queue *queue)
if (queue->curr_count != 1) if (queue->curr_count != 1)
return 0; return 0;
assert (bpacket_queue_first (queue)->buffer == NULL); assert(bpacket_queue_first(queue)->buffer == NULL);
return 1; return 1;
} }
@ -511,10 +477,9 @@ bpacket_queue_is_empty (struct bpacket_queue *queue)
* *
* Returns the packet after the given packet in a bpacket queue. * Returns the packet after the given packet in a bpacket queue.
*/ */
static inline struct bpacket * static inline struct bpacket *bpacket_next(struct bpacket *pkt)
bpacket_next (struct bpacket *pkt)
{ {
return TAILQ_NEXT (pkt, pkt_train); return TAILQ_NEXT(pkt, pkt_train);
} }
/* /*
@ -522,17 +487,15 @@ 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,17 +504,15 @@ 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);
} }
} }
@ -559,9 +520,9 @@ update_group_remove_peer_afs (struct peer *peer)
* update_subgroup_needs_refresh * update_subgroup_needs_refresh
*/ */
static inline int static inline int
update_subgroup_needs_refresh (const struct update_subgroup *subgrp) update_subgroup_needs_refresh(const struct update_subgroup *subgrp)
{ {
if (CHECK_FLAG (subgrp->flags, SUBGRP_FLAG_NEEDS_REFRESH)) if (CHECK_FLAG(subgrp->flags, SUBGRP_FLAG_NEEDS_REFRESH))
return 1; return 1;
else else
return 0; return 0;
@ -571,22 +532,22 @@ update_subgroup_needs_refresh (const struct update_subgroup *subgrp)
* update_subgroup_set_needs_refresh * update_subgroup_set_needs_refresh
*/ */
static inline void static inline void
update_subgroup_set_needs_refresh (struct update_subgroup *subgrp, int value) update_subgroup_set_needs_refresh(struct update_subgroup *subgrp, int value)
{ {
if (value) if (value)
SET_FLAG (subgrp->flags, SUBGRP_FLAG_NEEDS_REFRESH); SET_FLAG(subgrp->flags, SUBGRP_FLAG_NEEDS_REFRESH);
else else
UNSET_FLAG (subgrp->flags, SUBGRP_FLAG_NEEDS_REFRESH); UNSET_FLAG(subgrp->flags, SUBGRP_FLAG_NEEDS_REFRESH);
} }
static inline struct update_subgroup * static inline struct update_subgroup *peer_subgroup(struct peer *peer,
peer_subgroup (struct peer *peer, afi_t afi, safi_t safi) afi_t afi, safi_t safi)
{ {
struct peer_af *paf; struct peer_af *paf;
paf = peer_af_find (peer, afi, safi); paf = peer_af_find(peer, afi, safi);
if (paf) if (paf)
return PAF_SUBGRP (paf); return PAF_SUBGRP(paf);
return NULL; return NULL;
} }
@ -595,30 +556,26 @@ peer_subgroup (struct peer *peer, afi_t afi, safi_t safi)
* *
* Adjust all peer_af structures for the given peer. * Adjust all peer_af structures for the given peer.
*/ */
static inline void static inline void bgp_announce_peer(struct peer *peer)
bgp_announce_peer (struct peer *peer)
{ {
struct peer_af *paf; struct peer_af *paf;
int afidx; int afidx;
for (afidx = BGP_AF_START; afidx < BGP_AF_MAX; afidx++) for (afidx = BGP_AF_START; afidx < BGP_AF_MAX; afidx++) {
{
paf = peer->peer_af_array[afidx]; paf = peer->peer_af_array[afidx];
if (paf != NULL) if (paf != NULL)
subgroup_announce_all (PAF_SUBGRP (paf)); subgroup_announce_all(PAF_SUBGRP(paf));
} }
} }
/** /**
* advertise_list_is_empty * advertise_list_is_empty
*/ */
static inline int static inline int advertise_list_is_empty(struct update_subgroup *subgrp)
advertise_list_is_empty (struct update_subgroup *subgrp)
{ {
if (!BGP_ADV_FIFO_EMPTY (&subgrp->sync->update) || if (!BGP_ADV_FIFO_EMPTY(&subgrp->sync->update)
!BGP_ADV_FIFO_EMPTY (&subgrp->sync->withdraw) || || !BGP_ADV_FIFO_EMPTY(&subgrp->sync->withdraw)
!BGP_ADV_FIFO_EMPTY (&subgrp->sync->withdraw_low)) || !BGP_ADV_FIFO_EMPTY(&subgrp->sync->withdraw_low)) {
{
return 0; return 0;
} }

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -21,8 +21,8 @@
#if ENABLE_BGP_VNC #if ENABLE_BGP_VNC
typedef enum { typedef enum {
BGP_VNC_SUBTLV_TYPE_LIFETIME=1, BGP_VNC_SUBTLV_TYPE_LIFETIME = 1,
BGP_VNC_SUBTLV_TYPE_RFPOPTION=2, /* deprecated */ BGP_VNC_SUBTLV_TYPE_RFPOPTION = 2, /* deprecated */
} bgp_vnc_subtlv_types; } bgp_vnc_subtlv_types;
/* /*

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;
@ -47,16 +47,14 @@ show_adj_route_vpn (struct vty *vty, struct peer *peer, struct prefix_rd *prd,
json_object *json_routes = NULL; json_object *json_routes = NULL;
json_object *json_array = NULL; json_object *json_array = NULL;
bgp = bgp_get_default (); bgp = bgp_get_default();
if (bgp == NULL) if (bgp == NULL) {
{
if (!use_json) if (!use_json)
vty_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();
@ -74,14 +72,12 @@ show_adj_route_vpn (struct vty *vty, struct peer *peer, struct prefix_rd *prd,
json_object_string_add(json_ocode, "incomplete", "?"); json_object_string_add(json_ocode, "incomplete", "?");
} }
for (rn = bgp_table_top (bgp->rib[afi][SAFI_MPLS_VPN]); rn; for (rn = bgp_table_top(bgp->rib[afi][SAFI_MPLS_VPN]); rn;
rn = bgp_route_next (rn)) rn = bgp_route_next(rn)) {
{ if (prd && memcmp(rn->p.u.val, prd->val, 8) != 0)
if (prd && memcmp (rn->p.u.val, prd->val, 8) != 0)
continue; continue;
if ((table = rn->info) != NULL) if ((table = rn->info) != NULL) {
{
if (use_json) if (use_json)
json_array = json_object_new_array(); json_array = json_object_new_array();
else else
@ -89,112 +85,166 @@ 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;
pnt = rn->p.u.val; pnt = rn->p.u.val;
/* Decode RD type. */ /* Decode RD type. */
type = decode_rd_type (pnt); type = decode_rd_type(pnt);
/* Decode RD value. */ /* Decode RD value. */
if (type == RD_TYPE_AS) if (type == RD_TYPE_AS)
decode_rd_as (pnt + 2, &rd_as); decode_rd_as(pnt + 2,
&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,39 +28,46 @@ struct bgp;
#define BGP_AFI_CMD_STR "<ipv4|ipv6>" #define BGP_AFI_CMD_STR "<ipv4|ipv6>"
#define BGP_AFI_HELP_STR "Address Family\nAddress Family\n" #define BGP_AFI_HELP_STR "Address Family\nAddress Family\n"
#define BGP_SAFI_CMD_STR "<unicast|multicast|vpn|labeled-unicast>" #define BGP_SAFI_CMD_STR "<unicast|multicast|vpn>"
#define BGP_SAFI_HELP_STR \ #define BGP_SAFI_HELP_STR \
"Address Family modifier\n" \
"Address Family modifier\n" \ "Address Family modifier\n" \
"Address Family modifier\n" \ "Address Family modifier\n" \
"Address Family modifier\n" "Address Family modifier\n"
#define BGP_AFI_SAFI_CMD_STR BGP_AFI_CMD_STR" "BGP_SAFI_CMD_STR #define BGP_AFI_SAFI_CMD_STR BGP_AFI_CMD_STR" "BGP_SAFI_CMD_STR
#define BGP_AFI_SAFI_HELP_STR BGP_AFI_HELP_STR BGP_SAFI_HELP_STR #define BGP_AFI_SAFI_HELP_STR BGP_AFI_HELP_STR BGP_SAFI_HELP_STR
extern void bgp_vty_init (void); #define BGP_SAFI_WITH_LABEL_CMD_STR "<unicast|multicast|vpn|labeled-unicast>"
extern const char *afi_safi_print (afi_t, safi_t); #define BGP_SAFI_WITH_LABEL_HELP_STR \
extern const char *afi_safi_json (afi_t, safi_t); "Address Family modifier\n" \
extern int bgp_config_write_update_delay (struct vty *, struct bgp *); "Address Family modifier\n" \
"Address Family modifier\n" \
"Address Family modifier\n"
extern void bgp_vty_init(void);
extern const char *afi_safi_print(afi_t, safi_t);
extern const char *afi_safi_json(afi_t, safi_t);
extern int bgp_config_write_update_delay(struct vty *, struct bgp *);
extern int bgp_config_write_wpkt_quanta(struct vty *vty, struct bgp *bgp); extern int bgp_config_write_wpkt_quanta(struct vty *vty, struct bgp *bgp);
extern int bgp_config_write_listen(struct vty *vty, struct bgp *bgp); extern int bgp_config_write_listen(struct vty *vty, struct bgp *bgp);
extern int bgp_config_write_coalesce_time(struct vty *vty, struct bgp *bgp); extern int bgp_config_write_coalesce_time(struct vty *vty, struct bgp *bgp);
extern int bgp_vty_return (struct vty *vty, int ret); extern int bgp_vty_return(struct vty *vty, int ret);
extern struct peer * extern struct peer *peer_and_group_lookup_vty(struct vty *vty,
peer_and_group_lookup_vty (struct vty *vty, const char *peer_str); const char *peer_str);
extern afi_t extern afi_t bgp_vty_afi_from_str(const char *afi_str);
bgp_vty_afi_from_str(const char *afi_str);
extern safi_t extern safi_t bgp_vty_safi_from_str(const char *safi_str);
bgp_vty_safi_from_str(const char *safi_str);
extern int extern int argv_find_and_parse_afi(struct cmd_token **argv, int argc,
argv_find_and_parse_afi(struct cmd_token **argv, int argc, int *index, afi_t *afi); int *index, afi_t *afi);
extern int extern int argv_find_and_parse_safi(struct cmd_token **argv, int argc,
argv_find_and_parse_safi(struct cmd_token **argv, int argc, int *index, safi_t *safi); int *index, safi_t *safi);
extern int extern int bgp_vty_find_and_parse_afi_safi_bgp(struct vty *vty,
bgp_vty_find_and_parse_afi_safi_bgp (struct vty *vty, struct cmd_token **argv, int argc, int *idx, struct cmd_token **argv,
afi_t *afi, safi_t *safi, struct bgp **bgp); int argc, int *idx, afi_t *afi,
safi_t *safi, struct bgp **bgp);
extern int bgp_show_summary_vty(struct vty *vty, const char *name, afi_t afi,
safi_t safi, u_char use_json);
#endif /* _QUAGGA_BGP_VTY_H */ #endif /* _QUAGGA_BGP_VTY_H */

File diff suppressed because it is too large Load Diff

View File

@ -21,46 +21,43 @@
#ifndef _QUAGGA_BGP_ZEBRA_H #ifndef _QUAGGA_BGP_ZEBRA_H
#define _QUAGGA_BGP_ZEBRA_H #define _QUAGGA_BGP_ZEBRA_H
#define BGP_NEXTHOP_BUF_SIZE (8 * sizeof (struct in_addr *)) extern void bgp_zebra_init(struct thread_master *master);
#define BGP_IFINDICES_BUF_SIZE (8 * sizeof (unsigned int)) extern void bgp_zebra_destroy(void);
#define BGP_LABEL_BUF_SIZE (8 * sizeof (unsigned int)) extern int bgp_if_update_all(void);
extern int bgp_config_write_maxpaths(struct vty *, struct bgp *, afi_t, safi_t,
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_destroy (void);
extern int bgp_if_update_all (void);
extern int bgp_config_write_maxpaths (struct vty *, struct bgp *, afi_t,
safi_t, int *);
extern int bgp_config_write_redistribute (struct vty *, struct bgp *, afi_t, safi_t,
int *); int *);
extern void bgp_zebra_announce (struct bgp_node *, struct prefix *, extern int bgp_config_write_redistribute(struct vty *, struct bgp *, afi_t,
safi_t, int *);
extern void bgp_zebra_announce(struct bgp_node *, struct prefix *,
struct bgp_info *, struct bgp *, afi_t, safi_t); 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);
extern void bgp_zebra_withdraw (struct prefix *, struct bgp_info *, safi_t); extern void bgp_zebra_withdraw(struct prefix *, struct bgp_info *, safi_t);
extern void bgp_zebra_initiate_radv (struct bgp *bgp, struct peer *peer); extern void bgp_zebra_initiate_radv(struct bgp *bgp, struct peer *peer);
extern void bgp_zebra_terminate_radv (struct bgp *bgp, struct peer *peer); extern void bgp_zebra_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,
extern struct bgp_redist *bgp_redist_add (struct bgp *, afi_t, u_char, u_short); u_short);
extern int bgp_redistribute_set (struct bgp *, afi_t, int, u_short); extern struct bgp_redist *bgp_redist_add(struct bgp *, afi_t, u_char, u_short);
extern int bgp_redistribute_resend (struct bgp *, afi_t, int, u_short); extern int bgp_redistribute_set(struct bgp *, afi_t, int, u_short);
extern int bgp_redistribute_rmap_set (struct bgp_redist *, const char *); extern int bgp_redistribute_resend(struct bgp *, afi_t, int, u_short);
extern int bgp_redistribute_metric_set(struct bgp *, struct bgp_redist *, extern int bgp_redistribute_rmap_set(struct bgp_redist *, const char *);
afi_t, int, u_int32_t); extern int bgp_redistribute_metric_set(struct bgp *, struct bgp_redist *, afi_t,
extern int bgp_redistribute_unset (struct bgp *, afi_t, int, u_short); int, u_int32_t);
extern int bgp_redistribute_unreg (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 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,
@ -59,13 +60,14 @@ typedef u_int32_t as_t;
typedef u_int16_t as16_t; /* we may still encounter 16 Bit asnums */ 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__ (b) _b = (b); \ __typeof__(a) _a = (a); \
_a > _b ? _a : _b; }) __typeof__(b) _b = (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];
@ -874,8 +885,8 @@ struct peer
#define PEER_DOWN_BFD_DOWN 24 /* BFD down */ #define PEER_DOWN_BFD_DOWN 24 /* BFD down */
#define PEER_DOWN_IF_DOWN 25 /* Interface down */ #define PEER_DOWN_IF_DOWN 25 /* Interface down */
#define PEER_DOWN_NBR_ADDR_DEL 26 /* Peer address lost */ #define PEER_DOWN_NBR_ADDR_DEL 26 /* Peer address lost */
unsigned long last_reset_cause_size; unsigned long last_reset_cause_size;
u_char last_reset_cause[BGP_MAX_PACKET_SIZE]; u_char last_reset_cause[BGP_MAX_PACKET_SIZE];
/* The kind of route-map Flags.*/ /* The kind of route-map Flags.*/
u_char rmap_type; u_char rmap_type;
@ -901,16 +912,15 @@ DECLARE_QOBJ_TYPE(peer)
/* Check if suppress start/restart of sessions to peer. */ /* Check if suppress start/restart of sessions to peer. */
#define BGP_PEER_START_SUPPRESSED(P) \ #define BGP_PEER_START_SUPPRESSED(P) \
(CHECK_FLAG ((P)->flags, PEER_FLAG_SHUTDOWN) \ (CHECK_FLAG((P)->flags, PEER_FLAG_SHUTDOWN) \
|| CHECK_FLAG ((P)->sflags, PEER_STATUS_PREFIX_OVERFLOW)) || CHECK_FLAG((P)->sflags, PEER_STATUS_PREFIX_OVERFLOW))
#define PEER_PASSWORD_MINLEN (1) #define PEER_PASSWORD_MINLEN (1)
#define PEER_PASSWORD_MAXLEN (80) #define PEER_PASSWORD_MAXLEN (80)
/* 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,
@ -1112,7 +1121,7 @@ enum bgp_clear_type
/* Macros. */ /* Macros. */
#define BGP_INPUT(P) ((P)->ibuf) #define BGP_INPUT(P) ((P)->ibuf)
#define BGP_INPUT_PNT(P) (STREAM_PNT(BGP_INPUT(P))) #define BGP_INPUT_PNT(P) (STREAM_PNT(BGP_INPUT(P)))
#define BGP_IS_VALID_STATE_FOR_NOTIF(S)\ #define BGP_IS_VALID_STATE_FOR_NOTIF(S) \
(((S) == OpenSent) || ((S) == OpenConfirm) || ((S) == Established)) (((S) == OpenSent) || ((S) == OpenConfirm) || ((S) == Established))
/* BGP error codes. */ /* BGP error codes. */
@ -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,
@ -1167,32 +1176,34 @@ extern struct bgp_master *bm;
extern unsigned int multipath_num; extern unsigned int multipath_num;
/* Prototypes. */ /* Prototypes. */
extern void bgp_terminate (void); extern void bgp_terminate(void);
extern void bgp_reset (void); extern void bgp_reset(void);
extern time_t bgp_clock (void); extern time_t bgp_clock(void);
extern void bgp_zclient_reset (void); extern void bgp_zclient_reset(void);
extern int bgp_nexthop_set (union sockunion *, union sockunion *, extern int bgp_nexthop_set(union sockunion *, union sockunion *,
struct bgp_nexthop *, struct peer *); struct bgp_nexthop *, struct peer *);
extern struct bgp *bgp_get_default (void); extern struct bgp *bgp_get_default(void);
extern struct bgp *bgp_lookup (as_t, const char *); extern struct bgp *bgp_lookup(as_t, const char *);
extern struct bgp *bgp_lookup_by_name (const char *); extern struct bgp *bgp_lookup_by_name(const char *);
extern struct bgp *bgp_lookup_by_vrf_id (vrf_id_t); extern struct bgp *bgp_lookup_by_vrf_id(vrf_id_t);
extern struct peer *peer_lookup (struct bgp *, union sockunion *); extern struct peer *peer_lookup(struct bgp *, union sockunion *);
extern struct peer *peer_lookup_by_conf_if (struct bgp *, const char *); extern struct peer *peer_lookup_by_conf_if(struct bgp *, const char *);
extern struct peer *peer_lookup_by_hostname(struct bgp *, const char *); extern struct peer *peer_lookup_by_hostname(struct bgp *, const char *);
extern void bgp_peer_conf_if_to_su_update (struct peer *); extern void bgp_peer_conf_if_to_su_update(struct peer *);
extern int peer_group_listen_range_del(struct peer_group *, struct prefix *); 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 *
extern struct peer_group *peer_group_lookup_dynamic_neighbor (struct bgp *, peer_group_lookup_dynamic_neighbor_range(struct peer_group *, struct prefix *);
struct prefix *, struct prefix **); extern struct peer_group *peer_group_lookup_dynamic_neighbor(struct bgp *,
extern struct peer *peer_lookup_dynamic_neighbor (struct bgp *, struct prefix *,
struct prefix **);
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 *);
/* /*
* Peers are incredibly easy to memory leak * Peers are incredibly easy to memory leak
@ -1204,187 +1215,188 @@ extern struct peer *peer_unlock_with_caller(const char *, struct peer *);
#define peer_unlock(A) peer_unlock_with_caller(__FUNCTION__, (A)) #define peer_unlock(A) peer_unlock_with_caller(__FUNCTION__, (A))
#define peer_lock(B) peer_lock_with_caller(__FUNCTION__, (B)) #define peer_lock(B) peer_lock_with_caller(__FUNCTION__, (B))
extern bgp_peer_sort_t peer_sort (struct peer *peer); extern bgp_peer_sort_t peer_sort(struct peer *peer);
extern int peer_active (struct peer *); 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,
extern struct peer *peer_create_accept (struct bgp *); struct peer_group *);
extern void peer_xfer_config (struct peer *dst, struct peer *src); extern struct peer *peer_create_accept(struct bgp *);
extern char *peer_uptime (time_t, char *, size_t, u_char, json_object *); 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 int bgp_config_write (struct vty *); extern int bgp_config_write(struct vty *);
extern void bgp_config_write_family_header (struct vty *, afi_t, safi_t, int *); extern void bgp_config_write_family_header(struct vty *, afi_t, safi_t, int *);
extern void bgp_master_init (struct thread_master *master); extern void bgp_master_init(struct thread_master *master);
extern void bgp_init (void); extern void bgp_init(void);
extern void bgp_route_map_init (void); extern void bgp_route_map_init(void);
extern void bgp_session_reset (struct peer *); extern void bgp_session_reset(struct peer *);
extern int bgp_option_set (int); extern int bgp_option_set(int);
extern int bgp_option_unset (int); extern int bgp_option_unset(int);
extern int bgp_option_check (int); extern int bgp_option_check(int);
extern int bgp_get (struct bgp **, as_t *, const char *, enum bgp_instance_type); extern int bgp_get(struct bgp **, as_t *, const char *, enum bgp_instance_type);
extern void bgp_instance_up (struct bgp *); extern void bgp_instance_up(struct bgp *);
extern void bgp_instance_down (struct bgp *); extern void bgp_instance_down(struct bgp *);
extern int bgp_delete (struct bgp *); extern int bgp_delete(struct bgp *);
extern int bgp_flag_set (struct bgp *, int); extern int bgp_flag_set(struct bgp *, int);
extern int bgp_flag_unset (struct bgp *, int); extern int bgp_flag_unset(struct bgp *, int);
extern int bgp_flag_check (struct bgp *, int); extern int bgp_flag_check(struct bgp *, int);
extern void bgp_lock (struct bgp *); extern void bgp_lock(struct bgp *);
extern void bgp_unlock (struct bgp *); extern void bgp_unlock(struct bgp *);
extern void bgp_router_id_zebra_bump (vrf_id_t, const struct prefix*); extern void bgp_router_id_zebra_bump(vrf_id_t, const struct prefix *);
extern int bgp_router_id_static_set (struct bgp *, struct in_addr); extern int bgp_router_id_static_set(struct bgp *, struct in_addr);
extern int bgp_cluster_id_set (struct bgp *, struct in_addr *); extern int bgp_cluster_id_set(struct bgp *, struct in_addr *);
extern int bgp_cluster_id_unset (struct bgp *); extern int bgp_cluster_id_unset(struct bgp *);
extern int bgp_confederation_id_set (struct bgp *, as_t); extern int bgp_confederation_id_set(struct bgp *, as_t);
extern int bgp_confederation_id_unset (struct bgp *); extern int bgp_confederation_id_unset(struct bgp *);
extern int bgp_confederation_peers_check (struct bgp *, as_t); 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,
extern int bgp_timers_unset (struct bgp *); u_int32_t holdtime);
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);
extern int bgp_default_local_preference_unset (struct bgp *); extern int bgp_default_local_preference_unset(struct bgp *);
extern int bgp_default_subgroup_pkt_queue_max_set (struct bgp *bgp, u_int32_t); extern int bgp_default_subgroup_pkt_queue_max_set(struct bgp *bgp, u_int32_t);
extern int bgp_default_subgroup_pkt_queue_max_unset (struct bgp *bgp); extern int bgp_default_subgroup_pkt_queue_max_unset(struct bgp *bgp);
extern int bgp_listen_limit_set (struct bgp *, int); extern int bgp_listen_limit_set(struct bgp *, int);
extern int bgp_listen_limit_unset (struct bgp *); extern int bgp_listen_limit_unset(struct bgp *);
extern int bgp_update_delay_active (struct bgp *); extern int bgp_update_delay_active(struct bgp *);
extern int bgp_update_delay_configured (struct bgp *); extern int bgp_update_delay_configured(struct bgp *);
extern void peer_as_change (struct peer *, as_t, int); extern void peer_as_change(struct peer *, as_t, int);
extern int peer_remote_as (struct bgp *, union sockunion *,const char *, as_t *, extern int peer_remote_as(struct bgp *, union sockunion *, const char *, as_t *,
int, afi_t, safi_t); int, afi_t, safi_t);
extern int peer_group_remote_as (struct bgp *, const char *, as_t *, int); extern int peer_group_remote_as(struct bgp *, const char *, as_t *, int);
extern int peer_delete (struct peer *peer); extern int peer_delete(struct peer *peer);
extern int peer_group_delete (struct peer_group *); extern int peer_group_delete(struct peer_group *);
extern int peer_group_remote_as_delete (struct peer_group *); extern int peer_group_remote_as_delete(struct peer_group *);
extern int peer_group_listen_range_add(struct peer_group *, struct prefix *); extern int peer_group_listen_range_add(struct peer_group *, struct prefix *);
extern int peer_activate (struct peer *, afi_t, safi_t); extern int peer_activate(struct peer *, afi_t, safi_t);
extern int peer_deactivate (struct peer *, afi_t, safi_t); extern int peer_deactivate(struct peer *, afi_t, safi_t);
extern int peer_afc_set (struct peer *, afi_t, safi_t, int); extern int peer_afc_set(struct peer *, afi_t, safi_t, int);
extern int peer_group_bind (struct bgp *, union sockunion *, struct peer *, extern int peer_group_bind(struct bgp *, union sockunion *, struct peer *,
struct peer_group *, as_t *); struct peer_group *, as_t *);
extern int peer_group_unbind (struct bgp *, struct peer *, struct peer_group *); extern int peer_group_unbind(struct bgp *, struct peer *, struct peer_group *);
extern int peer_flag_set (struct peer *, u_int32_t); extern int peer_flag_set(struct peer *, u_int32_t);
extern int peer_flag_unset (struct peer *, u_int32_t); extern int peer_flag_unset(struct peer *, u_int32_t);
extern int peer_af_flag_set (struct peer *, afi_t, safi_t, u_int32_t); extern int peer_af_flag_set(struct peer *, afi_t, safi_t, u_int32_t);
extern int peer_af_flag_unset (struct peer *, afi_t, safi_t, u_int32_t); extern int peer_af_flag_unset(struct peer *, afi_t, safi_t, u_int32_t);
extern int peer_af_flag_check (struct peer *, afi_t, safi_t, u_int32_t); extern int peer_af_flag_check(struct peer *, afi_t, safi_t, u_int32_t);
extern int peer_ebgp_multihop_set (struct peer *, int); extern int peer_ebgp_multihop_set(struct peer *, int);
extern int peer_ebgp_multihop_unset (struct peer *); extern int peer_ebgp_multihop_unset(struct peer *);
extern int is_ebgp_multihop_configured (struct peer *peer); extern int is_ebgp_multihop_configured(struct peer *peer);
extern int peer_description_set (struct peer *, const char *); extern int peer_description_set(struct peer *, const char *);
extern int peer_description_unset (struct peer *); extern int peer_description_unset(struct peer *);
extern int peer_update_source_if_set (struct peer *, const char *); 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,
extern int peer_default_originate_unset (struct peer *, afi_t, safi_t); const char *);
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);
extern int peer_port_unset (struct peer *); 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,
extern int peer_timers_unset (struct peer *); u_int32_t holdtime);
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);
extern int peer_timers_connect_unset (struct peer *); extern int peer_timers_connect_unset(struct peer *);
extern int peer_advertise_interval_set (struct peer *, u_int32_t); extern int peer_advertise_interval_set(struct peer *, u_int32_t);
extern int peer_advertise_interval_unset (struct peer *); extern int peer_advertise_interval_unset(struct peer *);
extern void peer_interface_set (struct peer *, const char *); extern void peer_interface_set(struct peer *, const char *);
extern void peer_interface_unset (struct peer *); extern void peer_interface_unset(struct peer *);
extern int peer_distribute_set (struct peer *, afi_t, safi_t, int, const char *); extern int peer_distribute_set(struct peer *, afi_t, safi_t, int, const char *);
extern int peer_distribute_unset (struct peer *, afi_t, safi_t, int); extern int peer_distribute_unset(struct peer *, afi_t, safi_t, int);
extern int peer_allowas_in_set (struct peer *, afi_t, safi_t, int, int); extern int peer_allowas_in_set(struct peer *, afi_t, safi_t, int, int);
extern int peer_allowas_in_unset (struct peer *, afi_t, safi_t); 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,
extern int peer_prefix_list_unset (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_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 *);
extern int peer_aslist_unset (struct peer *,afi_t, safi_t, int); extern int peer_aslist_unset(struct peer *, afi_t, safi_t, int);
extern int peer_route_map_set (struct peer *, afi_t, safi_t, int, const char *); extern int peer_route_map_set(struct peer *, afi_t, safi_t, int, const char *);
extern int peer_route_map_unset (struct peer *, afi_t, safi_t, int); extern int peer_route_map_unset(struct peer *, afi_t, safi_t, int);
extern int peer_unsuppress_map_set (struct peer *, afi_t, safi_t, const char *); extern int peer_unsuppress_map_set(struct peer *, afi_t, safi_t, const char *);
extern int peer_password_set (struct peer *, const char *); extern int peer_password_set(struct peer *, const char *);
extern int peer_password_unset (struct peer *); 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,
extern int peer_maximum_prefix_unset (struct peer *, afi_t, safi_t); u_char, int, u_int16_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 **);
extern int peer_clear_soft (struct peer *, afi_t, safi_t, enum bgp_clear_type); extern int peer_clear_soft(struct peer *, afi_t, safi_t, enum bgp_clear_type);
extern int peer_ttl_security_hops_set (struct peer *, int); extern int peer_ttl_security_hops_set(struct peer *, int);
extern int peer_ttl_security_hops_unset (struct peer *); extern int peer_ttl_security_hops_unset(struct peer *);
extern int peer_tx_shutdown_message_set (struct peer *, const char *msg); extern int peer_tx_shutdown_message_set(struct peer *, const char *msg);
extern int peer_tx_shutdown_message_unset (struct peer *); extern int peer_tx_shutdown_message_unset(struct peer *);
extern int bgp_route_map_update_timer (struct thread *thread); extern int bgp_route_map_update_timer(struct thread *thread);
extern void bgp_route_map_terminate(void); 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);
extern struct peer_af * peer_af_find (struct peer *, afi_t, safi_t); extern struct peer_af *peer_af_find(struct peer *, afi_t, safi_t);
extern int peer_af_delete (struct peer *, afi_t, safi_t); 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,85 +1455,76 @@ 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;
return 0; return 0;
} }
/* 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;
if (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) if (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
vrf = vrf_lookup_by_id (VRF_DEFAULT); vrf = vrf_lookup_by_id(VRF_DEFAULT);
else if (bgp->inst_type == BGP_INSTANCE_TYPE_VRF) else if (bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
vrf = vrf_lookup_by_name (bgp->name); vrf = vrf_lookup_by_name(bgp->name);
else else
vrf = NULL; vrf = NULL;
@ -1531,32 +1532,28 @@ 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);
} }
bgp->vrf_id = VRF_UNKNOWN; bgp->vrf_id = VRF_UNKNOWN;
} }
extern void bgp_update_redist_vrf_bitmaps (struct bgp*, vrf_id_t); extern void bgp_update_redist_vrf_bitmaps(struct bgp *, vrf_id_t);
/* For benefit of rfapi */ /* For benefit of rfapi */
extern struct peer * peer_new (struct bgp *bgp); extern struct peer *peer_new(struct bgp *bgp);
#endif /* _QUAGGA_BGPD_H */ #endif /* _QUAGGA_BGPD_H */

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

@ -32,43 +32,38 @@
#include "bgpd/bgp_encap_types.h" #include "bgpd/bgp_encap_types.h"
/* probably ought to have a field-specific define in config.h */ /* probably ought to have a field-specific define in config.h */
# ifndef s6_addr32 /* for solaris/bsd */ #ifndef s6_addr32 /* for solaris/bsd */
# ifdef SOLARIS_IPV6 #ifdef SOLARIS_IPV6
# define s6_addr32 _S6_un._S6_u32 # define s6_addr32 _S6_un._S6_u32
# else #else
# define s6_addr32 __u6_addr.__u6_addr32 # define s6_addr32 __u6_addr.__u6_addr32
# endif #endif
# endif #endif
#define RFAPI_V4_ADDR 0x04 #define RFAPI_V4_ADDR 0x04
#define RFAPI_V6_ADDR 0x06 #define RFAPI_V6_ADDR 0x06
#define RFAPI_SHOW_STR "VNC information\n" #define RFAPI_SHOW_STR "VNC information\n"
struct rfapi_ip_addr struct rfapi_ip_addr {
{
uint8_t addr_family; /* AF_INET | AF_INET6 */ uint8_t addr_family; /* AF_INET | AF_INET6 */
union union {
{
struct in_addr v4; /* in network order */ struct 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;
@ -211,7 +200,7 @@ typedef void *rfapi_handle;
* rfapi_open() * rfapi_open()
* *
*------------------------------------------*/ *------------------------------------------*/
typedef void (rfapi_response_cb_t) (struct rfapi_next_hop_entry * next_hops, typedef void(rfapi_response_cb_t)(struct rfapi_next_hop_entry *next_hops,
void *userdata); void *userdata);
/*------------------------------------------ /*------------------------------------------
@ -228,7 +217,7 @@ typedef void (rfapi_response_cb_t) (struct rfapi_next_hop_entry * next_hops,
* ESTALE handle invalidated by configuration change * ESTALE handle invalidated by configuration change
* *
*------------------------------------------*/ *------------------------------------------*/
typedef void (rfapi_nve_close_cb_t) (rfapi_handle pHandle, int reason); typedef void(rfapi_nve_close_cb_t)(rfapi_handle pHandle, int reason);
/*------------------------------------------ /*------------------------------------------
* rfp_cfg_write_cb_t (callback typedef) * rfp_cfg_write_cb_t (callback typedef)
@ -247,7 +236,7 @@ typedef void (rfapi_nve_close_cb_t) (rfapi_handle pHandle, int reason);
* return value: * return value:
* lines written * lines written
--------------------------------------------*/ --------------------------------------------*/
typedef int (rfp_cfg_write_cb_t) (struct vty * vty, void *rfp_start_val); typedef int(rfp_cfg_write_cb_t)(struct vty *vty, void *rfp_start_val);
/*------------------------------------------ /*------------------------------------------
* rfp_cfg_group_write_cb_t (callback typedef) * rfp_cfg_group_write_cb_t (callback typedef)
@ -269,31 +258,26 @@ typedef int (rfp_cfg_write_cb_t) (struct vty * vty, void *rfp_start_val);
* return value: * return value:
* lines written * lines written
--------------------------------------------*/ --------------------------------------------*/
typedef enum typedef enum {
{
RFAPI_RFP_CFG_GROUP_DEFAULT, RFAPI_RFP_CFG_GROUP_DEFAULT,
RFAPI_RFP_CFG_GROUP_NVE, RFAPI_RFP_CFG_GROUP_NVE,
RFAPI_RFP_CFG_GROUP_L2 RFAPI_RFP_CFG_GROUP_L2
} rfapi_rfp_cfg_group_type; } rfapi_rfp_cfg_group_type;
typedef int (rfp_cfg_group_write_cb_t) (struct vty * vty, typedef int(rfp_cfg_group_write_cb_t)(struct vty *vty, void *rfp_start_val,
void *rfp_start_val,
rfapi_rfp_cfg_group_type type, rfapi_rfp_cfg_group_type type,
const char *name, 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,50 +101,47 @@ 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);
skiplist_free (ap->ip0_by_ether); skiplist_free(ap->ip0_by_ether);
skiplist_free (ap->by_lifetime); skiplist_free(ap->by_lifetime);
ap->ipN_by_prefix = NULL; ap->ipN_by_prefix = NULL;
ap->ip0_by_ether = NULL; ap->ip0_by_ether = NULL;
ap->by_lifetime = NULL; ap->by_lifetime = NULL;
} }
int int rfapiApCount(struct rfapi_descriptor *rfd)
rfapiApCount (struct rfapi_descriptor *rfd)
{ {
if (!rfd->advertised.by_lifetime) if (!rfd->advertised.by_lifetime)
return 0; return 0;
return skiplist_count (rfd->advertised.by_lifetime); return skiplist_count(rfd->advertised.by_lifetime);
} }
int int rfapiApCountAll(struct bgp *bgp)
rfapiApCountAll (struct bgp *bgp)
{ {
struct rfapi *h; struct rfapi *h;
struct listnode *node; struct listnode *node;
@ -153,34 +149,28 @@ 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);
} }
} }
return total; return total;
} }
void void rfapiApReadvertiseAll(struct bgp *bgp, struct rfapi_descriptor *rfd)
rfapiApReadvertiseAll (struct bgp *bgp, struct rfapi_descriptor *rfd)
{ {
struct rfapi_adb *adb; struct rfapi_adb *adb;
void *cursor = NULL; void *cursor = NULL;
int rc; int rc;
for (rc = for (rc = skiplist_next(rfd->advertised.by_lifetime, NULL,
skiplist_next (rfd->advertised.by_lifetime, NULL, (void **) &adb, (void **)&adb, &cursor);
&cursor); rc == 0; rc == 0; rc = skiplist_next(rfd->advertised.by_lifetime, NULL,
rc = (void **)&adb, &cursor)) {
skiplist_next (rfd->advertised.by_lifetime, NULL, (void **) &adb,
&cursor))
{
struct prefix_rd prd; struct prefix_rd prd;
uint32_t local_pref = rfp_cost_to_localpref (adb->cost); uint32_t local_pref = rfp_cost_to_localpref(adb->cost);
prd = rfd->rd; prd = rfd->rd;
prd.family = AF_UNSPEC; prd.family = AF_UNSPEC;
@ -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;
@ -425,13 +391,13 @@ rfapiApAdjustLifetimeStats (
min = lt; min = lt;
} }
cursor = NULL; cursor = NULL;
for (rc = skiplist_next (rfd->advertised.ip0_by_ether, for (rc = skiplist_next(rfd->advertised.ip0_by_ether,
(void **) &rk, (void **) &adb, (void **)&rk, (void **)&adb,
&cursor); !rc; &cursor);
rc = !rc;
skiplist_next (rfd->advertised.ip0_by_ether, (void **) &rk, rc = skiplist_next(rfd->advertised.ip0_by_ether,
(void **) &adb, &cursor)) (void **)&rk, (void **)&adb,
{ &cursor)) {
uint32_t lt = adb->lifetime; uint32_t lt = adb->lifetime;
@ -453,7 +419,7 @@ rfapiApAdjustLifetimeStats (
rfd->min_prefix_lifetime = min; rfd->min_prefix_lifetime = min;
} }
vnc_zlog_debug_verbose ("%s: returning advertise=%d, min=%d, max=%d", vnc_zlog_debug_verbose("%s: returning advertise=%d, min=%d, max=%d",
__func__, advertise, rfd->min_prefix_lifetime, __func__, advertise, rfd->min_prefix_lifetime,
rfd->max_prefix_lifetime); rfd->max_prefix_lifetime);
@ -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,65 +444,55 @@ 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,
skiplist_insert (rfd->advertised.ip0_by_ether, &adb->u.key, &adb->u.key, adb);
adb); } else {
} skiplist_insert(rfd->advertised.ipN_by_prefix,
else &adb->u.key, adb);
{
skiplist_insert (rfd->advertised.ipN_by_prefix, &adb->u.key,
adb);
} }
skiplist_insert (rfd->advertised.by_lifetime, adb, adb); skiplist_insert(rfd->advertised.by_lifetime, adb, adb);
} } else {
else
{
old_lifetime = adb->lifetime; 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;
if (l2o) if (l2o)
adb->l2o = *l2o; adb->l2o = *l2o;
else else
memset (&adb->l2o, 0, sizeof (struct rfapi_l2address_option)); memset(&adb->l2o, 0, sizeof(struct rfapi_l2address_option));
if (rfapiApAdjustLifetimeStats if (rfapiApAdjustLifetimeStats(rfd, (rc ? NULL : &old_lifetime),
(rfd, (rc ? NULL : &old_lifetime), &lifetime)) &lifetime))
return 1; return 1;
return 0; return 0;
@ -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,49 +517,39 @@ 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 {
rc = skiplist_delete(rfd->advertised.ipN_by_prefix, &rk, NULL);
} }
else assert(!rc);
{
rc = skiplist_delete (rfd->advertised.ipN_by_prefix, &rk, NULL);
}
assert (!rc);
rc = skiplist_delete (rfd->advertised.by_lifetime, adb, NULL); rc = skiplist_delete(rfd->advertised.by_lifetime, adb, NULL);
assert (!rc); assert(!rc);
rfapiAdbFree (adb); rfapiAdbFree(adb);
if (rfapiApAdjustLifetimeStats (rfd, &old_lifetime, NULL)) if (rfapiApAdjustLifetimeStats(rfd, &old_lifetime, NULL)) {
{
if (advertise_tunnel) if (advertise_tunnel)
*advertise_tunnel = 1; *advertise_tunnel = 1;
} }

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

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

View File

@ -36,15 +36,14 @@
#include "bgpd/rfapi/vnc_debug.h" #include "bgpd/rfapi/vnc_debug.h"
void * void *rfapi_create_generic(struct rfapi_ip_addr *vn, struct rfapi_ip_addr *un)
rfapi_create_generic (struct rfapi_ip_addr *vn, struct rfapi_ip_addr *un)
{ {
struct rfapi_descriptor *rfd; struct rfapi_descriptor *rfd;
rfd = XCALLOC (MTYPE_RFAPI_DESC, sizeof (struct rfapi_descriptor)); rfd = XCALLOC(MTYPE_RFAPI_DESC, sizeof(struct rfapi_descriptor));
vnc_zlog_debug_verbose ("%s: rfd=%p", __func__, rfd); vnc_zlog_debug_verbose("%s: rfd=%p", __func__, rfd);
rfd->vn_addr = *vn; rfd->vn_addr = *vn;
rfd->un_addr = *un; rfd->un_addr = *un;
return (void *) rfd; return (void *)rfd;
} }
/*------------------------------------------ /*------------------------------------------
@ -60,12 +59,11 @@ rfapi_create_generic (struct rfapi_ip_addr *vn, struct rfapi_ip_addr *un)
* return value: * return value:
* *
*------------------------------------------*/ *------------------------------------------*/
void void rfapi_free_generic(void *grfd)
rfapi_free_generic (void *grfd)
{ {
struct rfapi_descriptor *rfd; struct rfapi_descriptor *rfd;
rfd = (struct rfapi_descriptor *) grfd; rfd = (struct rfapi_descriptor *)grfd;
XFREE (MTYPE_RFAPI_DESC, rfd); XFREE(MTYPE_RFAPI_DESC, rfd);
} }
@ -84,22 +82,20 @@ rfapi_free_generic (void *grfd)
* 0 Mismatch * 0 Mismatch
* 1 Match * 1 Match
*------------------------------------------*/ *------------------------------------------*/
int int rfapi_compare_rfds(void *rfd1, void *rfd2)
rfapi_compare_rfds (void *rfd1, void *rfd2)
{ {
struct rfapi_descriptor *rrfd1, *rrfd2; struct rfapi_descriptor *rrfd1, *rrfd2;
int match = 0; int match = 0;
rrfd1 = (struct rfapi_descriptor *) rfd1; rrfd1 = (struct rfapi_descriptor *)rfd1;
rrfd2 = (struct rfapi_descriptor *) rfd2; rrfd2 = (struct rfapi_descriptor *)rfd2;
if (rrfd1->vn_addr.addr_family == rrfd2->vn_addr.addr_family) if (rrfd1->vn_addr.addr_family == rrfd2->vn_addr.addr_family) {
{
if (rrfd1->vn_addr.addr_family == AF_INET) if (rrfd1->vn_addr.addr_family == AF_INET)
match = IPV4_ADDR_SAME (&(rrfd1->vn_addr.addr.v4), match = IPV4_ADDR_SAME(&(rrfd1->vn_addr.addr.v4),
&(rrfd2->vn_addr.addr.v4)); &(rrfd2->vn_addr.addr.v4));
else else
match = IPV6_ADDR_SAME (&(rrfd1->vn_addr.addr.v6), match = IPV6_ADDR_SAME(&(rrfd1->vn_addr.addr.v6),
&(rrfd2->vn_addr.addr.v6)); &(rrfd2->vn_addr.addr.v6));
} }
@ -114,17 +110,16 @@ 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
*/ */
if (rrfd1->un_addr.addr_family == AF_INET) if (rrfd1->un_addr.addr_family == AF_INET)
match = IPV4_ADDR_SAME (&(rrfd1->un_addr.addr.v4), match = IPV4_ADDR_SAME(&(rrfd1->un_addr.addr.v4),
&(rrfd2->un_addr.addr.v4)); &(rrfd2->un_addr.addr.v4));
else else
match = IPV6_ADDR_SAME (&(rrfd1->un_addr.addr.v6), match = IPV6_ADDR_SAME(&(rrfd1->un_addr.addr.v6),
&(rrfd2->un_addr.addr.v6)); &(rrfd2->un_addr.addr.v6));
} }
return match; return match;

View File

@ -19,7 +19,7 @@
*/ */
extern void *rfapi_create_generic (struct rfapi_ip_addr *vn, extern void *rfapi_create_generic(struct rfapi_ip_addr *vn,
struct rfapi_ip_addr *un); struct rfapi_ip_addr *un);
/*------------------------------------------ /*------------------------------------------
@ -35,4 +35,4 @@ extern void *rfapi_create_generic (struct rfapi_ip_addr *vn,
* return value: * return value:
* *
*------------------------------------------*/ *------------------------------------------*/
extern void rfapi_free_generic (void *grfd); extern void rfapi_free_generic(void *grfd);

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;
@ -48,85 +46,84 @@ rfapi_add_endpoint_address_to_subtlv (
subtlv->ip_address.v4 = ea->addr.v4; subtlv->ip_address.v4 = ea->addr.v4;
else else
subtlv->ip_address.v6 = ea->addr.v6; subtlv->ip_address.v6 = ea->addr.v6;
subtlv->as4 = htonl (bgp->as); subtlv->as4 = htonl(bgp->as);
} }
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:
_RTTO_MAYBE_ADD_ENDPOINT_ADDRESS (gre); _RTTO_MAYBE_ADD_ENDPOINT_ADDRESS(gre);
bgp_encap_type_gre_to_tlv (&tto->bgpinfo.gre, attr); bgp_encap_type_gre_to_tlv(&tto->bgpinfo.gre, attr);
break; break;
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:
_RTTO_MAYBE_ADD_ENDPOINT_ADDRESS (ip_ip); _RTTO_MAYBE_ADD_ENDPOINT_ADDRESS(ip_ip);
bgp_encap_type_ip_in_ip_to_tlv (&tto->bgpinfo.ip_ip, attr); bgp_encap_type_ip_in_ip_to_tlv(&tto->bgpinfo.ip_ip, attr);
break; break;
case BGP_ENCAP_TYPE_VXLAN: case BGP_ENCAP_TYPE_VXLAN:
_RTTO_MAYBE_ADD_ENDPOINT_ADDRESS (vxlan); _RTTO_MAYBE_ADD_ENDPOINT_ADDRESS(vxlan);
bgp_encap_type_vxlan_to_tlv (&tto->bgpinfo.vxlan, attr); bgp_encap_type_vxlan_to_tlv(&tto->bgpinfo.vxlan, attr);
break; break;
case BGP_ENCAP_TYPE_NVGRE: case BGP_ENCAP_TYPE_NVGRE:
_RTTO_MAYBE_ADD_ENDPOINT_ADDRESS (nvgre); _RTTO_MAYBE_ADD_ENDPOINT_ADDRESS(nvgre);
bgp_encap_type_nvgre_to_tlv (&tto->bgpinfo.nvgre, attr); bgp_encap_type_nvgre_to_tlv(&tto->bgpinfo.nvgre, attr);
break; break;
case BGP_ENCAP_TYPE_MPLS: case BGP_ENCAP_TYPE_MPLS:
@ -134,128 +131,123 @@ rfapi_tunneltype_option_to_tlv (
break; break;
case BGP_ENCAP_TYPE_MPLS_IN_GRE: case BGP_ENCAP_TYPE_MPLS_IN_GRE:
_RTTO_MAYBE_ADD_ENDPOINT_ADDRESS (mpls_gre); _RTTO_MAYBE_ADD_ENDPOINT_ADDRESS(mpls_gre);
bgp_encap_type_mpls_in_gre_to_tlv (&tto->bgpinfo.mpls_gre, attr); bgp_encap_type_mpls_in_gre_to_tlv(&tto->bgpinfo.mpls_gre, attr);
break; break;
case BGP_ENCAP_TYPE_VXLAN_GPE: case BGP_ENCAP_TYPE_VXLAN_GPE:
_RTTO_MAYBE_ADD_ENDPOINT_ADDRESS (vxlan_gpe); _RTTO_MAYBE_ADD_ENDPOINT_ADDRESS(vxlan_gpe);
bgp_encap_type_vxlan_gpe_to_tlv (&tto->bgpinfo.vxlan_gpe, attr); bgp_encap_type_vxlan_gpe_to_tlv(&tto->bgpinfo.vxlan_gpe, attr);
break; break;
case BGP_ENCAP_TYPE_MPLS_IN_UDP: case BGP_ENCAP_TYPE_MPLS_IN_UDP:
_RTTO_MAYBE_ADD_ENDPOINT_ADDRESS (mpls_udp); _RTTO_MAYBE_ADD_ENDPOINT_ADDRESS(mpls_udp);
bgp_encap_type_mpls_in_udp_to_tlv (&tto->bgpinfo.mpls_udp, attr); bgp_encap_type_mpls_in_udp_to_tlv(&tto->bgpinfo.mpls_udp, attr);
break; break;
case BGP_ENCAP_TYPE_PBB: case BGP_ENCAP_TYPE_PBB:
_RTTO_MAYBE_ADD_ENDPOINT_ADDRESS (pbb); _RTTO_MAYBE_ADD_ENDPOINT_ADDRESS(pbb);
bgp_encap_type_pbb_to_tlv (&tto->bgpinfo.pbb, attr); bgp_encap_type_pbb_to_tlv(&tto->bgpinfo.pbb, attr);
break; break;
default: default:
assert (0); assert(0);
} }
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:
rc = tlv_to_bgp_encap_type_gre (stlv, &tto->bgpinfo.gre); rc = tlv_to_bgp_encap_type_gre(stlv, &tto->bgpinfo.gre);
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:
rc = tlv_to_bgp_encap_type_ip_in_ip (stlv, &tto->bgpinfo.ip_ip); rc = tlv_to_bgp_encap_type_ip_in_ip(stlv, &tto->bgpinfo.ip_ip);
break; break;
case BGP_ENCAP_TYPE_VXLAN: case BGP_ENCAP_TYPE_VXLAN:
rc = tlv_to_bgp_encap_type_vxlan (stlv, &tto->bgpinfo.vxlan); rc = tlv_to_bgp_encap_type_vxlan(stlv, &tto->bgpinfo.vxlan);
break; break;
case BGP_ENCAP_TYPE_NVGRE: case BGP_ENCAP_TYPE_NVGRE:
rc = tlv_to_bgp_encap_type_nvgre (stlv, &tto->bgpinfo.nvgre); rc = tlv_to_bgp_encap_type_nvgre(stlv, &tto->bgpinfo.nvgre);
break; break;
case BGP_ENCAP_TYPE_MPLS: case BGP_ENCAP_TYPE_MPLS:
rc = tlv_to_bgp_encap_type_mpls (stlv, &tto->bgpinfo.mpls); rc = tlv_to_bgp_encap_type_mpls(stlv, &tto->bgpinfo.mpls);
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:
rc = tlv_to_bgp_encap_type_pbb (stlv, &tto->bgpinfo.pbb); rc = tlv_to_bgp_encap_type_pbb(stlv, &tto->bgpinfo.pbb);
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;
} }
return uo; return uo;
@ -265,149 +257,129 @@ 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 *, ...);
struct vty *vty; struct vty *vty;
void *out; void *out;
const char *vty_newline; const char *vty_newline;
if (rfapiStream2Vty (stream, &fp, &vty, &out, &vty_newline) == 0) if (rfapiStream2Vty(stream, &fp, &vty, &out, &vty_newline) == 0)
return; return;
if (!st) if (!st)
return; return;
fp (out, "%*s%s%s", column_offset, "", "SubTLV: Encap(L2TPv3 over IP)", fp(out, "%*s%s%s", column_offset, "", "SubTLV: 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);
fp (out, "%*s Cookie: (length %d)%s", column_offset, "", st->cookie_length,
vty_newline); vty_newline);
fp(out, "%*s Cookie: (length %d)%s", column_offset, "",
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 *, ...);
struct vty *vty; struct vty *vty;
void *out; void *out;
const char *vty_newline; const char *vty_newline;
if (rfapiStream2Vty (stream, &fp, &vty, &out, &vty_newline) == 0) if (rfapiStream2Vty(stream, &fp, &vty, &out, &vty_newline) == 0)
return; return;
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)",
fp (out, "%*s GRE key: %d (0x%x)%s", column_offset, "", st->gre_key, vty_newline);
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 *, ...);
struct vty *vty; struct vty *vty;
void *out; void *out;
const char *vty_newline; const char *vty_newline;
if (rfapiStream2Vty (stream, &fp, &vty, &out, &vty_newline) == 0) if (rfapiStream2Vty(stream, &fp, &vty, &out, &vty_newline) == 0)
return; return;
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 *, ...);
struct vty *vty; struct vty *vty;
void *out; void *out;
const char *vty_newline; const char *vty_newline;
if (rfapiStream2Vty (stream, &fp, &vty, &out, &vty_newline) == 0) if (rfapiStream2Vty(stream, &fp, &vty, &out, &vty_newline) == 0)
return; return;
if (!st) if (!st)
return; return;
fp (out, "%*s%s%s", column_offset, "", "SubTLV: Encap(Proto Type)", fp(out, "%*s%s%s", column_offset, "", "SubTLV: Encap(Proto Type)",
vty_newline);
fp (out, "%*s Proto %d (0x%x)%s", column_offset, "", st->proto, st->proto,
vty_newline); vty_newline);
fp(out, "%*s Proto %d (0x%x)%s", column_offset, "", st->proto,
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 *, ...);
struct vty *vty; struct vty *vty;
void *out; void *out;
const char *vty_newline; const char *vty_newline;
if (rfapiStream2Vty (stream, &fp, &vty, &out, &vty_newline) == 0) if (rfapiStream2Vty(stream, &fp, &vty, &out, &vty_newline) == 0)
return; return;
if (!st) if (!st)
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 *, ...);
struct vty *vty; struct vty *vty;
void *out; void *out;
const char *vty_newline; const char *vty_newline;
if (rfapiStream2Vty (stream, &fp, &vty, &out, &vty_newline) == 0) if (rfapiStream2Vty(stream, &fp, &vty, &out, &vty_newline) == 0)
return; return;
if (!st) if (!st)
return; return;
fp (out, "%*s%s%s", column_offset, "", "SubTLV: IPSEC TA", vty_newline); fp(out, "%*s%s%s", column_offset, "", "SubTLV: IPSEC TA", vty_newline);
fp (out, "%*s Authenticator Type: %d (0x%x)", column_offset, "", fp(out, "%*s Authenticator Type: %d (0x%x)", column_offset, "",
st->authenticator_type, st->authenticator_type, vty_newline); st->authenticator_type, st->authenticator_type, vty_newline);
fp (out, "%*s Authenticator: (length %d)", column_offset, "", fp(out, "%*s Authenticator: (length %d)", column_offset, "",
st->authenticator_length, vty_newline); st->authenticator_length, vty_newline);
} }
@ -416,396 +388,358 @@ 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";
int (*fp) (void *, const char *, ...); int (*fp)(void *, const char *, ...);
struct vty *vty; struct vty *vty;
void *out; void *out;
const char *vty_newline; const char *vty_newline;
if (rfapiStream2Vty (stream, &fp, &vty, &out, &vty_newline) == 0) if (rfapiStream2Vty(stream, &fp, &vty, &out, &vty_newline) == 0)
return; return;
if (!bet) if (!bet)
return; return;
fp (out, "%*sTEA type %s%s", column_offset, "", type, vty_newline); fp(out, "%*sTEA type %s%s", column_offset, "", type, vty_newline);
subtlv_print_encap_l2tpv3_over_ip (stream, column_offset + 2, subtlv_print_encap_l2tpv3_over_ip(stream, column_offset + 2,
&bet->st_encap); &bet->st_encap);
subtlv_print_proto_type (stream, column_offset + 2, &bet->st_proto); subtlv_print_proto_type(stream, column_offset + 2, &bet->st_proto);
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";
int (*fp) (void *, const char *, ...); int (*fp)(void *, const char *, ...);
struct vty *vty; struct vty *vty;
void *out; void *out;
const char *vty_newline; const char *vty_newline;
if (rfapiStream2Vty (stream, &fp, &vty, &out, &vty_newline) == 0) if (rfapiStream2Vty(stream, &fp, &vty, &out, &vty_newline) == 0)
return; return;
if (!bet) if (!bet)
return; return;
fp (out, "%*sTEA type %s%s", column_offset, "", type, vty_newline); fp(out, "%*sTEA type %s%s", column_offset, "", type, vty_newline);
subtlv_print_encap_gre (stream, column_offset + 2, &bet->st_encap); subtlv_print_encap_gre(stream, column_offset + 2, &bet->st_encap);
subtlv_print_proto_type (stream, column_offset + 2, &bet->st_proto); subtlv_print_proto_type(stream, column_offset + 2, &bet->st_proto);
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";
int (*fp) (void *, const char *, ...); int (*fp)(void *, const char *, ...);
struct vty *vty; struct vty *vty;
void *out; void *out;
const char *vty_newline; const char *vty_newline;
if (rfapiStream2Vty (stream, &fp, &vty, &out, &vty_newline) == 0) if (rfapiStream2Vty(stream, &fp, &vty, &out, &vty_newline) == 0)
return; return;
if (!bet) if (!bet)
return; return;
fp (out, "%*sTEA type %s%s", column_offset, "", type, vty_newline); fp(out, "%*sTEA type %s%s", column_offset, "", type, vty_newline);
subtlv_print_proto_type (stream, column_offset + 2, &bet->st_proto); subtlv_print_proto_type(stream, column_offset + 2, &bet->st_proto);
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";
int (*fp) (void *, const char *, ...); int (*fp)(void *, const char *, ...);
struct vty *vty; struct vty *vty;
void *out; void *out;
const char *vty_newline; const char *vty_newline;
if (rfapiStream2Vty (stream, &fp, &vty, &out, &vty_newline) == 0) if (rfapiStream2Vty(stream, &fp, &vty, &out, &vty_newline) == 0)
return; return;
if (!bet) if (!bet)
return; return;
fp (out, "%*sTEA type %s%s", column_offset, "", type, vty_newline); fp(out, "%*sTEA type %s%s", column_offset, "", type, vty_newline);
/* 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";
int (*fp) (void *, const char *, ...); int (*fp)(void *, const char *, ...);
struct vty *vty; struct vty *vty;
void *out; void *out;
const char *vty_newline; const char *vty_newline;
if (rfapiStream2Vty (stream, &fp, &vty, &out, &vty_newline) == 0) if (rfapiStream2Vty(stream, &fp, &vty, &out, &vty_newline) == 0)
return; return;
if (!bet) if (!bet)
return; return;
fp (out, "%*sTEA type %s%s", column_offset, "", type, vty_newline); fp(out, "%*sTEA type %s%s", column_offset, "", type, vty_newline);
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";
int (*fp) (void *, const char *, ...); int (*fp)(void *, const char *, ...);
struct vty *vty; struct vty *vty;
void *out; void *out;
const char *vty_newline; const char *vty_newline;
if (rfapiStream2Vty (stream, &fp, &vty, &out, &vty_newline) == 0) if (rfapiStream2Vty(stream, &fp, &vty, &out, &vty_newline) == 0)
return; return;
if (!bet) if (!bet)
return; return;
fp (out, "%*sTEA type %s%s", column_offset, "", type, vty_newline); fp(out, "%*sTEA type %s%s", column_offset, "", type, vty_newline);
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";
int (*fp) (void *, const char *, ...); int (*fp)(void *, const char *, ...);
struct vty *vty; struct vty *vty;
void *out; void *out;
const char *vty_newline; const char *vty_newline;
if (rfapiStream2Vty (stream, &fp, &vty, &out, &vty_newline) == 0) if (rfapiStream2Vty(stream, &fp, &vty, &out, &vty_newline) == 0)
return; return;
if (!bet) if (!bet)
return; return;
fp (out, "%*sTEA type %s%s", column_offset, "", type, vty_newline); fp(out, "%*sTEA type %s%s", column_offset, "", type, vty_newline);
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_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";
int (*fp) (void *, const char *, ...); int (*fp)(void *, const char *, ...);
struct vty *vty; struct vty *vty;
void *out; void *out;
const char *vty_newline; const char *vty_newline;
if (rfapiStream2Vty (stream, &fp, &vty, &out, &vty_newline) == 0) if (rfapiStream2Vty(stream, &fp, &vty, &out, &vty_newline) == 0)
return; return;
if (!bet) if (!bet)
return; return;
fp (out, "%*sTEA type %s%s", column_offset, "", type, vty_newline); fp(out, "%*sTEA type %s%s", column_offset, "", type, vty_newline);
subtlv_print_encap_pbb (stream, column_offset + 2, &bet->st_encap); subtlv_print_encap_pbb(stream, column_offset + 2, &bet->st_encap);
} }
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";
int (*fp) (void *, const char *, ...); int (*fp)(void *, const char *, ...);
struct vty *vty; struct vty *vty;
void *out; void *out;
const char *vty_newline; const char *vty_newline;
if (rfapiStream2Vty (stream, &fp, &vty, &out, &vty_newline) == 0) if (rfapiStream2Vty(stream, &fp, &vty, &out, &vty_newline) == 0)
return; return;
if (!bet) if (!bet)
return; return;
fp (out, "%*sTEA type %s%s", column_offset, "", type, vty_newline); fp(out, "%*sTEA type %s%s", column_offset, "", type, vty_newline);
/* no subtlvs for this type */ /* no subtlvs for this type */
} }
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";
int (*fp) (void *, const char *, ...); int (*fp)(void *, const char *, ...);
struct vty *vty; struct vty *vty;
void *out; void *out;
const char *vty_newline; const char *vty_newline;
if (rfapiStream2Vty (stream, &fp, &vty, &out, &vty_newline) == 0) if (rfapiStream2Vty(stream, &fp, &vty, &out, &vty_newline) == 0)
return; return;
if (!bet) if (!bet)
return; return;
fp (out, "%*sTEA type %s%s", column_offset, "", type, vty_newline); fp(out, "%*sTEA type %s%s", column_offset, "", type, vty_newline);
/* 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";
int (*fp) (void *, const char *, ...); int (*fp)(void *, const char *, ...);
struct vty *vty; struct vty *vty;
void *out; void *out;
const char *vty_newline; const char *vty_newline;
if (rfapiStream2Vty (stream, &fp, &vty, &out, &vty_newline) == 0) if (rfapiStream2Vty(stream, &fp, &vty, &out, &vty_newline) == 0)
return; return;
if (!bet) if (!bet)
return; return;
fp (out, "%*sTEA type %s%s", column_offset, "", type, vty_newline); fp(out, "%*sTEA type %s%s", column_offset, "", type, vty_newline);
/* 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";
int (*fp) (void *, const char *, ...); int (*fp)(void *, const char *, ...);
struct vty *vty; struct vty *vty;
void *out; void *out;
const char *vty_newline; const char *vty_newline;
if (rfapiStream2Vty (stream, &fp, &vty, &out, &vty_newline) == 0) if (rfapiStream2Vty(stream, &fp, &vty, &out, &vty_newline) == 0)
return; return;
if (!bet) if (!bet)
return; return;
fp (out, "%*sTEA type %s%s", column_offset, "", type, vty_newline); fp(out, "%*sTEA type %s%s", column_offset, "", type, vty_newline);
/* 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";
int (*fp) (void *, const char *, ...); int (*fp)(void *, const char *, ...);
struct vty *vty; struct vty *vty;
void *out; void *out;
const char *vty_newline; const char *vty_newline;
if (rfapiStream2Vty (stream, &fp, &vty, &out, &vty_newline) == 0) if (rfapiStream2Vty(stream, &fp, &vty, &out, &vty_newline) == 0)
return; return;
if (!bet) if (!bet)
return; return;
fp (out, "%*sTEA type %s%s", column_offset, "", type, vty_newline); fp(out, "%*sTEA type %s%s", column_offset, "", type, vty_newline);
/* 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";
int (*fp) (void *, const char *, ...); int (*fp)(void *, const char *, ...);
struct vty *vty; struct vty *vty;
void *out; void *out;
const char *vty_newline; const char *vty_newline;
if (rfapiStream2Vty (stream, &fp, &vty, &out, &vty_newline) == 0) if (rfapiStream2Vty(stream, &fp, &vty, &out, &vty_newline) == 0)
return; return;
if (!bet) if (!bet)
return; return;
fp (out, "%*sTEA type %s%s", column_offset, "", type, vty_newline); fp(out, "%*sTEA type %s%s", column_offset, "", type, vty_newline);
/* 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);
break; break;
case BGP_ENCAP_TYPE_GRE: case BGP_ENCAP_TYPE_GRE:
print_encap_type_gre (stream, column_offset, &tto->bgpinfo.gre); print_encap_type_gre(stream, column_offset, &tto->bgpinfo.gre);
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:
print_encap_type_mpls_in_gre (stream, column_offset, print_encap_type_mpls_in_gre(stream, column_offset,
&tto->bgpinfo.mpls_gre); &tto->bgpinfo.mpls_gre);
break; break;
case BGP_ENCAP_TYPE_VXLAN_GPE: case BGP_ENCAP_TYPE_VXLAN_GPE:
print_encap_type_vxlan_gpe (stream, column_offset, print_encap_type_vxlan_gpe(stream, column_offset,
&tto->bgpinfo.vxlan_gpe); &tto->bgpinfo.vxlan_gpe);
break; break;
case BGP_ENCAP_TYPE_MPLS_IN_UDP: case BGP_ENCAP_TYPE_MPLS_IN_UDP:
print_encap_type_mpls_in_udp (stream, column_offset, print_encap_type_mpls_in_udp(stream, column_offset,
&tto->bgpinfo.mpls_udp); &tto->bgpinfo.mpls_udp);
break; break;
case BGP_ENCAP_TYPE_PBB: case BGP_ENCAP_TYPE_PBB:
print_encap_type_pbb (stream, column_offset, &tto->bgpinfo.pbb); print_encap_type_pbb(stream, column_offset, &tto->bgpinfo.pbb);
break; break;
default: default:
assert (0); assert(0);
} }
} }

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