Merge pull request #14139 from donaldsharp/v6_v4_nexthops

V6 v4 nexthops
This commit is contained in:
Donatas Abraitis 2023-08-06 20:11:19 +03:00 committed by GitHub
commit ceea81be77
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 103 additions and 56 deletions

View File

@ -57,15 +57,17 @@
/* 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' },
{"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' },
{"int_num", required_argument, NULL, 'I'}, { "int_num", required_argument, NULL, 'I' },
{"no_zebra", no_argument, NULL, 'Z'}, { "no_zebra", no_argument, NULL, 'Z' },
{"socket_size", required_argument, NULL, 's'}, { "socket_size", required_argument, NULL, 's' },
{0}}; { "v6-with-v4-nexthops", no_argument, NULL, 'v' },
{ 0 }
};
/* signal definitions */ /* signal definitions */
void sighup(void); void sighup(void);
@ -387,16 +389,16 @@ int main(int argc, char **argv)
addresses->cmp = (int (*)(void *, void *))strcmp; addresses->cmp = (int (*)(void *, void *))strcmp;
frr_preinit(&bgpd_di, argc, argv); frr_preinit(&bgpd_di, argc, argv);
frr_opt_add( frr_opt_add("p:l:SnZe:I:s:" DEPRECATED_OPTIONS, longopts,
"p:l:SnZe:I:s:" DEPRECATED_OPTIONS, longopts, " -p, --bgp_port Set BGP listen port number (0 means do not listen).\n"
" -p, --bgp_port Set BGP listen port number (0 means do not listen).\n" " -l, --listenon Listen on specified address (implies -n)\n"
" -l, --listenon Listen on specified address (implies -n)\n" " -n, --no_kernel Do not install route to kernel.\n"
" -n, --no_kernel Do not install route to kernel.\n" " -Z, --no_zebra Do not communicate with Zebra.\n"
" -Z, --no_zebra Do not communicate with Zebra.\n" " -S, --skip_runas Skip capabilities checks, and changing user and group IDs.\n"
" -S, --skip_runas Skip capabilities checks, and changing user and group IDs.\n" " -e, --ecmp Specify ECMP to use.\n"
" -e, --ecmp Specify ECMP to use.\n" " -I, --int_num Set instance number (label-manager)\n"
" -I, --int_num Set instance number (label-manager)\n" " -s, --socket_size Set BGP peer socket send buffer size\n"
" -s, --socket_size Set BGP peer socket send buffer size\n"); " , --v6-with-v4-nexthop Allow BGP to form v6 neighbors using v4 nexthops\n");
/* Command line argument treatment. */ /* Command line argument treatment. */
while (1) { while (1) {
@ -458,6 +460,9 @@ int main(int argc, char **argv)
case 's': case 's':
buffer_size = atoi(optarg); buffer_size = atoi(optarg);
break; break;
case 'v':
bm->v6_with_v4_nexthops = true;
break;
default: default:
frr_help_exit(1); frr_help_exit(1);
} }

View File

@ -1787,11 +1787,14 @@ static int bgp_open_receive(struct peer *peer, bgp_size_t size)
|| peer->afc_nego[AFI_IP6][SAFI_MULTICAST] || peer->afc_nego[AFI_IP6][SAFI_MULTICAST]
|| peer->afc_nego[AFI_IP6][SAFI_MPLS_VPN] || peer->afc_nego[AFI_IP6][SAFI_MPLS_VPN]
|| peer->afc_nego[AFI_IP6][SAFI_ENCAP]) { || peer->afc_nego[AFI_IP6][SAFI_ENCAP]) {
if (IN6_IS_ADDR_UNSPECIFIED(&peer->nexthop.v6_global)) { if (IN6_IS_ADDR_UNSPECIFIED(&peer->nexthop.v6_global) &&
#if defined(HAVE_CUMULUS) !bm->v6_with_v4_nexthops) {
zlog_warn("%s: No local IPv6 address, BGP routing may not work", flog_err(EC_BGP_SND_FAIL,
peer->host); "%s: No local IPv6 address, and zebra does not support V6 routing with v4 nexthops, BGP routing for V6 will not work",
#endif peer->host);
bgp_notify_send(peer, BGP_NOTIFY_CEASE,
BGP_NOTIFY_SUBCODE_UNSPECIFIC);
return BGP_Stop;
} }
} }
peer->rtt = sockopt_tcp_rtt(peer->fd); peer->rtt = sockopt_tcp_rtt(peer->fd);

View File

@ -3455,6 +3455,11 @@ static bool bgp_zebra_label_manager_connect(void)
return true; return true;
} }
static void bgp_zebra_capabilities(struct zclient_capabilities *cap)
{
bm->v6_with_v4_nexthops = cap->v6_with_v4_nexthop;
}
void bgp_zebra_init(struct event_loop *master, unsigned short instance) void bgp_zebra_init(struct event_loop *master, unsigned short instance)
{ {
struct zclient_options options = zclient_options_default; struct zclient_options options = zclient_options_default;
@ -3470,6 +3475,7 @@ void bgp_zebra_init(struct event_loop *master, unsigned short instance)
array_size(bgp_handlers)); array_size(bgp_handlers));
zclient_init(zclient, ZEBRA_ROUTE_BGP, 0, &bgpd_privs); zclient_init(zclient, ZEBRA_ROUTE_BGP, 0, &bgpd_privs);
zclient->zebra_connected = bgp_zebra_connected; zclient->zebra_connected = bgp_zebra_connected;
zclient->zebra_capabilities = bgp_zebra_capabilities;
zclient->instance = instance; zclient->instance = instance;
/* Initialize special zclient for synchronous message exchanges. */ /* Initialize special zclient for synchronous message exchanges. */

View File

@ -168,6 +168,8 @@ struct bgp_master {
struct event *t_bgp_sync_label_manager; struct event *t_bgp_sync_label_manager;
struct event *t_bgp_start_label_manager; struct event *t_bgp_start_label_manager;
bool v6_with_v4_nexthops;
QOBJ_FIELDS; QOBJ_FIELDS;
}; };
DECLARE_QOBJ_TYPE(bgp_master); DECLARE_QOBJ_TYPE(bgp_master);

View File

@ -86,6 +86,15 @@ be specified (:ref:`common-invocation-options`).
be done to see if this is helping or not at the scale you are running be done to see if this is helping or not at the scale you are running
at. at.
.. option:: --v6-with-v4-nexthops
Allow BGP to peer in the V6 afi, when the interface only has v4 addresses.
This allows bgp to install the v6 routes with a v6 nexthop that has the
v4 address encoded in the nexthop. Zebra's equivalent option currently
overrides the bgp setting. This setting is only really usable when
the operator has turned off communication to zebra and is running bgpd
as a complete standalone process.
LABEL MANAGER LABEL MANAGER
------------- -------------

View File

@ -87,6 +87,13 @@ Besides the common invocation options (:ref:`common-invocation-options`), the
Allow zebra to modify the default receive buffer size to SIZE Allow zebra to modify the default receive buffer size to SIZE
in bytes. Under \*BSD only the -s option is available. in bytes. Under \*BSD only the -s option is available.
.. option:: --v6-with-v4-nexthops
Signal to zebra that v6 routes with v4 nexthops are accepted
by the underlying dataplane. This will be communicated to
the upper level daemons that can install v6 routes with v4
nexthops.
.. _interface-commands: .. _interface-commands:
Configuration Addresses behaviour Configuration Addresses behaviour

View File

@ -3876,6 +3876,7 @@ static int zclient_capability_decode(ZAPI_CALLBACK_ARGS)
cap.mpls_enabled = !!mpls_enabled; cap.mpls_enabled = !!mpls_enabled;
STREAM_GETL(s, cap.ecmp); STREAM_GETL(s, cap.ecmp);
STREAM_GETC(s, cap.role); STREAM_GETC(s, cap.role);
STREAM_GETC(s, cap.v6_with_v4_nexthop);
if (zclient->zebra_capabilities) if (zclient->zebra_capabilities)
(*zclient->zebra_capabilities)(&cap); (*zclient->zebra_capabilities)(&cap);

View File

@ -274,6 +274,7 @@ struct zclient_capabilities {
uint32_t ecmp; uint32_t ecmp;
bool mpls_enabled; bool mpls_enabled;
enum mlag_role role; enum mlag_role role;
bool v6_with_v4_nexthop;
}; };
/* Graceful Restart Capabilities message */ /* Graceful Restart Capabilities message */

View File

@ -71,22 +71,25 @@ uint32_t rcvbufsize = 128 * 1024;
#define OPTION_V6_RR_SEMANTICS 2000 #define OPTION_V6_RR_SEMANTICS 2000
#define OPTION_ASIC_OFFLOAD 2001 #define OPTION_ASIC_OFFLOAD 2001
#define OPTION_V6_WITH_V4_NEXTHOP 2002
/* Command line options. */ /* Command line options. */
const struct option longopts[] = { const struct option longopts[] = {
{"batch", no_argument, NULL, 'b'}, { "batch", no_argument, NULL, 'b' },
{"allow_delete", no_argument, NULL, 'a'}, { "allow_delete", no_argument, NULL, 'a' },
{"socket", required_argument, NULL, 'z'}, { "socket", required_argument, NULL, 'z' },
{"ecmp", required_argument, NULL, 'e'}, { "ecmp", required_argument, NULL, 'e' },
{"retain", no_argument, NULL, 'r'}, { "retain", no_argument, NULL, 'r' },
{"graceful_restart", required_argument, NULL, 'K'}, { "graceful_restart", required_argument, NULL, 'K' },
{"asic-offload", optional_argument, NULL, OPTION_ASIC_OFFLOAD}, { "asic-offload", optional_argument, NULL, OPTION_ASIC_OFFLOAD },
{ "v6-with-v4-nexthops", no_argument, NULL, OPTION_V6_WITH_V4_NEXTHOP },
#ifdef HAVE_NETLINK #ifdef HAVE_NETLINK
{"vrfwnetns", no_argument, NULL, 'n'}, { "vrfwnetns", no_argument, NULL, 'n' },
{"nl-bufsize", required_argument, NULL, 's'}, { "nl-bufsize", required_argument, NULL, 's' },
{"v6-rr-semantics", no_argument, NULL, OPTION_V6_RR_SEMANTICS}, { "v6-rr-semantics", no_argument, NULL, OPTION_V6_RR_SEMANTICS },
#endif /* HAVE_NETLINK */ #endif /* HAVE_NETLINK */
{0}}; { 0 }
};
zebra_capabilities_t _caps_p[] = {ZCAP_NET_ADMIN, ZCAP_SYS_ADMIN, zebra_capabilities_t _caps_p[] = {ZCAP_NET_ADMIN, ZCAP_SYS_ADMIN,
ZCAP_NET_RAW, ZCAP_NET_RAW,
@ -287,6 +290,7 @@ int main(int argc, char **argv)
struct sockaddr_storage dummy; struct sockaddr_storage dummy;
socklen_t dummylen; socklen_t dummylen;
bool asic_offload = false; bool asic_offload = false;
bool v6_with_v4_nexthop = false;
bool notify_on_ack = true; bool notify_on_ack = true;
graceful_restart = 0; graceful_restart = 0;
@ -294,26 +298,26 @@ int main(int argc, char **argv)
frr_preinit(&zebra_di, argc, argv); frr_preinit(&zebra_di, argc, argv);
frr_opt_add( frr_opt_add("baz:e:rK:s:"
"baz:e:rK:s:"
#ifdef HAVE_NETLINK #ifdef HAVE_NETLINK
"n" "n"
#endif #endif
, ,
longopts, longopts,
" -b, --batch Runs in batch mode\n" " -b, --batch Runs in batch mode\n"
" -a, --allow_delete Allow other processes to delete zebra routes\n" " -a, --allow_delete Allow other processes to delete zebra routes\n"
" -z, --socket Set path of zebra socket\n" " -z, --socket Set path of zebra socket\n"
" -e, --ecmp Specify ECMP to use.\n" " -e, --ecmp Specify ECMP to use.\n"
" -r, --retain When program terminates, retain added route by zebra.\n" " -r, --retain When program terminates, retain added route by zebra.\n"
" -K, --graceful_restart Graceful restart at the kernel level, timer in seconds for expiration\n" " -K, --graceful_restart Graceful restart at the kernel level, timer in seconds for expiration\n"
" -A, --asic-offload FRR is interacting with an asic underneath the linux kernel\n" " -A, --asic-offload FRR is interacting with an asic underneath the linux kernel\n"
" --v6-with-v4-nexthops Underlying dataplane supports v6 routes with v4 nexthops"
#ifdef HAVE_NETLINK #ifdef HAVE_NETLINK
" -s, --nl-bufsize Set netlink receive buffer size\n" " -s, --nl-bufsize Set netlink receive buffer size\n"
" -n, --vrfwnetns Use NetNS as VRF backend\n" " -n, --vrfwnetns Use NetNS as VRF backend\n"
" --v6-rr-semantics Use v6 RR semantics\n" " --v6-rr-semantics Use v6 RR semantics\n"
#else #else
" -s, Set kernel socket receive buffer size\n" " -s, Set kernel socket receive buffer size\n"
#endif /* HAVE_NETLINK */ #endif /* HAVE_NETLINK */
); );
@ -383,6 +387,9 @@ int main(int argc, char **argv)
notify_on_ack = true; notify_on_ack = true;
asic_offload = true; asic_offload = true;
break; break;
case OPTION_V6_WITH_V4_NEXTHOP:
v6_with_v4_nexthop = true;
break;
#endif /* HAVE_NETLINK */ #endif /* HAVE_NETLINK */
default: default:
frr_help_exit(1); frr_help_exit(1);
@ -392,7 +399,7 @@ int main(int argc, char **argv)
zrouter.master = frr_init(); zrouter.master = frr_init();
/* Zebra related initialize. */ /* Zebra related initialize. */
zebra_router_init(asic_offload, notify_on_ack); zebra_router_init(asic_offload, notify_on_ack, v6_with_v4_nexthop);
zserv_init(); zserv_init();
rib_init(); rib_init();
zebra_if_init(); zebra_if_init();

View File

@ -2319,7 +2319,7 @@ static void zsend_capabilities(struct zserv *client, struct zebra_vrf *zvrf)
stream_putc(s, mpls_enabled); stream_putc(s, mpls_enabled);
stream_putl(s, zrouter.multipath_num); stream_putl(s, zrouter.multipath_num);
stream_putc(s, zebra_mlag_get_role()); stream_putc(s, zebra_mlag_get_role());
stream_putc(s, zrouter.v6_with_v4_nexthop);
stream_putw_at(s, 0, stream_get_endp(s)); stream_putw_at(s, 0, stream_get_endp(s));
zserv_send_message(client, s); zserv_send_message(client, s);
} }

View File

@ -255,7 +255,8 @@ bool zebra_router_notify_on_ack(void)
return !zrouter.asic_offloaded || zrouter.notify_on_ack; return !zrouter.asic_offloaded || zrouter.notify_on_ack;
} }
void zebra_router_init(bool asic_offload, bool notify_on_ack) void zebra_router_init(bool asic_offload, bool notify_on_ack,
bool v6_with_v4_nexthop)
{ {
zrouter.sequence_num = 0; zrouter.sequence_num = 0;
@ -310,7 +311,7 @@ void zebra_router_init(bool asic_offload, bool notify_on_ack)
zrouter.asic_offloaded = asic_offload; zrouter.asic_offloaded = asic_offload;
zrouter.notify_on_ack = notify_on_ack; zrouter.notify_on_ack = notify_on_ack;
zrouter.v6_with_v4_nexthop = v6_with_v4_nexthop;
/* /*
* If you start using asic_notification_nexthop_control * If you start using asic_notification_nexthop_control
* come talk to the FRR community about what you are doing * come talk to the FRR community about what you are doing

View File

@ -207,6 +207,7 @@ struct zebra_router {
*/ */
bool asic_offloaded; bool asic_offloaded;
bool notify_on_ack; bool notify_on_ack;
bool v6_with_v4_nexthop;
/* /*
* If the asic is notifying us about successful nexthop * If the asic is notifying us about successful nexthop
@ -237,7 +238,8 @@ struct zebra_router {
extern struct zebra_router zrouter; extern struct zebra_router zrouter;
extern uint32_t rcvbufsize; extern uint32_t rcvbufsize;
extern void zebra_router_init(bool asic_offload, bool notify_on_ack); extern void zebra_router_init(bool asic_offload, bool notify_on_ack,
bool v6_with_v4_nexthop);
extern void zebra_router_cleanup(void); extern void zebra_router_cleanup(void);
extern void zebra_router_terminate(void); extern void zebra_router_terminate(void);

View File

@ -4033,6 +4033,9 @@ DEFUN (show_zebra,
ttable_add_row(table, "VRF|Not Available"); ttable_add_row(table, "VRF|Not Available");
#endif #endif
ttable_add_row(table, "v6 with v4 nexthop|%s",
zrouter.v6_with_v4_nexthop ? "Used" : "Unavaliable");
ttable_add_row(table, "ASIC offload|%s", ttable_add_row(table, "ASIC offload|%s",
zrouter.asic_offloaded ? "Used" : "Unavailable"); zrouter.asic_offloaded ? "Used" : "Unavailable");