From 3f9b7bfe9ff050430a5886b22a5ab11b5f253048 Mon Sep 17 00:00:00 2001 From: Ondrej Zajicek Date: Wed, 18 Nov 2009 20:32:36 +0100 Subject: Implements option that controls IPv6 BGP next hops when lladdr is missing. --- doc/bird.sgml | 28 ++++++++++++++++++++++------ nest/config.Y | 2 +- proto/bgp/bgp.c | 4 ++++ proto/bgp/bgp.h | 5 +++++ proto/bgp/config.Y | 6 +++++- proto/bgp/packets.c | 47 ++++++++++++++++++++++++++++++++--------------- 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 1.0.0.0/16 ˜ [ 1.0.0.0/8- ] is false. Cisco-style patterns like 10.0.0.0/8 ge 16 le 24 can be expressed - in Bird as 10.0.0.0/8{16,24}, 192.168.0.0/16 le 24 as + in BIRD as 10.0.0.0/8{16,24}, 192.168.0.0/16 le 24 as 192.168.0.0/16{16,24} and 192.168.0.0/16 ge 24 as 192.168.0.0/16{24,32}. @@ -887,12 +887,28 @@ for each neighbor using the following configuration parameters: we should route via our direct neighbor with address next hop self 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. + next hop self 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. + missing lladdr self|drop|ignoreNext 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. source address 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; -- cgit v1.2.3