summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOndrej Zajicek <santiago@crfreenet.org>2009-11-18 20:32:36 +0100
committerOndrej Zajicek <santiago@crfreenet.org>2009-11-18 20:32:36 +0100
commit3f9b7bfe9ff050430a5886b22a5ab11b5f253048 (patch)
treed2261e130a4704bf2c84136bbdd98bdd238b2778
parent62aa96caa28180f76c8aff0c49dd21128e396153 (diff)
downloadbird-3f9b7bfe9ff050430a5886b22a5ab11b5f253048.tar
bird-3f9b7bfe9ff050430a5886b22a5ab11b5f253048.zip
Implements option that controls IPv6 BGP next hops when lladdr is missing.
-rw-r--r--doc/bird.sgml28
-rw-r--r--nest/config.Y2
-rw-r--r--proto/bgp/bgp.c4
-rw-r--r--proto/bgp/bgp.h5
-rw-r--r--proto/bgp/config.Y6
-rw-r--r--proto/bgp/packets.c47
6 files changed, 69 insertions, 23 deletions
diff --git a/doc/bird.sgml b/doc/bird.sgml
index b475830..db9a747 100644
--- a/doc/bird.sgml
+++ b/doc/bird.sgml
@@ -646,7 +646,7 @@ incompatible with each other (that is to prevent you from shooting in the foot).
but <cf>1.0.0.0/16 &tilde; [ 1.0.0.0/8- ]</cf> is false.
Cisco-style patterns like <cf>10.0.0.0/8 ge 16 le 24</cf> can be expressed
- in Bird as <cf>10.0.0.0/8{16,24}</cf>, <cf>192.168.0.0/16 le 24</cf> as
+ in BIRD as <cf>10.0.0.0/8{16,24}</cf>, <cf>192.168.0.0/16 le 24</cf> as
<cf>192.168.0.0/16{16,24}</cf> and <cf>192.168.0.0/16 ge 24</cf> as
<cf>192.168.0.0/16{24,32}</cf>.
@@ -887,12 +887,28 @@ for each neighbor using the following configuration parameters:
we should route via our direct neighbor with address <m/ip/.
Default: switched off.
- <tag>next hop self</tag> Avoid calculation of the Next Hop attribute
- and always advertise our own source address (see below) as a next hop.
- This needs to be used only
- occasionally to circumvent misconfigurations of other routers.
+ <tag>next hop self</tag> Avoid calculation of the Next Hop
+ attribute and always advertise our own source address (see
+ below) as a next hop. This needs to be used only occasionally
+ to circumvent misconfigurations of other routers.
Default: disabled.
+ <tag>missing lladdr self|drop|ignore</tag>Next Hop attribute
+ in BGP-IPv6 sometimes contains just the global IPv6 address,
+ but sometimes it has to contain both global and link-local
+ IPv6 addresses. This option specifies what to do if BIRD have
+ to send both addresses but does not know link-local address.
+ This situation might happen when routes from other protocols
+ are exported to BGP, or when improper updates are received
+ from BGP peers. <tag/self/ means that BIRD advertises its own
+ local address instead. <tag/drop/ means that BIRD skips that
+ prefixes and logs error. <tag/ignore/ means that BIRD ignores
+ the problem and sends just the global address (and therefore
+ forms improper BGP update). Default: <tag/self/, unless BIRD
+ is configured as a route server (option <tag/rs client/), in
+ that case default is <tag/drop/, because route servers usually
+ does not forward packets ifselves.
+
<tag>source address <m/ip/</tag> Define local address we should use
for next hop calculation. Default: the address of the local end
of the interface our neighbor is connected to.
@@ -920,7 +936,7 @@ for each neighbor using the following configuration parameters:
as a route server client. A route server is used as a
replacement for full mesh EBGP routing in Internet exchange
points in a similar way to route reflectors used in IBGP routing.
- Bird does not implement obsoleted RFC 1863, but uses ad-hoc implementation,
+ BIRD does not implement obsoleted RFC 1863, but uses ad-hoc implementation,
which behaves like plain EBGP but reduces modifications to advertised route
attributes to be transparent (for example does not prepend its AS number to
AS PATH attribute and keep MED attribute). Default: disabled.
diff --git a/nest/config.Y b/nest/config.Y
index f287943..3d6f154 100644
--- a/nest/config.Y
+++ b/nest/config.Y
@@ -141,7 +141,7 @@ proto_item:
| EXPORT imexport { this_proto->out_filter = $2; }
| TABLE rtable { this_proto->table = $2; }
| ROUTER ID idval { this_proto->router_id = $3; }
- | DESCRIPTION dsc { this_proto->dsc = $2; }
+ | DESCRIPTION TEXT { this_proto->dsc = $2; }
;
imexport:
diff --git a/proto/bgp/bgp.c b/proto/bgp/bgp.c
index b38c6b1..cde0276 100644
--- a/proto/bgp/bgp.c
+++ b/proto/bgp/bgp.c
@@ -886,6 +886,10 @@ bgp_check(struct bgp_config *c)
if ((c->local_as == c->remote_as) && (c->rs_client))
cf_error("Only external neighbor can be RS client");
+
+ /* Different default based on rs_client */
+ if (c->missing_lladdr == 0)
+ c->missing_lladdr = c->rs_client ? MLL_DROP : MLL_SELF;
}
static char *bgp_state_names[] = { "Idle", "Connect", "Active", "OpenSent", "OpenConfirm", "Established", "Close" };
diff --git a/proto/bgp/bgp.h b/proto/bgp/bgp.h
index c487aaf..c4d0335 100644
--- a/proto/bgp/bgp.h
+++ b/proto/bgp/bgp.h
@@ -23,6 +23,7 @@ struct bgp_config {
ip_addr multihop_via; /* Multihop: address to route to */
ip_addr source_addr; /* Source address to use */
int next_hop_self; /* Always set next hop to local IP address */
+ int missing_lladdr; /* What we will do when we don' know link-local addr, see MLL_* */
int compare_path_lengths; /* Use path lengths when selecting best route */
int prefer_older; /* Prefer older routes according to RFC 5004 */
u32 default_local_pref; /* Default value for LOCAL_PREF attribute */
@@ -46,6 +47,10 @@ struct bgp_config {
char *password; /* Password used for MD5 authentication */
};
+#define MLL_SELF 1
+#define MLL_DROP 2
+#define MLL_IGNORE 3
+
struct bgp_conn {
struct bgp_proto *bgp;
struct birdsock *sk;
diff --git a/proto/bgp/config.Y b/proto/bgp/config.Y
index 9401175..3576946 100644
--- a/proto/bgp/config.Y
+++ b/proto/bgp/config.Y
@@ -22,7 +22,8 @@ CF_KEYWORDS(BGP, LOCAL, NEIGHBOR, AS, HOLD, TIME, CONNECT, RETRY, KEEPALIVE,
BGP_PATH, BGP_LOCAL_PREF, BGP_MED, BGP_ORIGIN, BGP_NEXT_HOP,
BGP_ATOMIC_AGGR, BGP_AGGREGATOR, BGP_COMMUNITY, SOURCE, ADDRESS,
PASSWORD, RR, RS, CLIENT, CLUSTER, ID, AS4, ADVERTISE, IPV4,
- CAPABILITIES, LIMIT, PASSIVE, PREFER, OLDER)
+ CAPABILITIES, LIMIT, PASSIVE, PREFER, OLDER, MISSING, LLADDR,
+ DROP, IGNORE)
CF_GRAMMAR
@@ -64,6 +65,9 @@ bgp_proto:
| bgp_proto KEEPALIVE TIME expr ';' { BGP_CFG->keepalive_time = $4; }
| bgp_proto MULTIHOP expr VIA ipa ';' { BGP_CFG->multihop = $3; BGP_CFG->multihop_via = $5; }
| bgp_proto NEXT HOP SELF ';' { BGP_CFG->next_hop_self = 1; }
+ | bgp_proto MISSING LLADDR SELF ';' { BGP_CFG->missing_lladdr = MLL_SELF; }
+ | bgp_proto MISSING LLADDR DROP ';' { BGP_CFG->missing_lladdr = MLL_DROP; }
+ | bgp_proto MISSING LLADDR IGNORE ';' { BGP_CFG->missing_lladdr = MLL_IGNORE; }
| bgp_proto PATH METRIC bool ';' { BGP_CFG->compare_path_lengths = $4; }
| bgp_proto PREFER OLDER bool ';' { BGP_CFG->prefer_older = $4; }
| bgp_proto DEFAULT BGP_MED expr ';' { BGP_CFG->default_med = $4; }
diff --git a/proto/bgp/packets.c b/proto/bgp/packets.c
index d126fe5..4176c9f 100644
--- a/proto/bgp/packets.c
+++ b/proto/bgp/packets.c
@@ -199,7 +199,7 @@ bgp_create_update(struct bgp_conn *conn, byte *buf)
if (a_size < 0)
{
- log(L_ERR "%s: Attribute list too long, skipping corresponding route group", p->p.name);
+ log(L_ERR "%s: Attribute list too long, skipping corresponding routes", p->p.name);
bgp_flush_prefixes(p, buck);
rem_node(&buck->send_node);
bgp_free_bucket(p, buck);
@@ -234,9 +234,9 @@ bgp_create_update(struct bgp_conn *conn, byte *buf)
{
struct bgp_proto *p = conn->bgp;
struct bgp_bucket *buck;
- int size, second;
+ int size, second, rem_stored;
int remains = BGP_MAX_PACKET_LENGTH - BGP_HEADER_LENGTH - 4;
- byte *w, *tmp, *tstart;
+ byte *w, *w_stored, *tmp, *tstart;
ip_addr *ipp, ip, ip_ll;
ea_list *ea;
eattr *nh;
@@ -272,28 +272,25 @@ bgp_create_update(struct bgp_conn *conn, byte *buf)
}
DBG("Processing bucket %p\n", buck);
- size = bgp_encode_attrs(p, w, buck->eattrs, 2048);
+ rem_stored = remains;
+ w_stored = w;
+ size = bgp_encode_attrs(p, w, buck->eattrs, 2048);
if (size < 0)
{
- log(L_ERR "%s: Attribute list too long, ignoring corresponding route group", p->p.name);
+ log(L_ERR "%s: Attribute list too long, skipping corresponding routes", p->p.name);
bgp_flush_prefixes(p, buck);
rem_node(&buck->send_node);
bgp_free_bucket(p, buck);
continue;
}
-
w += size;
remains -= size;
- tstart = tmp = bgp_attach_attr_wa(&ea, bgp_linpool, BA_MP_REACH_NLRI, remains-8);
- *tmp++ = 0;
- *tmp++ = BGP_AF_IPV6;
- *tmp++ = 1;
- nh = ea_find(buck->eattrs, EA_CODE(EAP_BGP, BA_NEXT_HOP));
- ASSERT(nh);
- /* We have two addresses here in 'nh'. Really.
+ /* We have two addresses here in NEXT_HOP eattr. Really.
Unless NEXT_HOP was modified by filter */
+ nh = ea_find(buck->eattrs, EA_CODE(EAP_BGP, BA_NEXT_HOP));
+ ASSERT(nh);
second = (nh->u.ptr->length == NEXT_HOP_LENGTH);
ipp = (ip_addr *) nh->u.ptr->data;
ip = ipp[0];
@@ -322,12 +319,32 @@ bgp_create_update(struct bgp_conn *conn, byte *buf)
ip_ll = ipp[1];
else
{
- ip = p->source_addr;
- ip_ll = p->local_link;
+ switch (p->cf->missing_lladdr)
+ {
+ case MLL_SELF:
+ ip = p->source_addr;
+ ip_ll = p->local_link;
+ break;
+ case MLL_DROP:
+ log(L_ERR "%s: Missing link-local next hop address, skipping corresponding routes", p->p.name);
+ w = w_stored;
+ remains = rem_stored;
+ bgp_flush_prefixes(p, buck);
+ rem_node(&buck->send_node);
+ bgp_free_bucket(p, buck);
+ continue;
+ case MLL_IGNORE:
+ break;
+ }
}
}
}
+ tstart = tmp = bgp_attach_attr_wa(&ea, bgp_linpool, BA_MP_REACH_NLRI, remains-8);
+ *tmp++ = 0;
+ *tmp++ = BGP_AF_IPV6;
+ *tmp++ = 1;
+
if (ipa_nonzero(ip_ll))
{
*tmp++ = 32;