diff options
Diffstat (limited to 'proto/bgp')
-rw-r--r-- | proto/bgp/bgp.c | 15 | ||||
-rw-r--r-- | proto/bgp/bgp.h | 4 | ||||
-rw-r--r-- | proto/bgp/config.Y | 21 | ||||
-rw-r--r-- | proto/bgp/packets.c | 5 |
4 files changed, 30 insertions, 15 deletions
diff --git a/proto/bgp/bgp.c b/proto/bgp/bgp.c index 3aa8845..1f723ae 100644 --- a/proto/bgp/bgp.c +++ b/proto/bgp/bgp.c @@ -951,6 +951,8 @@ bgp_store_error(struct bgp_proto *p, struct bgp_conn *c, u8 class, u32 code) void bgp_check(struct bgp_config *c) { + int internal = (c->local_as == c->remote_as); + if (!c->local_as) cf_error("Local AS number must be set"); @@ -960,15 +962,22 @@ bgp_check(struct bgp_config *c) if (!(c->capabilities && c->enable_as4) && (c->remote_as > 0xFFFF)) cf_error("Neighbor AS number out of range (AS4 not available)"); - if ((c->local_as != c->remote_as) && (c->rr_client)) + if (!internal && c->rr_client) cf_error("Only internal neighbor can be RR client"); - if ((c->local_as == c->remote_as) && (c->rs_client)) + if (internal && c->rs_client) cf_error("Only external neighbor can be RS client"); + if (c->multihop && (c->gw_mode == GW_DIRECT)) + cf_error("Multihop BGP cannot use direct gateway mode"); + /* Different default based on rs_client */ - if (c->missing_lladdr == 0) + if (!c->missing_lladdr) c->missing_lladdr = c->rs_client ? MLL_DROP : MLL_SELF; + + /* Different default for gw_mode */ + if (!c->gw_mode) + c->gw_mode = (c->multihop || internal) ? GW_RECURSIVE : GW_DIRECT; } 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 160aa3d..6bb1d6e 100644 --- a/proto/bgp/bgp.h +++ b/proto/bgp/bgp.h @@ -23,6 +23,7 @@ struct bgp_config { 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 gw_mode; /* How we compute route gateway from next_hop attr, see GW_* */ 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 */ @@ -53,6 +54,9 @@ struct bgp_config { #define MLL_DROP 2 #define MLL_IGNORE 3 +#define GW_DIRECT 1 +#define GW_RECURSIVE 2 + struct bgp_conn { struct bgp_proto *bgp; struct birdsock *sk; diff --git a/proto/bgp/config.Y b/proto/bgp/config.Y index e591f89..75b9339 100644 --- a/proto/bgp/config.Y +++ b/proto/bgp/config.Y @@ -16,15 +16,16 @@ CF_DEFINES CF_DECLS -CF_KEYWORDS(BGP, LOCAL, NEIGHBOR, AS, HOLD, TIME, CONNECT, RETRY, KEEPALIVE, - MULTIHOP, STARTUP, VIA, NEXT, HOP, SELF, DEFAULT, PATH, METRIC, - ERROR, START, DELAY, FORGET, WAIT, ENABLE, DISABLE, AFTER, - 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, MISSING, LLADDR, - DROP, IGNORE, ROUTE, REFRESH, INTERPRET, COMMUNITIES, - BGP_ORIGINATOR_ID, BGP_CLUSTER_LIST, IGP, TABLE) +CF_KEYWORDS(BGP, LOCAL, NEIGHBOR, AS, HOLD, TIME, CONNECT, RETRY, + KEEPALIVE, MULTIHOP, STARTUP, VIA, NEXT, HOP, SELF, DEFAULT, + PATH, METRIC, ERROR, START, DELAY, FORGET, WAIT, ENABLE, + DISABLE, AFTER, 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, + MISSING, LLADDR, DROP, IGNORE, ROUTE, REFRESH, INTERPRET, + COMMUNITIES, BGP_ORIGINATOR_ID, BGP_CLUSTER_LIST, IGP, TABLE, + GATEWAY, DIRECT, RECURSIVE) CF_GRAMMAR @@ -74,6 +75,8 @@ bgp_proto: | 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 GATEWAY DIRECT ';' { BGP_CFG->gw_mode = GW_DIRECT; } + | bgp_proto GATEWAY RECURSIVE ';' { BGP_CFG->gw_mode = GW_RECURSIVE; } | 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 ee2c1b0..6e23022 100644 --- a/proto/bgp/packets.c +++ b/proto/bgp/packets.c @@ -807,8 +807,7 @@ bgp_set_next_hop(struct bgp_proto *p, rta *a) struct eattr *nh = ea_find(a->eattrs, EA_CODE(EAP_BGP, BA_NEXT_HOP)); ip_addr nexthop = *(ip_addr *) nh->u.ptr->data; - if (!p->is_internal) /* FIXME better option - */ + if (p->cf->gw_mode == GW_DIRECT) { neighbor *ng = neigh_find(&p->p, &nexthop, 0) ? : p->neigh; if (ng->scope == SCOPE_HOST) @@ -819,7 +818,7 @@ bgp_set_next_hop(struct bgp_proto *p, rta *a) a->iface = ng->iface; a->hostentry = NULL; } - else + else /* GW_RECURSIVE */ rta_set_recursive_next_hop(p->p.table, a, p->igp_table, &nexthop); return 1; |