summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bgpd/bgp_main.c43
-rw-r--r--bgpd/bgp_packet.c13
-rw-r--r--bgpd/bgp_zebra.c6
-rw-r--r--bgpd/bgpd.h2
-rw-r--r--doc/user/bgp.rst9
-rw-r--r--doc/user/zebra.rst7
-rw-r--r--lib/zclient.c1
-rw-r--r--lib/zclient.h1
-rw-r--r--zebra/main.c63
-rw-r--r--zebra/zapi_msg.c2
-rw-r--r--zebra/zebra_router.c5
-rw-r--r--zebra/zebra_router.h4
-rw-r--r--zebra/zebra_vty.c3
13 files changed, 103 insertions, 56 deletions
diff --git a/bgpd/bgp_main.c b/bgpd/bgp_main.c
index 074059c146..11917c6c4a 100644
--- a/bgpd/bgp_main.c
+++ b/bgpd/bgp_main.c
@@ -57,15 +57,17 @@
/* bgpd options, we use GNU getopt library. */
static const struct option longopts[] = {
- {"bgp_port", required_argument, NULL, 'p'},
- {"listenon", required_argument, NULL, 'l'},
- {"no_kernel", no_argument, NULL, 'n'},
- {"skip_runas", no_argument, NULL, 'S'},
- {"ecmp", required_argument, NULL, 'e'},
- {"int_num", required_argument, NULL, 'I'},
- {"no_zebra", no_argument, NULL, 'Z'},
- {"socket_size", required_argument, NULL, 's'},
- {0}};
+ { "bgp_port", required_argument, NULL, 'p' },
+ { "listenon", required_argument, NULL, 'l' },
+ { "no_kernel", no_argument, NULL, 'n' },
+ { "skip_runas", no_argument, NULL, 'S' },
+ { "ecmp", required_argument, NULL, 'e' },
+ { "int_num", required_argument, NULL, 'I' },
+ { "no_zebra", no_argument, NULL, 'Z' },
+ { "socket_size", required_argument, NULL, 's' },
+ { "v6-with-v4-nexthops", no_argument, NULL, 'v' },
+ { 0 }
+};
/* signal definitions */
void sighup(void);
@@ -387,16 +389,16 @@ int main(int argc, char **argv)
addresses->cmp = (int (*)(void *, void *))strcmp;
frr_preinit(&bgpd_di, argc, argv);
- frr_opt_add(
- "p:l:SnZe:I:s:" DEPRECATED_OPTIONS, longopts,
- " -p, --bgp_port Set BGP listen port number (0 means do not listen).\n"
- " -l, --listenon Listen on specified address (implies -n)\n"
- " -n, --no_kernel Do not install route to kernel.\n"
- " -Z, --no_zebra Do not communicate with Zebra.\n"
- " -S, --skip_runas Skip capabilities checks, and changing user and group IDs.\n"
- " -e, --ecmp Specify ECMP to use.\n"
- " -I, --int_num Set instance number (label-manager)\n"
- " -s, --socket_size Set BGP peer socket send buffer size\n");
+ frr_opt_add("p:l:SnZe:I:s:" DEPRECATED_OPTIONS, longopts,
+ " -p, --bgp_port Set BGP listen port number (0 means do not listen).\n"
+ " -l, --listenon Listen on specified address (implies -n)\n"
+ " -n, --no_kernel Do not install route to kernel.\n"
+ " -Z, --no_zebra Do not communicate with Zebra.\n"
+ " -S, --skip_runas Skip capabilities checks, and changing user and group IDs.\n"
+ " -e, --ecmp Specify ECMP to use.\n"
+ " -I, --int_num Set instance number (label-manager)\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. */
while (1) {
@@ -458,6 +460,9 @@ int main(int argc, char **argv)
case 's':
buffer_size = atoi(optarg);
break;
+ case 'v':
+ bm->v6_with_v4_nexthops = true;
+ break;
default:
frr_help_exit(1);
}
diff --git a/bgpd/bgp_packet.c b/bgpd/bgp_packet.c
index 7c2c6f616b..cc9b2c7bb4 100644
--- a/bgpd/bgp_packet.c
+++ b/bgpd/bgp_packet.c
@@ -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_MPLS_VPN]
|| peer->afc_nego[AFI_IP6][SAFI_ENCAP]) {
- if (IN6_IS_ADDR_UNSPECIFIED(&peer->nexthop.v6_global)) {
-#if defined(HAVE_CUMULUS)
- zlog_warn("%s: No local IPv6 address, BGP routing may not work",
- peer->host);
-#endif
+ if (IN6_IS_ADDR_UNSPECIFIED(&peer->nexthop.v6_global) &&
+ !bm->v6_with_v4_nexthops) {
+ flog_err(EC_BGP_SND_FAIL,
+"%s: No local IPv6 address, and zebra does not support V6 routing with v4 nexthops, BGP routing for V6 will not work",
+ peer->host);
+ bgp_notify_send(peer, BGP_NOTIFY_CEASE,
+ BGP_NOTIFY_SUBCODE_UNSPECIFIC);
+ return BGP_Stop;
}
}
peer->rtt = sockopt_tcp_rtt(peer->fd);
diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c
index becd99167f..8ff6b63e05 100644
--- a/bgpd/bgp_zebra.c
+++ b/bgpd/bgp_zebra.c
@@ -3455,6 +3455,11 @@ static bool bgp_zebra_label_manager_connect(void)
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)
{
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));
zclient_init(zclient, ZEBRA_ROUTE_BGP, 0, &bgpd_privs);
zclient->zebra_connected = bgp_zebra_connected;
+ zclient->zebra_capabilities = bgp_zebra_capabilities;
zclient->instance = instance;
/* Initialize special zclient for synchronous message exchanges. */
diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h
index 5e467bb873..67ee8aa138 100644
--- a/bgpd/bgpd.h
+++ b/bgpd/bgpd.h
@@ -168,6 +168,8 @@ struct bgp_master {
struct event *t_bgp_sync_label_manager;
struct event *t_bgp_start_label_manager;
+ bool v6_with_v4_nexthops;
+
QOBJ_FIELDS;
};
DECLARE_QOBJ_TYPE(bgp_master);
diff --git a/doc/user/bgp.rst b/doc/user/bgp.rst
index ad8f913355..09173ab2f5 100644
--- a/doc/user/bgp.rst
+++ b/doc/user/bgp.rst
@@ -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
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
-------------
diff --git a/doc/user/zebra.rst b/doc/user/zebra.rst
index d7e768b710..32de3e908f 100644
--- a/doc/user/zebra.rst
+++ b/doc/user/zebra.rst
@@ -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
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:
Configuration Addresses behaviour
diff --git a/lib/zclient.c b/lib/zclient.c
index c36bcc6e2e..294a78feb0 100644
--- a/lib/zclient.c
+++ b/lib/zclient.c
@@ -3876,6 +3876,7 @@ static int zclient_capability_decode(ZAPI_CALLBACK_ARGS)
cap.mpls_enabled = !!mpls_enabled;
STREAM_GETL(s, cap.ecmp);
STREAM_GETC(s, cap.role);
+ STREAM_GETC(s, cap.v6_with_v4_nexthop);
if (zclient->zebra_capabilities)
(*zclient->zebra_capabilities)(&cap);
diff --git a/lib/zclient.h b/lib/zclient.h
index 316dd4cd68..42c5a5fdac 100644
--- a/lib/zclient.h
+++ b/lib/zclient.h
@@ -274,6 +274,7 @@ struct zclient_capabilities {
uint32_t ecmp;
bool mpls_enabled;
enum mlag_role role;
+ bool v6_with_v4_nexthop;
};
/* Graceful Restart Capabilities message */
diff --git a/zebra/main.c b/zebra/main.c
index bd4623be55..aeb9739c13 100644
--- a/zebra/main.c
+++ b/zebra/main.c
@@ -71,22 +71,25 @@ uint32_t rcvbufsize = 128 * 1024;
#define OPTION_V6_RR_SEMANTICS 2000
#define OPTION_ASIC_OFFLOAD 2001
+#define OPTION_V6_WITH_V4_NEXTHOP 2002
/* Command line options. */
const struct option longopts[] = {
- {"batch", no_argument, NULL, 'b'},
- {"allow_delete", no_argument, NULL, 'a'},
- {"socket", required_argument, NULL, 'z'},
- {"ecmp", required_argument, NULL, 'e'},
- {"retain", no_argument, NULL, 'r'},
- {"graceful_restart", required_argument, NULL, 'K'},
- {"asic-offload", optional_argument, NULL, OPTION_ASIC_OFFLOAD},
+ { "batch", no_argument, NULL, 'b' },
+ { "allow_delete", no_argument, NULL, 'a' },
+ { "socket", required_argument, NULL, 'z' },
+ { "ecmp", required_argument, NULL, 'e' },
+ { "retain", no_argument, NULL, 'r' },
+ { "graceful_restart", required_argument, NULL, 'K' },
+ { "asic-offload", optional_argument, NULL, OPTION_ASIC_OFFLOAD },
+ { "v6-with-v4-nexthops", no_argument, NULL, OPTION_V6_WITH_V4_NEXTHOP },
#ifdef HAVE_NETLINK
- {"vrfwnetns", no_argument, NULL, 'n'},
- {"nl-bufsize", required_argument, NULL, 's'},
- {"v6-rr-semantics", no_argument, NULL, OPTION_V6_RR_SEMANTICS},
+ { "vrfwnetns", no_argument, NULL, 'n' },
+ { "nl-bufsize", required_argument, NULL, 's' },
+ { "v6-rr-semantics", no_argument, NULL, OPTION_V6_RR_SEMANTICS },
#endif /* HAVE_NETLINK */
- {0}};
+ { 0 }
+};
zebra_capabilities_t _caps_p[] = {ZCAP_NET_ADMIN, ZCAP_SYS_ADMIN,
ZCAP_NET_RAW,
@@ -287,6 +290,7 @@ int main(int argc, char **argv)
struct sockaddr_storage dummy;
socklen_t dummylen;
bool asic_offload = false;
+ bool v6_with_v4_nexthop = false;
bool notify_on_ack = true;
graceful_restart = 0;
@@ -294,26 +298,26 @@ int main(int argc, char **argv)
frr_preinit(&zebra_di, argc, argv);
- frr_opt_add(
- "baz:e:rK:s:"
+ frr_opt_add("baz:e:rK:s:"
#ifdef HAVE_NETLINK
- "n"
+ "n"
#endif
- ,
- longopts,
- " -b, --batch Runs in batch mode\n"
- " -a, --allow_delete Allow other processes to delete zebra routes\n"
- " -z, --socket Set path of zebra socket\n"
- " -e, --ecmp Specify ECMP to use.\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"
- " -A, --asic-offload FRR is interacting with an asic underneath the linux kernel\n"
+ ,
+ longopts,
+ " -b, --batch Runs in batch mode\n"
+ " -a, --allow_delete Allow other processes to delete zebra routes\n"
+ " -z, --socket Set path of zebra socket\n"
+ " -e, --ecmp Specify ECMP to use.\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"
+ " -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
- " -s, --nl-bufsize Set netlink receive buffer size\n"
- " -n, --vrfwnetns Use NetNS as VRF backend\n"
- " --v6-rr-semantics Use v6 RR semantics\n"
+ " -s, --nl-bufsize Set netlink receive buffer size\n"
+ " -n, --vrfwnetns Use NetNS as VRF backend\n"
+ " --v6-rr-semantics Use v6 RR semantics\n"
#else
- " -s, Set kernel socket receive buffer size\n"
+ " -s, Set kernel socket receive buffer size\n"
#endif /* HAVE_NETLINK */
);
@@ -383,6 +387,9 @@ int main(int argc, char **argv)
notify_on_ack = true;
asic_offload = true;
break;
+ case OPTION_V6_WITH_V4_NEXTHOP:
+ v6_with_v4_nexthop = true;
+ break;
#endif /* HAVE_NETLINK */
default:
frr_help_exit(1);
@@ -392,7 +399,7 @@ int main(int argc, char **argv)
zrouter.master = frr_init();
/* 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();
rib_init();
zebra_if_init();
diff --git a/zebra/zapi_msg.c b/zebra/zapi_msg.c
index 2fc696c4e1..e9c243217a 100644
--- a/zebra/zapi_msg.c
+++ b/zebra/zapi_msg.c
@@ -2319,7 +2319,7 @@ static void zsend_capabilities(struct zserv *client, struct zebra_vrf *zvrf)
stream_putc(s, mpls_enabled);
stream_putl(s, zrouter.multipath_num);
stream_putc(s, zebra_mlag_get_role());
-
+ stream_putc(s, zrouter.v6_with_v4_nexthop);
stream_putw_at(s, 0, stream_get_endp(s));
zserv_send_message(client, s);
}
diff --git a/zebra/zebra_router.c b/zebra/zebra_router.c
index 1b3e31ee42..4caaf8a9e2 100644
--- a/zebra/zebra_router.c
+++ b/zebra/zebra_router.c
@@ -255,7 +255,8 @@ bool zebra_router_notify_on_ack(void)
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;
@@ -310,7 +311,7 @@ void zebra_router_init(bool asic_offload, bool notify_on_ack)
zrouter.asic_offloaded = asic_offload;
zrouter.notify_on_ack = notify_on_ack;
-
+ zrouter.v6_with_v4_nexthop = v6_with_v4_nexthop;
/*
* If you start using asic_notification_nexthop_control
* come talk to the FRR community about what you are doing
diff --git a/zebra/zebra_router.h b/zebra/zebra_router.h
index a7f0f135f9..bd86cfb495 100644
--- a/zebra/zebra_router.h
+++ b/zebra/zebra_router.h
@@ -207,6 +207,7 @@ struct zebra_router {
*/
bool asic_offloaded;
bool notify_on_ack;
+ bool v6_with_v4_nexthop;
/*
* If the asic is notifying us about successful nexthop
@@ -237,7 +238,8 @@ struct zebra_router {
extern struct zebra_router zrouter;
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_terminate(void);
diff --git a/zebra/zebra_vty.c b/zebra/zebra_vty.c
index 291c2eb7e0..1a123ba5c2 100644
--- a/zebra/zebra_vty.c
+++ b/zebra/zebra_vty.c
@@ -4033,6 +4033,9 @@ DEFUN (show_zebra,
ttable_add_row(table, "VRF|Not Available");
#endif
+ ttable_add_row(table, "v6 with v4 nexthop|%s",
+ zrouter.v6_with_v4_nexthop ? "Used" : "Unavaliable");
+
ttable_add_row(table, "ASIC offload|%s",
zrouter.asic_offloaded ? "Used" : "Unavailable");