Implements option that controls IPv6 BGP next hops when lladdr is missing.

This commit is contained in:
Ondrej Zajicek 2009-11-18 20:32:36 +01:00
parent 62aa96caa2
commit 3f9b7bfe9f
6 changed files with 69 additions and 23 deletions

View file

@ -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. 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 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{16,24}</cf> and <cf>192.168.0.0/16 ge 24</cf> as
<cf>192.168.0.0/16{24,32}</cf>. <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/. we should route via our direct neighbor with address <m/ip/.
Default: switched off. Default: switched off.
<tag>next hop self</tag> Avoid calculation of the Next Hop attribute <tag>next hop self</tag> Avoid calculation of the Next Hop
and always advertise our own source address (see below) as a next hop. attribute and always advertise our own source address (see
This needs to be used only below) as a next hop. This needs to be used only occasionally
occasionally to circumvent misconfigurations of other routers. to circumvent misconfigurations of other routers.
Default: disabled. 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 <tag>source address <m/ip/</tag> Define local address we should use
for next hop calculation. Default: the address of the local end for next hop calculation. Default: the address of the local end
of the interface our neighbor is connected to. 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 as a route server client. A route server is used as a
replacement for full mesh EBGP routing in Internet exchange replacement for full mesh EBGP routing in Internet exchange
points in a similar way to route reflectors used in IBGP routing. 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 which behaves like plain EBGP but reduces modifications to advertised route
attributes to be transparent (for example does not prepend its AS number to attributes to be transparent (for example does not prepend its AS number to
AS PATH attribute and keep MED attribute). Default: disabled. AS PATH attribute and keep MED attribute). Default: disabled.

View file

@ -141,7 +141,7 @@ proto_item:
| EXPORT imexport { this_proto->out_filter = $2; } | EXPORT imexport { this_proto->out_filter = $2; }
| TABLE rtable { this_proto->table = $2; } | TABLE rtable { this_proto->table = $2; }
| ROUTER ID idval { this_proto->router_id = $3; } | ROUTER ID idval { this_proto->router_id = $3; }
| DESCRIPTION dsc { this_proto->dsc = $2; } | DESCRIPTION TEXT { this_proto->dsc = $2; }
; ;
imexport: imexport:

View file

@ -886,6 +886,10 @@ bgp_check(struct bgp_config *c)
if ((c->local_as == c->remote_as) && (c->rs_client)) if ((c->local_as == c->remote_as) && (c->rs_client))
cf_error("Only external neighbor can be 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" }; static char *bgp_state_names[] = { "Idle", "Connect", "Active", "OpenSent", "OpenConfirm", "Established", "Close" };

View file

@ -23,6 +23,7 @@ struct bgp_config {
ip_addr multihop_via; /* Multihop: address to route to */ ip_addr multihop_via; /* Multihop: address to route to */
ip_addr source_addr; /* Source address to use */ ip_addr source_addr; /* Source address to use */
int next_hop_self; /* Always set next hop to local IP address */ 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 compare_path_lengths; /* Use path lengths when selecting best route */
int prefer_older; /* Prefer older routes according to RFC 5004 */ int prefer_older; /* Prefer older routes according to RFC 5004 */
u32 default_local_pref; /* Default value for LOCAL_PREF attribute */ u32 default_local_pref; /* Default value for LOCAL_PREF attribute */
@ -46,6 +47,10 @@ struct bgp_config {
char *password; /* Password used for MD5 authentication */ char *password; /* Password used for MD5 authentication */
}; };
#define MLL_SELF 1
#define MLL_DROP 2
#define MLL_IGNORE 3
struct bgp_conn { struct bgp_conn {
struct bgp_proto *bgp; struct bgp_proto *bgp;
struct birdsock *sk; struct birdsock *sk;

View file

@ -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_PATH, BGP_LOCAL_PREF, BGP_MED, BGP_ORIGIN, BGP_NEXT_HOP,
BGP_ATOMIC_AGGR, BGP_AGGREGATOR, BGP_COMMUNITY, SOURCE, ADDRESS, BGP_ATOMIC_AGGR, BGP_AGGREGATOR, BGP_COMMUNITY, SOURCE, ADDRESS,
PASSWORD, RR, RS, CLIENT, CLUSTER, ID, AS4, ADVERTISE, IPV4, 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 CF_GRAMMAR
@ -64,6 +65,9 @@ bgp_proto:
| bgp_proto KEEPALIVE TIME expr ';' { BGP_CFG->keepalive_time = $4; } | 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 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 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 PATH METRIC bool ';' { BGP_CFG->compare_path_lengths = $4; }
| bgp_proto PREFER OLDER bool ';' { BGP_CFG->prefer_older = $4; } | bgp_proto PREFER OLDER bool ';' { BGP_CFG->prefer_older = $4; }
| bgp_proto DEFAULT BGP_MED expr ';' { BGP_CFG->default_med = $4; } | bgp_proto DEFAULT BGP_MED expr ';' { BGP_CFG->default_med = $4; }

View file

@ -199,7 +199,7 @@ bgp_create_update(struct bgp_conn *conn, byte *buf)
if (a_size < 0) 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); bgp_flush_prefixes(p, buck);
rem_node(&buck->send_node); rem_node(&buck->send_node);
bgp_free_bucket(p, buck); 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_proto *p = conn->bgp;
struct bgp_bucket *buck; struct bgp_bucket *buck;
int size, second; int size, second, rem_stored;
int remains = BGP_MAX_PACKET_LENGTH - BGP_HEADER_LENGTH - 4; 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; ip_addr *ipp, ip, ip_ll;
ea_list *ea; ea_list *ea;
eattr *nh; eattr *nh;
@ -272,28 +272,25 @@ bgp_create_update(struct bgp_conn *conn, byte *buf)
} }
DBG("Processing bucket %p\n", buck); 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) 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); bgp_flush_prefixes(p, buck);
rem_node(&buck->send_node); rem_node(&buck->send_node);
bgp_free_bucket(p, buck); bgp_free_bucket(p, buck);
continue; continue;
} }
w += size; w += size;
remains -= size; remains -= size;
tstart = tmp = bgp_attach_attr_wa(&ea, bgp_linpool, BA_MP_REACH_NLRI, remains-8);
*tmp++ = 0; /* We have two addresses here in NEXT_HOP eattr. Really.
*tmp++ = BGP_AF_IPV6; Unless NEXT_HOP was modified by filter */
*tmp++ = 1;
nh = ea_find(buck->eattrs, EA_CODE(EAP_BGP, BA_NEXT_HOP)); nh = ea_find(buck->eattrs, EA_CODE(EAP_BGP, BA_NEXT_HOP));
ASSERT(nh); ASSERT(nh);
/* We have two addresses here in 'nh'. Really.
Unless NEXT_HOP was modified by filter */
second = (nh->u.ptr->length == NEXT_HOP_LENGTH); second = (nh->u.ptr->length == NEXT_HOP_LENGTH);
ipp = (ip_addr *) nh->u.ptr->data; ipp = (ip_addr *) nh->u.ptr->data;
ip = ipp[0]; ip = ipp[0];
@ -322,12 +319,32 @@ bgp_create_update(struct bgp_conn *conn, byte *buf)
ip_ll = ipp[1]; ip_ll = ipp[1];
else else
{ {
ip = p->source_addr; switch (p->cf->missing_lladdr)
ip_ll = p->local_link; {
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)) if (ipa_nonzero(ip_ll))
{ {
*tmp++ = 32; *tmp++ = 32;