summaryrefslogtreecommitdiff
path: root/proto/bgp
diff options
context:
space:
mode:
authorOndrej Zajicek <santiago@crfreenet.org>2010-07-05 17:50:19 +0200
committerOndrej Zajicek <santiago@crfreenet.org>2010-07-05 17:50:19 +0200
commitcfe34a316e35a209fcd814ccf3523c262e8d4b0a (patch)
tree29046cfeb797ade6a3c879b5d58f93cd414ab14d /proto/bgp
parent824de84d48eff6cbd0c550309fbd0bbf7740cb14 (diff)
Implements hostcache and recursive next hops.
Hostcache is a structure for monitoring changes in a routing table that is used for routes with dynamic/recursive next hops. This is needed for proper iBGP next hop handling.
Diffstat (limited to 'proto/bgp')
-rw-r--r--proto/bgp/attrs.c6
-rw-r--r--proto/bgp/bgp.c20
-rw-r--r--proto/bgp/bgp.h2
-rw-r--r--proto/bgp/config.Y3
-rw-r--r--proto/bgp/packets.c32
5 files changed, 41 insertions, 22 deletions
diff --git a/proto/bgp/attrs.c b/proto/bgp/attrs.c
index c1b8fd1e..8743358e 100644
--- a/proto/bgp/attrs.c
+++ b/proto/bgp/attrs.c
@@ -1265,15 +1265,13 @@ bgp_decode_attrs(struct bgp_conn *conn, byte *attr, unsigned int len, struct lin
ea_list *ea;
struct adata *ad;
+ bzero(a, sizeof(rta));
a->proto = &bgp->p;
a->source = RTS_BGP;
a->scope = SCOPE_UNIVERSE;
a->cast = RTC_UNICAST;
- a->dest = RTD_ROUTER;
- a->flags = 0;
- a->aflags = 0;
+ /* a->dest = RTD_ROUTER; -- set in bgp_set_next_hop() */
a->from = bgp->cf->remote_ip;
- a->eattrs = NULL;
/* Parse the attributes */
bzero(seen, sizeof(seen));
diff --git a/proto/bgp/bgp.c b/proto/bgp/bgp.c
index 932c8aa3..b36c4a3d 100644
--- a/proto/bgp/bgp.c
+++ b/proto/bgp/bgp.c
@@ -786,6 +786,8 @@ bgp_start(struct proto *P)
p->incoming_conn.state = BS_IDLE;
p->neigh = NULL;
+ rt_lock_table(p->igp_table);
+
p->event = ev_new(p->p.pool);
p->event->hook = bgp_decision;
p->event->data = p;
@@ -837,6 +839,19 @@ bgp_shutdown(struct proto *P)
return p->p.proto_state;
}
+static void
+bgp_cleanup(struct proto *P)
+{
+ struct bgp_proto *p = (struct bgp_proto *) P;
+ rt_unlock_table(p->igp_table);
+}
+
+static rtable *
+get_igp_table(struct bgp_config *cf)
+{
+ return cf->igp_table ? cf->igp_table->table : cf->c.table->table;
+}
+
static struct proto *
bgp_init(struct proto_config *C)
{
@@ -854,6 +869,7 @@ bgp_init(struct proto_config *C)
p->local_as = c->local_as;
p->remote_as = c->remote_as;
p->is_internal = (c->local_as == c->remote_as);
+ p->igp_table = get_igp_table(c);
return P;
}
@@ -1065,7 +1081,8 @@ bgp_reconfigure(struct proto *P, struct proto_config *C)
// password item is last and must be checked separately
OFFSETOF(struct bgp_config, password) - sizeof(struct proto_config))
&& ((!old->password && !new->password)
- || (old->password && new->password && !strcmp(old->password, new->password)));
+ || (old->password && new->password && !strcmp(old->password, new->password)))
+ && (get_igp_table(old) == get_igp_table(new));
/* We should update our copy of configuration ptr as old configuration will be freed */
if (same)
@@ -1081,6 +1098,7 @@ struct protocol proto_bgp = {
init: bgp_init,
start: bgp_start,
shutdown: bgp_shutdown,
+ cleanup: bgp_cleanup,
reconfigure: bgp_reconfigure,
get_status: bgp_get_status,
get_attr: bgp_get_attr,
diff --git a/proto/bgp/bgp.h b/proto/bgp/bgp.h
index c81fe624..76844af3 100644
--- a/proto/bgp/bgp.h
+++ b/proto/bgp/bgp.h
@@ -47,6 +47,7 @@ struct bgp_config {
unsigned error_delay_time_max;
unsigned disable_after_error; /* Disable the protocol when error is detected */
char *password; /* Password used for MD5 authentication */
+ struct rtable_config *igp_table; /* Table used for recursive next hop lookups */
};
#define MLL_SELF 1
@@ -92,6 +93,7 @@ struct bgp_proto {
struct neighbor *neigh; /* Neighbor entry corresponding to next_hop */
ip_addr local_addr; /* Address of the local end of the link to next_hop */
ip_addr source_addr; /* Address used as advertised next hop, usually local_addr */
+ rtable *igp_table; /* Table used for recursive next hop lookups */
struct event *event; /* Event for respawning and shutting process */
struct timer *startup_timer; /* Timer used to delay protocol startup due to previous errors (startup_delay) */
struct bgp_bucket **bucket_hash; /* Hash table of attribute buckets */
diff --git a/proto/bgp/config.Y b/proto/bgp/config.Y
index c4ed1032..a46431cb 100644
--- a/proto/bgp/config.Y
+++ b/proto/bgp/config.Y
@@ -24,7 +24,7 @@ CF_KEYWORDS(BGP, LOCAL, NEIGHBOR, AS, HOLD, TIME, CONNECT, RETRY, KEEPALIVE,
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)
+ BGP_ORIGINATOR_ID, BGP_CLUSTER_LIST, IGP, TABLE)
CF_GRAMMAR
@@ -89,6 +89,7 @@ bgp_proto:
| bgp_proto ROUTE LIMIT expr ';' { BGP_CFG->route_limit = $4; }
| bgp_proto PASSIVE bool ';' { BGP_CFG->passive = $3; }
| bgp_proto INTERPRET COMMUNITIES bool ';' { BGP_CFG->interpret_communities = $4; }
+ | bgp_proto IGP TABLE rtable ';' { BGP_CFG->igp_table = $4; }
;
CF_ADDTO(dynamic_attr, BGP_ORIGIN
diff --git a/proto/bgp/packets.c b/proto/bgp/packets.c
index 1e9d6465..514e878d 100644
--- a/proto/bgp/packets.c
+++ b/proto/bgp/packets.c
@@ -802,26 +802,26 @@ bgp_rx_open(struct bgp_conn *conn, byte *pkt, int len)
} while (0)
static inline int
-bgp_get_nexthop(struct bgp_proto *bgp, rta *a)
+bgp_set_next_hop(struct bgp_proto *p, rta *a)
{
- neighbor *neigh;
- ip_addr nexthop;
struct eattr *nh = ea_find(a->eattrs, EA_CODE(EAP_BGP, BA_NEXT_HOP));
- ASSERT(nh);
- nexthop = *(ip_addr *) nh->u.ptr->data;
- neigh = neigh_find(&bgp->p, &nexthop, 0);
- if (neigh)
+ ip_addr nexthop = *(ip_addr *) nh->u.ptr->data;
+
+ if (!p->is_internal) /* FIXME better option
+ */
{
- if (neigh->scope == SCOPE_HOST)
- {
- DBG("BGP: Loop!\n");
- return 0;
- }
+ neighbor *ng = neigh_find(&p->p, &nexthop, 0) ? : p->neigh;
+ if (ng->scope == SCOPE_HOST)
+ return 0;
+
+ a->dest = RTD_ROUTER;
+ a->gw = ng->addr;
+ a->iface = ng->iface;
+ a->hostentry = NULL;
}
else
- neigh = bgp->neigh;
- a->gw = neigh->addr;
- a->iface = neigh->iface;
+ rta_set_recursive_next_hop(p->p.table, a, p->igp_table, &nexthop);
+
return 1;
}
@@ -853,7 +853,7 @@ bgp_do_rx_update(struct bgp_conn *conn,
return;
a0 = bgp_decode_attrs(conn, attrs, attr_len, bgp_linpool, nlri_len);
- if (a0 && nlri_len && bgp_get_nexthop(p, a0))
+ if (a0 && nlri_len && bgp_set_next_hop(p, a0))
{
a = rta_lookup(a0);
while (nlri_len)