Hoi,

On 3/30/24 19:24, Juliusz Chroboczek wrote:
Yes, it's legal, but discouraged.  Please see RFC 9229 Section 2.1:
Thanks Juliusz, for confirming and for making the allowance in the RFC in the first place. Attached is a patch that optionally allows extended next hop to be set for IPv4 routes. Please take a look.

groet,
Pim

--
Pim van Pelt
PBVP1-RIPE -https://ipng.ch/
diff --git a/doc/bird.sgml b/doc/bird.sgml
index d0bfabdb..35c36484 100644
--- a/doc/bird.sgml
+++ b/doc/bird.sgml
@@ -2224,7 +2224,7 @@ protocol babel [<name>] {
 		check link <switch>;
 		next hop ipv4 <address>;
 		next hop ipv6 <address>;
-		extended next hop <switch>;
+		extended next hop <switch>|always;
 		rtt cost <number>;
 		rtt min <time>;
 		rtt max <time>;
@@ -2338,7 +2338,11 @@ protocol babel [<name>] {
       <tag><label id="babel-extended-next-hop">extended next hop <m/switch/</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">. The order of preference when selecting a nexthop is: if
+      this option is set to <cf/always/, IPv6 nexthop is always used; otherwise,
+      if an IPv4 address is present on the interface, then IPv4 is used; otherwise,
+      if this option is set to yes, then IPv6 is used. 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..846baf7a 100644
--- a/proto/babel/babel.c
+++ b/proto/babel/babel.c
@@ -1038,12 +1038,16 @@ babel_send_update_(struct babel_iface *ifa, btime changed, struct fib *rtable)
 
     if (e->n.addr->type == NET_IP4)
     {
-      /* Always prefer IPv4 nexthop if set */
-      if (ipa_nonzero(ifa->next_hop_ip4))
+      /* Order of preference:
+       * 1) IPv6 iff extended next hop always; is set
+       * 2) IPv4 if there's an IPv4 address on the interface
+       * 3) IPv6 if extended next hop on; is set
+       */
+      if (ifa->cf->ext_next_hop == BABEL_EXTNH_ALWAYS)
+        msg.update.next_hop = ifa->next_hop_ip6;
+      else if (ipa_nonzero(ifa->next_hop_ip4))
         msg.update.next_hop = ifa->next_hop_ip4;
-
-      /* Only send IPv6 nexthop if enabled */
-      else if (ifa->cf->ext_next_hop)
+      else if (ifa->cf->ext_next_hop == BABEL_EXTNH_ON)
         msg.update.next_hop = ifa->next_hop_ip6;
     }
     else
diff --git a/proto/babel/babel.h b/proto/babel/babel.h
index edde4cab..0582a3fc 100644
--- a/proto/babel/babel.h
+++ b/proto/babel/babel.h
@@ -35,6 +35,9 @@
 #define BABEL_PORT		6696
 #define BABEL_INFINITY		0xFFFF
 
+#define BABEL_EXTNH_ON		1
+#define BABEL_EXTNH_ALWAYS	2
+
 
 #define BABEL_HELLO_INTERVAL_WIRED	(4 S_)	/* Default hello intervals in seconds */
 #define BABEL_HELLO_INTERVAL_WIRELESS	(4 S_)
diff --git a/proto/babel/config.Y b/proto/babel/config.Y
index d412a54b..a1d4c017 100644
--- a/proto/babel/config.Y
+++ b/proto/babel/config.Y
@@ -24,9 +24,11 @@ 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, ALWAYS, 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)
+	EXTENDED, TUNNEL, RTT, MIN, MAX, DECAY, SEND, TIMESTAMPS)
+
+%type <i> babel_extnh
 
 CF_GRAMMAR
 
@@ -142,6 +144,10 @@ babel_iface_finish:
 };
 
 
+babel_extnh:
+   bool { $$ = $1; }
+ | ALWAYS { $$ = BABEL_EXTNH_ALWAYS; }
+
 babel_iface_item:
  | PORT expr { BABEL_IFACE->port = $2; if (($2<1) || ($2>65535)) cf_error("Invalid port number"); }
  | RXCOST expr { BABEL_IFACE->rxcost = $2; if (($2<1) || ($2>65535)) cf_error("Invalid rxcost"); }
@@ -158,7 +164,7 @@ 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 babel_extnh { BABEL_IFACE->ext_next_hop = $4; }
  | 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; }

Reply via email to