diff options
Diffstat (limited to 'proto/bgp')
-rw-r--r-- | proto/bgp/bgp.c | 40 | ||||
-rw-r--r-- | proto/bgp/bgp.h | 11 | ||||
-rw-r--r-- | proto/bgp/packets.c | 84 |
3 files changed, 82 insertions, 53 deletions
diff --git a/proto/bgp/bgp.c b/proto/bgp/bgp.c index 1ae56397..0a2e8f5a 100644 --- a/proto/bgp/bgp.c +++ b/proto/bgp/bgp.c @@ -380,10 +380,20 @@ bgp_close_conn(struct bgp_conn *conn) rfree(conn->sk); conn->sk = NULL; + mb_free(conn->local_open_msg); + conn->local_open_msg = NULL; + mb_free(conn->remote_open_msg); + conn->remote_open_msg = NULL; + conn->local_open_length = 0; + conn->remote_open_length = 0; + mb_free(conn->local_caps); conn->local_caps = NULL; mb_free(conn->remote_caps); conn->remote_caps = NULL; + + conn->notify_data = NULL; + conn->notify_size = 0; } @@ -682,10 +692,12 @@ bgp_conn_enter_established_state(struct bgp_conn *conn) bgp_conn_set_state(conn, BS_ESTABLISHED); proto_notify_state(&p->p, PS_UP); + bmp_peer_up(p, conn->local_open_msg, conn->local_open_length, + conn->remote_open_msg, conn->remote_open_length); } static void -bgp_conn_leave_established_state(struct bgp_proto *p) +bgp_conn_leave_established_state(struct bgp_conn *conn, struct bgp_proto *p) { BGP_TRACE(D_EVENTS, "BGP session closed"); p->last_established = current_time(); @@ -693,6 +705,10 @@ bgp_conn_leave_established_state(struct bgp_proto *p) if (p->p.proto_state == PS_UP) bgp_stop(p, 0, NULL, 0); + + bmp_peer_down(p, p->last_error_class, + conn->notify_code, conn->notify_subcode, + conn->notify_data, conn->notify_size); } void @@ -709,7 +725,7 @@ bgp_conn_enter_close_state(struct bgp_conn *conn) bgp_start_timer(conn->hold_timer, 10); if (os == BS_ESTABLISHED) - bgp_conn_leave_established_state(p); + bgp_conn_leave_established_state(conn, p); } void @@ -723,7 +739,7 @@ bgp_conn_enter_idle_state(struct bgp_conn *conn) ev_schedule(p->event); if (os == BS_ESTABLISHED) - bgp_conn_leave_established_state(p); + bgp_conn_leave_established_state(conn, p); } /** @@ -867,10 +883,7 @@ bgp_graceful_restart_timeout(timer *t) } } else - { bgp_stop(p, 0, NULL, 0); - bmp_peer_down(p, BE_NONE, NULL, 0); - } } static void @@ -994,10 +1007,7 @@ bgp_sock_err(sock *sk, int err) if (err) BGP_TRACE(D_EVENTS, "Connection lost (%M)", err); else - { BGP_TRACE(D_EVENTS, "Connection closed"); - bmp_peer_down(p, BE_SOCKET, NULL, 0); - } if ((conn->state == BS_ESTABLISHED) && p->gr_ready) bgp_handle_graceful_restart(p); @@ -1322,7 +1332,6 @@ bgp_neigh_notify(neighbor *n) bgp_store_error(p, NULL, BE_MISC, BEM_NEIGHBOR_LOST); /* Perhaps also run bgp_update_startup_delay(p)? */ bgp_stop(p, 0, NULL, 0); - bmp_peer_down(p, BE_MISC, NULL, 0); } } else if (p->cf->check_link && !(n->iface->flags & IF_LINK_UP)) @@ -1334,7 +1343,6 @@ bgp_neigh_notify(neighbor *n) if (ps == PS_UP) bgp_update_startup_delay(p); bgp_stop(p, 0, NULL, 0); - bmp_peer_down(p, BE_MISC, NULL, 0); } } else @@ -1376,7 +1384,6 @@ bgp_bfd_notify(struct bfd_request *req) if (ps == PS_UP) bgp_update_startup_delay(p); bgp_stop(p, 0, NULL, 0); - bmp_peer_down(p, BE_MISC, NULL, 0); } } } @@ -1705,10 +1712,6 @@ bgp_init(struct proto_config *CF) P->rte_modify = bgp_rte_modify_stale; P->rte_igp_metric = bgp_rte_igp_metric; -#ifdef CONFIG_BMP - P->rte_update_in_notify = bgp_rte_update_in_notify; -#endif - p->cf = cf; p->is_internal = (cf->local_as == cf->remote_as); p->is_interior = p->is_internal || cf->confederation_member; @@ -2261,12 +2264,13 @@ bgp_error(struct bgp_conn *c, uint code, uint subcode, byte *data, int len) bgp_log_error(p, BE_BGP_TX, "Error", code, subcode, data, ABS(len)); bgp_store_error(p, c, BE_BGP_TX, (code << 16) | subcode); - bgp_conn_enter_close_state(c); c->notify_code = code; c->notify_subcode = subcode; c->notify_data = data; c->notify_size = (len > 0) ? len : 0; + + bgp_conn_enter_close_state(c); bgp_schedule_packet(c, NULL, PKT_NOTIFICATION); if (code != 6) @@ -2634,7 +2638,7 @@ bgp_show_proto_info(struct proto *P) } } -struct channel_class channel_bgp = { +const struct channel_class channel_bgp = { .channel_size = sizeof(struct bgp_channel), .config_size = sizeof(struct bgp_channel_config), .init = bgp_channel_init, diff --git a/proto/bgp/bgp.h b/proto/bgp/bgp.h index 0fb375d5..c11433ec 100644 --- a/proto/bgp/bgp.h +++ b/proto/bgp/bgp.h @@ -287,6 +287,11 @@ struct bgp_conn { u8 ext_messages; /* Session uses extended message length */ u32 received_as; /* ASN received in OPEN message */ + byte *local_open_msg; /* Saved OPEN messages (no header) */ + byte *remote_open_msg; + uint local_open_length; + uint remote_open_length; + struct bgp_caps *local_caps; struct bgp_caps *remote_caps; timer *connect_timer; @@ -487,6 +492,7 @@ struct bgp_parse_state { #define BGP_PORT 179 #define BGP_VERSION 4 #define BGP_HEADER_LENGTH 19 +#define BGP_HDR_MARKER_LENGTH 16 #define BGP_MAX_MESSAGE_LENGTH 4096 #define BGP_MAX_EXT_MSG_LENGTH 65535 #define BGP_RX_BUFFER_SIZE 4096 @@ -625,11 +631,12 @@ struct rte *bgp_rte_modify_stale(struct rte *r, struct linpool *pool); u32 bgp_rte_igp_metric(struct rte *); void bgp_rt_notify(struct proto *P, struct channel *C, net *n, rte *new, rte *old); int bgp_preexport(struct channel *, struct rte *); -void bgp_rte_update_in_notify(struct channel *C, const net_addr *n, const struct rte *new, const struct rte_src *src); int bgp_get_attr(const struct eattr *e, byte *buf, int buflen); void bgp_get_route_info(struct rte *, byte *buf); int bgp_total_aigp_metric_(rte *e, u64 *metric, const struct adata **ad); +byte * bgp_bmp_encode_rte(struct bgp_channel *c, byte *buf, const net_addr *n, const struct rte *new, const struct rte_src *src); + #define BGP_AIGP_METRIC 1 #define BGP_AIGP_MAX U64(0xffffffffffffffff) @@ -658,8 +665,8 @@ const char * bgp_error_dsc(unsigned code, unsigned subcode); void bgp_log_error(struct bgp_proto *p, u8 class, char *msg, unsigned code, unsigned subcode, byte *data, unsigned len); void bgp_update_next_hop(struct bgp_export_state *s, eattr *a, ea_list **to); +byte *bgp_create_end_mark_(struct bgp_channel *c, byte *buf); -byte * bgp_create_end_mark(struct bgp_channel *c, byte *buf); /* Packet types */ diff --git a/proto/bgp/packets.c b/proto/bgp/packets.c index 66f243bd..ee98115d 100644 --- a/proto/bgp/packets.c +++ b/proto/bgp/packets.c @@ -167,7 +167,6 @@ bgp_create_notification(struct bgp_conn *conn, byte *buf) buf[0] = conn->notify_code; buf[1] = conn->notify_subcode; memcpy(buf+2, conn->notify_data, conn->notify_size); - bmp_peer_down(p, BE_NONE, buf, conn->notify_size + 2); return buf + 2 + conn->notify_size; } @@ -777,6 +776,14 @@ err: } static byte * +bgp_copy_open(struct bgp_proto *p, const byte *pkt, uint len) +{ + char *buf = mb_alloc(p->p.pool, len - BGP_HEADER_LENGTH); + memcpy(buf, pkt + BGP_HEADER_LENGTH, len - BGP_HEADER_LENGTH); + return buf; +} + +static byte * bgp_create_open(struct bgp_conn *conn, byte *buf) { struct bgp_proto *p = conn->bgp; @@ -850,6 +857,9 @@ bgp_rx_open(struct bgp_conn *conn, byte *pkt, uint len) id = get_u32(pkt+24); BGP_TRACE(D_PACKETS, "Got OPEN(as=%d,hold=%d,id=%R)", asn, hold, id); + conn->remote_open_msg = bgp_copy_open(p, pkt, len); + conn->remote_open_length = len - BGP_HEADER_LENGTH; + if (bgp_read_options(conn, pkt+29, pkt[28], len-29) < 0) return; @@ -981,7 +991,6 @@ bgp_rx_open(struct bgp_conn *conn, byte *pkt, uint len) bgp_schedule_packet(conn, NULL, PKT_KEEPALIVE); bgp_start_timer(conn->hold_timer, conn->hold_time); bgp_conn_enter_openconfirm_state(conn); - bmp_put_recv_bgp_open_msg(p, pkt, len); } @@ -2419,15 +2428,20 @@ bgp_create_update_bmp(struct bgp_channel *c, byte *buf, struct bgp_bucket *buck, { struct bgp_proto *p = (void *) c->c.proto; byte *end = buf + (BGP_MAX_EXT_MSG_LENGTH - BGP_HEADER_LENGTH); + byte *res = NULL; /* FIXME: must be a bit shorter */ + struct lp_state tmpp; + lp_save(tmp_linpool, &tmpp); + struct bgp_caps *peer = p->conn->remote_caps; const struct bgp_af_caps *rem = bgp_find_af_caps(peer, c->afi); + struct bgp_write_state s = { .proto = p, .channel = c, .pool = tmp_linpool, - .mp_reach = (c->afi != BGP_AF_IPV4) || rem->ext_next_hop, + .mp_reach = (c->afi != BGP_AF_IPV4) || (rem && rem->ext_next_hop), .as4_session = 1, .add_path = c->add_path_rx, .mpls = c->desc->mpls, @@ -2436,16 +2450,20 @@ bgp_create_update_bmp(struct bgp_channel *c, byte *buf, struct bgp_bucket *buck, if (!update) { - return !s.mp_reach ? + res = !s.mp_reach ? bgp_create_ip_unreach(&s, buck, buf, end): bgp_create_mp_unreach(&s, buck, buf, end); } else { - return !s.mp_reach ? + res = !s.mp_reach ? bgp_create_ip_reach(&s, buck, buf, end): bgp_create_mp_reach(&s, buck, buf, end); } + + lp_restore(tmp_linpool, &tmpp); + + return res; } static byte * @@ -2458,14 +2476,11 @@ bgp_bmp_prepare_bgp_hdr(byte *buf, const u16 msg_size, const u8 msg_type) return buf + BGP_MSG_HDR_TYPE_POS + BGP_MSG_HDR_TYPE_SIZE; } -void -bgp_rte_update_in_notify(struct channel *C, const net_addr *n, - const struct rte *new, const struct rte_src *src) +byte * +bgp_bmp_encode_rte(struct bgp_channel *c, byte *buf, const net_addr *n, + const struct rte *new, const struct rte_src *src) { -// struct bgp_proto *p = (void *) C->proto; - struct bgp_channel *c = (void *) C; - - byte buf[BGP_MAX_EXT_MSG_LENGTH]; +// struct bgp_proto *p = (void *) c->c.proto; byte *pkt = buf + BGP_HEADER_LENGTH; ea_list *attrs = new ? new->attrs->eattrs : NULL; @@ -2489,11 +2504,11 @@ bgp_rte_update_in_notify(struct channel *C, const net_addr *n, add_tail(&b->prefixes, &px->buck_node); byte *end = bgp_create_update_bmp(c, pkt, b, !!new); - if (!end) - return; - bgp_bmp_prepare_bgp_hdr(buf, end - buf, PKT_UPDATE); - bmp_route_monitor_put_update_in_pre_msg(buf, end - buf); + if (end) + bgp_bmp_prepare_bgp_hdr(buf, end - buf, PKT_UPDATE); + + return end; } #endif /* CONFIG_BMP */ @@ -2600,6 +2615,14 @@ bgp_create_mp_end_mark(struct bgp_channel *c, byte *buf) } byte * +bgp_create_end_mark_(struct bgp_channel *c, byte *buf) +{ + return (c->afi == BGP_AF_IPV4) ? + bgp_create_ip_end_mark(c, buf): + bgp_create_mp_end_mark(c, buf); +} + +static byte * bgp_create_end_mark(struct bgp_channel *c, byte *buf) { struct bgp_proto *p = (void *) c->c.proto; @@ -2607,9 +2630,7 @@ bgp_create_end_mark(struct bgp_channel *c, byte *buf) BGP_TRACE(D_PACKETS, "Sending END-OF-RIB"); p->stats.tx_updates++; - return (c->afi == BGP_AF_IPV4) ? - bgp_create_ip_end_mark(c, buf): - bgp_create_mp_end_mark(c, buf); + return bgp_create_end_mark_(c, buf); } static inline void @@ -2750,8 +2771,6 @@ bgp_rx_update(struct bgp_conn *conn, byte *pkt, uint len) s.ip_reach_len = len - pos; s.ip_reach_nlri = pkt + pos; - bmp_route_monitor_update_in_pre_begin(); - if (s.attr_len) ea = bgp_decode_attrs(&s, s.attrs, s.attr_len); else @@ -2782,9 +2801,6 @@ bgp_rx_update(struct bgp_conn *conn, byte *pkt, uint len) bgp_decode_nlri(&s, s.mp_reach_af, s.mp_reach_nlri, s.mp_reach_len, ea, s.mp_next_hop_data, s.mp_next_hop_len); - bmp_route_monitor_update_in_pre_commit(p); - bmp_route_monitor_update_in_pre_end(); - done: rta_free(s.cached_rta); lp_restore(tmp_linpool, &tmpp); @@ -2988,7 +3004,7 @@ bgp_send(struct bgp_conn *conn, uint type, uint len) conn->bgp->stats.tx_messages++; conn->bgp->stats.tx_bytes += len; - memset(buf, 0xff, 16); /* Marker */ + memset(buf, 0xff, BGP_HDR_MARKER_LENGTH); put_u16(buf+16, len); buf[18] = type; @@ -3036,12 +3052,11 @@ bgp_fire_tx(struct bgp_conn *conn) { conn->packets_to_send &= ~(1 << PKT_OPEN); end = bgp_create_open(conn, pkt); - int rv = bgp_send(conn, PKT_OPEN, end - buf); - if (rv >= 0) - { - bmp_put_sent_bgp_open_msg(p, pkt, end - buf); - } - return rv; + + conn->local_open_msg = bgp_copy_open(p, buf, end - buf); + conn->local_open_length = end - buf - BGP_HEADER_LENGTH; + + return bgp_send(conn, PKT_OPEN, end - buf); } else if (s & (1 << PKT_KEEPALIVE)) { @@ -3322,6 +3337,11 @@ bgp_rx_notification(struct bgp_conn *conn, byte *pkt, uint len) bgp_log_error(p, BE_BGP_RX, "Received", code, subcode, pkt+21, len-21); bgp_store_error(p, conn, BE_BGP_RX, (code << 16) | subcode); + conn->notify_code = code; + conn->notify_subcode = subcode; + conn->notify_data = pkt+21; + conn->notify_size = len-21; + bgp_conn_enter_close_state(conn); bgp_schedule_packet(conn, NULL, PKT_SCHEDULE_CLOSE); @@ -3340,8 +3360,6 @@ bgp_rx_notification(struct bgp_conn *conn, byte *pkt, uint len) p->p.disabled = 1; } } - - bmp_peer_down(p, BE_NONE, pkt, len); } static void |