[PATCH,RFC] Allow exchanging LOCAL_PREF with eBGP peers.

Lennert Buytenhek buytenh at wantstofly.org
Mon Feb 20 05:08:41 CET 2017


On Sun, Feb 19, 2017 at 12:57:29AM +0100, Ondrej Zajicek wrote:

> > I've attached a patch that allows (selectively) exchanging LOCAL_PREF
> > with eBGP peers.
> > 
> > The BGP RFC (RFC4271) says that you shouldn't send LOCAL_PREF to eBGP
> > peers, but most modern BGP implementations have an override to allow
> > doing this anyway, and it is very useful in some scenarios, for example
> > if you have a network topology a la RFC7938.
> > 
> > This patch enables this functionality by the 'ebgp localpref' clause
> > in a bgp protocol statement, for example:
> > 
> > 	protocol bgp mypeer {
> > 		[...];
> > 		ebgp localpref rx;
> > 	}
> > 
> > This option works like 'add paths', in that the possible arguments are
> > "rx" or "tx" or a bool (where "yes" means both rx and tx).
> 
> Hello

Hi!


> I think it is a useful feature. But rx/tx values seems like a bit
> overengineering. If for some obscure reason someone wants it just
> one way, it can easily be done in filters.

Good point, I agree.  Here's v2, also with the corresponding change to
bird.sgml, against current 1.6 git HEAD.  Are you happy with the name of
the config option?



diff --git a/doc/bird.sgml b/doc/bird.sgml
index 6af0e0f..513382d 100644
--- a/doc/bird.sgml
+++ b/doc/bird.sgml
@@ -2043,6 +2043,14 @@ using the following configuration parameters:
 	TX direction. When active, all available routes accepted by the export
 	filter are advertised to the neighbor. Default: off.
 
+	<tag><label id="bgp-ebgp-localpref">ebgp localpref <m/switch/</tag>
+	A standard BGP implementation will not send the Local Preference
+	attribute to eBGP neighbors and will ignore this attribute if received
+	from eBGP neighbors, as per <rfc id="4271">.  When this option is
+	enabled on an eBGP session, this attribute will be sent to and
+	accepted from the peer, which is useful for example if you have a
+	setup like in <rfc id="7938">.
+
 	<tag><label id="bgp-allow-local-as">allow local as [<m/number/]</tag>
 	BGP prevents routing loops by rejecting received routes with the local
 	AS number in the AS path. This option allows to loose or disable the
diff --git a/proto/bgp/attrs.c b/proto/bgp/attrs.c
index 9d23374..257c0ff 100644
--- a/proto/bgp/attrs.c
+++ b/proto/bgp/attrs.c
@@ -307,7 +307,7 @@ static struct attr_desc bgp_attr_table[] = {
     bgp_check_next_hop, bgp_format_next_hop },
   { "med", 4, BAF_OPTIONAL, EAF_TYPE_INT, 1,					/* BA_MULTI_EXIT_DISC */
     NULL, NULL },
-  { "local_pref", 4, BAF_TRANSITIVE, EAF_TYPE_INT, 0,				/* BA_LOCAL_PREF */
+  { "local_pref", 4, BAF_TRANSITIVE, EAF_TYPE_INT, 1,				/* BA_LOCAL_PREF */
     NULL, NULL },
   { "atomic_aggr", 0, BAF_TRANSITIVE, EAF_TYPE_OPAQUE, 1,			/* BA_ATOMIC_AGGR */
     NULL, NULL },
@@ -822,8 +822,13 @@ bgp_get_bucket(struct bgp_proto *p, net *n, ea_list *attrs, int originate)
       code = EA_ID(a->id);
       if (ATTR_KNOWN(code))
 	{
-	  if (!bgp_attr_table[code].allow_in_ebgp && !p->is_internal)
-	    continue;
+	  if (!p->is_internal)
+	    {
+	      if (!bgp_attr_table[code].allow_in_ebgp)
+		continue;
+	      if (code == BA_LOCAL_PREF && !p->cf->ebgp_local_pref)
+		continue;
+	    }
 	  /* The flags might have been zero if the attr was added by filters */
 	  a->flags = (a->flags & BAF_PARTIAL) | bgp_attr_table[code].expected_flags;
 	  if (code < 32)
@@ -1777,8 +1782,13 @@ bgp_decode_attrs(struct bgp_conn *conn, byte *attr, uint len, struct linpool *po
 	    { errcode = 5; goto err; }
 	  if ((desc->expected_flags ^ flags) & (BAF_OPTIONAL | BAF_TRANSITIVE))
 	    { errcode = 4; goto err; }
-	  if (!desc->allow_in_ebgp && !bgp->is_internal)
-	    continue;
+	  if (!bgp->is_internal)
+	    {
+	      if (!desc->allow_in_ebgp)
+		continue;
+	      if (code == BA_LOCAL_PREF && !bgp->cf->ebgp_local_pref)
+		continue;
+	    }
 	  if (desc->validate)
 	    {
 	      errcode = desc->validate(bgp, z, l);
diff --git a/proto/bgp/bgp.c b/proto/bgp/bgp.c
index 0f1c944..dee4d91 100644
--- a/proto/bgp/bgp.c
+++ b/proto/bgp/bgp.c
@@ -1556,7 +1556,7 @@ bgp_show_proto_info(struct proto *P)
 	      (c->peer_add_path & ADD_PATH_RX) ? " add-path-rx" : "",
 	      (c->peer_add_path & ADD_PATH_TX) ? " add-path-tx" : "",
 	      c->peer_ext_messages_support ? " ext-messages" : "");
-      cli_msg(-1006, "    Session:          %s%s%s%s%s%s%s%s",
+      cli_msg(-1006, "    Session:          %s%s%s%s%s%s%s%s%s",
 	      p->is_internal ? "internal" : "external",
 	      p->cf->multihop ? " multihop" : "",
 	      p->rr_client ? " route-reflector" : "",
@@ -1564,7 +1564,8 @@ bgp_show_proto_info(struct proto *P)
 	      p->as4_session ? " AS4" : "",
 	      p->add_path_rx ? " add-path-rx" : "",
 	      p->add_path_tx ? " add-path-tx" : "",
-	      p->ext_messages ? " ext-messages" : "");
+	      p->ext_messages ? " ext-messages" : "",
+	      p->cf->ebgp_local_pref ? " ebgp-localpref" : "");
       cli_msg(-1006, "    Source address:   %I", p->source_addr);
       if (P->cf->in_limit)
 	cli_msg(-1006, "    Route limit:      %d/%d",
diff --git a/proto/bgp/bgp.h b/proto/bgp/bgp.h
index d028bef..69c06d6 100644
--- a/proto/bgp/bgp.h
+++ b/proto/bgp/bgp.h
@@ -49,6 +49,7 @@ struct bgp_config {
   int interpret_communities;		/* Hardwired handling of well-known communities */
   int secondary;			/* Accept also non-best routes (i.e. RA_ACCEPTED) */
   int add_path;				/* Use ADD-PATH extension [draft] */
+  int ebgp_local_pref;			/* Exchange LOCAL_PREF with eBGP peers */
   int allow_local_as;			/* Allow that number of local ASNs in incoming AS_PATHs */
   int gr_mode;				/* Graceful restart mode (BGP_GR_*) */
   int setkey;				/* Set MD5 password to system SA/SP database */
diff --git a/proto/bgp/config.Y b/proto/bgp/config.Y
index 32ae88a..4cc1291 100644
--- a/proto/bgp/config.Y
+++ b/proto/bgp/config.Y
@@ -27,7 +27,8 @@ CF_KEYWORDS(BGP, LOCAL, NEIGHBOR, AS, HOLD, TIME, CONNECT, RETRY,
 	INTERPRET, COMMUNITIES, BGP_ORIGINATOR_ID, BGP_CLUSTER_LIST, IGP,
 	TABLE, GATEWAY, DIRECT, RECURSIVE, MED, TTL, SECURITY, DETERMINISTIC,
 	SECONDARY, ALLOW, BFD, ADD, PATHS, RX, TX, GRACEFUL, RESTART, AWARE,
-	CHECK, LINK, PORT, EXTENDED, MESSAGES, SETKEY, BGP_LARGE_COMMUNITY)
+	CHECK, LINK, PORT, EXTENDED, MESSAGES, SETKEY, BGP_LARGE_COMMUNITY,
+	EBGP, LOCALPREF)
 
 CF_GRAMMAR
 
@@ -126,6 +127,7 @@ bgp_proto:
  | bgp_proto ADD PATHS RX ';' { BGP_CFG->add_path = ADD_PATH_RX; }
  | bgp_proto ADD PATHS TX ';' { BGP_CFG->add_path = ADD_PATH_TX; }
  | bgp_proto ADD PATHS bool ';' { BGP_CFG->add_path = $4 ? ADD_PATH_FULL : 0; }
+ | bgp_proto EBGP LOCALPREF bool ';' { BGP_CFG->ebgp_local_pref = $4; }
  | bgp_proto ALLOW LOCAL AS ';' { BGP_CFG->allow_local_as = -1; }
  | bgp_proto ALLOW LOCAL AS expr ';' { BGP_CFG->allow_local_as = $5; }
  | bgp_proto GRACEFUL RESTART bool ';' { BGP_CFG->gr_mode = $4; }


More information about the Bird-users mailing list