[PATCH v2] Babel: Allow v6 next hop on interfaces with v4 addresses

Chris Webb chris at arachsys.com
Sun Nov 24 14:57:35 CET 2024


By default, the Babel protocol will advertise an IPv6 extended next hop
address on interfaces which don't have an IPv4 address. This is controlled
by the 'extended next hop' option.

Add support for 'extended next hop force' which advertises an extended
next hop even when IPv4 addresses are present. (They may be temporary,
for debugging or otherwise unsuitable for including in an advertisement.)
---
v2: use an explicit enum for possible values of ext_next_hop

 doc/bird.sgml        |  9 ++++++---
 proto/babel/babel.c  | 17 +++++++++++++----
 proto/babel/babel.h  |  6 ++++++
 proto/babel/config.Y |  5 +++--
 4 files changed, 28 insertions(+), 9 deletions(-)

diff --git a/doc/bird.sgml b/doc/bird.sgml
index 0d1e6f49..cb5fa572 100644
--- a/doc/bird.sgml
+++ b/doc/bird.sgml
@@ -2266,7 +2266,7 @@ protocol babel [<name>] {
 		check link <switch>;
 		next hop ipv4 <address>;
 		next hop ipv6 <address>;
-		extended next hop <switch>;
+		extended next hop <switch>|force;
 		rtt cost <number>;
 		rtt min <time>;
 		rtt max <time>;
@@ -2377,10 +2377,13 @@ protocol babel [<name>] {
       source for Babel packets will be used. In normal operation, it should not
       be necessary to set this option.
 
-      <tag><label id="babel-extended-next-hop">extended next hop <m/switch/</tag>
+      <tag><label id="babel-extended-next-hop">extended next hop
+      <m/switch/|force</tag>
       If enabled, BIRD will accept and emit IPv4 routes with an IPv6 next
       hop when IPv4 addresses are absent from the interface as described in
-      <rfc id="9229">. Default: yes.
+      <rfc id="9229">. Use <cf/extended next hop force/ to emit IPv4 routes
+      with an IPv6 next hop even when IPv4 addresses are present on the
+      interface. Default: yes.
 
       <tag><label id="babel-rtt-cost">rtt cost <m/number/</tag>
       The RTT-based cost that will be applied to all routes from each neighbour
diff --git a/proto/babel/babel.c b/proto/babel/babel.c
index 4187d258..4db6bd04 100644
--- a/proto/babel/babel.c
+++ b/proto/babel/babel.c
@@ -1836,8 +1836,12 @@ babel_iface_update_addr4(struct babel_iface *ifa)
 {
   struct babel_proto *p = ifa->proto;
 
-  ip_addr addr4 = ifa->iface->addr4 ? ifa->iface->addr4->ip : IPA_NONE;
-  ifa->next_hop_ip4 = ipa_nonzero(ifa->cf->next_hop_ip4) ? ifa->cf->next_hop_ip4 : addr4;
+  if (ipa_nonzero(ifa->cf->next_hop_ip4))
+    ifa->next_hop_ip4 = ifa->cf->next_hop_ip4;
+  else if (ifa->cf->ext_next_hop != BABEL_EXT_NEXT_HOP_FORCE && ifa->iface->addr4)
+    ifa->next_hop_ip4 = ifa->iface->addr4->ip;
+  else
+    ifa->next_hop_ip4 = IPA_NONE;
 
   if (ipa_zero(ifa->next_hop_ip4) && p->ip4_channel && !ifa->cf->ext_next_hop)
     log(L_WARN "%s: Missing IPv4 next hop address for %s", p->p.name, ifa->ifname);
@@ -1912,8 +1916,13 @@ babel_add_iface(struct babel_proto *p, struct iface *new, struct babel_iface_con
 
   add_tail(&p->interfaces, NODE ifa);
 
-  ip_addr addr4 = new->addr4 ? new->addr4->ip : IPA_NONE;
-  ifa->next_hop_ip4 = ipa_nonzero(ic->next_hop_ip4) ? ic->next_hop_ip4 : addr4;
+  if (ipa_nonzero(ic->next_hop_ip4))
+    ifa->next_hop_ip4 = ic->next_hop_ip4;
+  else if (ic->ext_next_hop != BABEL_EXT_NEXT_HOP_FORCE && new->addr4)
+    ifa->next_hop_ip4 = new->addr4->ip;
+  else
+    ifa->next_hop_ip4 = IPA_NONE;
+
   ifa->next_hop_ip6 = ipa_nonzero(ic->next_hop_ip6) ? ic->next_hop_ip6 : ifa->addr;
 
   if (ipa_zero(ifa->next_hop_ip4) && p->ip4_channel && !ic->ext_next_hop)
diff --git a/proto/babel/babel.h b/proto/babel/babel.h
index edde4cab..5b397b45 100644
--- a/proto/babel/babel.h
+++ b/proto/babel/babel.h
@@ -127,6 +127,12 @@ enum babel_ae_type {
   BABEL_AE_MAX
 };
 
+enum babel_ext_next_hop {
+  BABEL_EXT_NEXT_HOP_OFF	= 0,
+  BABEL_EXT_NEXT_HOP_ON		= 1,
+  BABEL_EXT_NEXT_HOP_FORCE	= 2
+};
+
 
 struct babel_config {
   struct proto_config c;
diff --git a/proto/babel/config.Y b/proto/babel/config.Y
index d412a54b..bdfff203 100644
--- a/proto/babel/config.Y
+++ b/proto/babel/config.Y
@@ -24,7 +24,7 @@ CF_DECLS
 
 CF_KEYWORDS(BABEL, INTERFACE, METRIC, RXCOST, HELLO, UPDATE, INTERVAL, PORT,
 	TYPE, WIRED, WIRELESS, RX, TX, BUFFER, PRIORITY, LENGTH, CHECK, LINK,
-	NEXT, HOP, IPV4, IPV6, BABEL_METRIC, SHOW, INTERFACES, NEIGHBORS,
+	NEXT, HOP, FORCE, IPV4, IPV6, BABEL_METRIC, SHOW, INTERFACES, NEIGHBORS,
 	ENTRIES, RANDOMIZE, ROUTER, ID, AUTHENTICATION, NONE, MAC, PERMISSIVE,
 	EXTENDED, TUNNEL, RTT, MIN, MAX, DECAY, SEND, TIMESTAMPS, COST, DELAY)
 
@@ -158,7 +158,8 @@ babel_iface_item:
  | CHECK LINK bool { BABEL_IFACE->check_link = $3; }
  | NEXT HOP IPV4 ipa { BABEL_IFACE->next_hop_ip4 = $4; if (!ipa_is_ip4($4)) cf_error("Must be an IPv4 address"); }
  | NEXT HOP IPV6 ipa { BABEL_IFACE->next_hop_ip6 = $4; if (!ipa_is_ip6($4)) cf_error("Must be an IPv6 address"); }
- | EXTENDED NEXT HOP bool { BABEL_IFACE->ext_next_hop = $4; }
+ | EXTENDED NEXT HOP bool { BABEL_IFACE->ext_next_hop = $4 ? BABEL_EXT_NEXT_HOP_ON : BABEL_EXT_NEXT_HOP_OFF; }
+ | EXTENDED NEXT HOP FORCE { BABEL_IFACE->ext_next_hop = BABEL_EXT_NEXT_HOP_FORCE; }
  | AUTHENTICATION NONE { BABEL_IFACE->auth_type = BABEL_AUTH_NONE; }
  | AUTHENTICATION MAC { BABEL_IFACE->auth_type = BABEL_AUTH_MAC; BABEL_IFACE->auth_permissive = 0; }
  | AUTHENTICATION MAC PERMISSIVE { BABEL_IFACE->auth_type = BABEL_AUTH_MAC; BABEL_IFACE->auth_permissive = 1; }



More information about the Bird-users mailing list