diff options
Diffstat (limited to 'proto/bgp')
-rw-r--r-- | proto/bgp/attrs.c | 6 | ||||
-rw-r--r-- | proto/bgp/bgp.c | 20 | ||||
-rw-r--r-- | proto/bgp/bgp.h | 2 | ||||
-rw-r--r-- | proto/bgp/config.Y | 3 | ||||
-rw-r--r-- | proto/bgp/packets.c | 32 |
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) |