From a848dad40aa618e5e24417e4ef46b62c860de679 Mon Sep 17 00:00:00 2001 From: Pawel Maslanka Date: Mon, 29 Mar 2021 22:45:21 +0200 Subject: BMP protocol support Initial implementation of a basic subset of the BMP (BGP Monitoring Protocol, RFC 7854) from Akamai team. Submitted for further review and improvement. --- proto/bgp/bgp.h | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'proto/bgp/bgp.h') diff --git a/proto/bgp/bgp.h b/proto/bgp/bgp.h index 302f58e7..c4f4f3be 100644 --- a/proto/bgp/bgp.h +++ b/proto/bgp/bgp.h @@ -496,6 +496,13 @@ struct bgp_parse_state { #define BGP_CF_WALK_CHANNELS(P,C) WALK_LIST(C, P->c.channels) if (C->c.channel == &channel_bgp) #define BGP_WALK_CHANNELS(P,C) WALK_LIST(C, P->p.channels) if (C->c.channel == &channel_bgp) +#define BGP_MSG_HDR_MARKER_SIZE 16 +#define BGP_MSG_HDR_MARKER_POS 0 +#define BGP_MSG_HDR_LENGTH_SIZE 2 +#define BGP_MSG_HDR_LENGTH_POS BGP_MSG_HDR_MARKER_SIZE +#define BGP_MSG_HDR_TYPE_SIZE 1 +#define BGP_MSG_HDR_TYPE_POS (BGP_MSG_HDR_MARKER_SIZE + BGP_MSG_HDR_LENGTH_SIZE) + static inline int bgp_channel_is_ipv4(struct bgp_channel *c) { return BGP_AFI(c->afi) == BGP_AFI_IPV4; } @@ -542,6 +549,8 @@ void bgp_store_error(struct bgp_proto *p, struct bgp_conn *c, u8 class, u32 code void bgp_stop(struct bgp_proto *p, int subcode, byte *data, uint len); const char *bgp_format_role_name(u8 role); +void bgp_fix_attr_flags(ea_list *attrs); + static inline int rte_resolvable(rte *rt) { @@ -615,6 +624,9 @@ 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(const struct proto *P, const struct channel *C, + const net *net, const struct rte *new, const struct rte *old, + 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); @@ -648,6 +660,7 @@ void bgp_log_error(struct bgp_proto *p, u8 class, char *msg, unsigned code, unsi 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); /* Packet types */ @@ -658,6 +671,7 @@ void bgp_update_next_hop(struct bgp_export_state *s, eattr *a, ea_list **to); #define PKT_ROUTE_REFRESH 0x05 /* [RFC2918] */ #define PKT_BEGIN_REFRESH 0x1e /* Dummy type for BoRR packet [RFC7313] */ #define PKT_SCHEDULE_CLOSE 0x1f /* Used internally to schedule socket close */ +#define PKT_BMP_MSG 0x20 /* BGP Monitoring Protocol message [RFC7854] */ /* Attributes */ -- cgit v1.2.3 From 4adebdf198d6e2ca1afcd7cb9bfac81725e7b24e Mon Sep 17 00:00:00 2001 From: "Ondrej Zajicek (work)" Date: Sun, 28 Mar 2021 15:36:59 +0200 Subject: BMP: Minor cleanups Remove redundant 'disable' option, simplify IP address serialization, and remove useless macros. --- proto/bgp/bgp.c | 10 +++++----- proto/bgp/bgp.h | 1 - proto/bmp/bmp.c | 42 +++++++----------------------------------- proto/bmp/bmp.h | 9 --------- proto/bmp/config.Y | 11 ++--------- 5 files changed, 14 insertions(+), 59 deletions(-) (limited to 'proto/bgp/bgp.h') diff --git a/proto/bgp/bgp.c b/proto/bgp/bgp.c index 709625ea..a6d30eff 100644 --- a/proto/bgp/bgp.c +++ b/proto/bgp/bgp.c @@ -869,7 +869,7 @@ bgp_graceful_restart_timeout(timer *t) else { bgp_stop(p, 0, NULL, 0); - bmp_peer_down(p, BE_NONE, NULL, BMP_PEER_DOWN_NULL_PKT_SIZE); + bmp_peer_down(p, BE_NONE, NULL, 0); } } @@ -996,7 +996,7 @@ bgp_sock_err(sock *sk, int err) else { BGP_TRACE(D_EVENTS, "Connection closed"); - bmp_peer_down(p, BE_SOCKET, NULL, BMP_PEER_DOWN_NULL_PKT_SIZE); + bmp_peer_down(p, BE_SOCKET, NULL, 0); } if ((conn->state == BS_ESTABLISHED) && p->gr_ready) @@ -1322,7 +1322,7 @@ 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, BMP_PEER_DOWN_NULL_PKT_SIZE); + bmp_peer_down(p, BE_MISC, NULL, 0); } } else if (p->cf->check_link && !(n->iface->flags & IF_LINK_UP)) @@ -1334,7 +1334,7 @@ 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, BMP_PEER_DOWN_NULL_PKT_SIZE); + bmp_peer_down(p, BE_MISC, NULL, 0); } } else @@ -1376,7 +1376,7 @@ 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, BMP_PEER_DOWN_NULL_PKT_SIZE); + bmp_peer_down(p, BE_MISC, NULL, 0); } } } diff --git a/proto/bgp/bgp.h b/proto/bgp/bgp.h index c4f4f3be..5f68e3de 100644 --- a/proto/bgp/bgp.h +++ b/proto/bgp/bgp.h @@ -671,7 +671,6 @@ byte * bgp_create_end_mark(struct bgp_channel *c, byte *buf); #define PKT_ROUTE_REFRESH 0x05 /* [RFC2918] */ #define PKT_BEGIN_REFRESH 0x1e /* Dummy type for BoRR packet [RFC7313] */ #define PKT_SCHEDULE_CLOSE 0x1f /* Used internally to schedule socket close */ -#define PKT_BMP_MSG 0x20 /* BGP Monitoring Protocol message [RFC7854] */ /* Attributes */ diff --git a/proto/bmp/bmp.c b/proto/bmp/bmp.c index d088226e..57112cbe 100644 --- a/proto/bmp/bmp.c +++ b/proto/bmp/bmp.c @@ -377,12 +377,12 @@ bmp_sock_err(sock *sk, int err) log(L_WARN "[BMP:%s] Socket error: %M", conn->bmp->p.name, err); } -static void -bmp_put_ip4_addr_with_padding(buffer *stream, const ip4_addr addr) +static inline void +bmp_put_ipa(buffer *stream, const ip_addr addr) { - byte padding[BMP_PADDING_IP4_ADDR_SIZE] = { 0x00 }; - bmp_put_data(stream, padding, BMP_PADDING_IP4_ADDR_SIZE); - bmp_put_ip4(stream, addr); + bmp_put_ip6(stream, ipa_is_ip4(addr) ? + ip6_build(0,0,0, ipa_to_u32(addr)) : + ipa_to_ip6(addr)); } static void @@ -434,15 +434,7 @@ bmp_per_peer_hdr_serialize(buffer *stream, const bool is_global_instance_peer, bmp_put_u8(stream, peer_flags); // TODO: Provide appropriate peer Route Distinguisher if applicable bmp_put_u64(stream, 0x00); // 0x00 - Not supported peer distinguisher - if (ipa_is_ip4(peer_addr)) - { - bmp_put_ip4_addr_with_padding(stream, ipa_to_ip4(peer_addr)); - } - else - { - bmp_put_ip6(stream, ipa_to_ip6(peer_addr)); - } - + bmp_put_ipa(stream, peer_addr); bmp_put_u32(stream, peer_as); bmp_put_u32(stream, peer_bgp_id); bmp_put_u32(stream, ts_sec); @@ -478,15 +470,7 @@ bmp_peer_up_notif_msg_serialize(buffer *stream, const bool is_peer_global, bmp_per_peer_hdr_serialize(stream, is_peer_global, true /* TODO: Hardcoded pre-policy Adj-RIB-In */, as4_support, remote_addr, peer_as, peer_bgp_id, 0, 0); // 0, 0 - No timestamp provided - if (ipa_is_ip4(local_addr)) - { - bmp_put_ip4_addr_with_padding(stream, ipa_to_ip4(local_addr)); - } - else - { - bmp_put_ip6(stream, ipa_to_ip6(local_addr)); - } - + bmp_put_ipa(stream, local_addr); bmp_put_u16(stream, local_port); bmp_put_u16(stream, remote_port); bmp_set_initial_bgp_hdr(stream, sent_msg_size, PKT_OPEN); @@ -1115,7 +1099,6 @@ bmp_init(struct proto_config *CF) p->station_port = cf->station_port; strcpy(p->sys_descr, cf->sys_descr); strcpy(p->sys_name, cf->sys_name); - p->disabled = cf->disabled; p->monitoring_rib.in_pre_policy = cf->monitoring_rib_in_pre_policy; p->monitoring_rib.in_post_policy = cf->monitoring_rib_in_post_policy; p->monitoring_rib.local = cf->monitoring_rib_local; @@ -1128,17 +1111,6 @@ bmp_start(struct proto *P) { struct bmp_proto *p = (void *) P; - if (p->disabled) - { - g_bmp = NULL; - return PS_DOWN; - } - - if (p->disabled) - { - return PS_DOWN; - } - p->conn = mb_allocz(P->pool, sizeof (struct bmp_conn)); p->conn->bmp = p; bmp_setup_socket(p->conn); diff --git a/proto/bmp/bmp.h b/proto/bmp/bmp.h index eb800f8e..73f40eb8 100644 --- a/proto/bmp/bmp.h +++ b/proto/bmp/bmp.h @@ -23,12 +23,6 @@ // Max length of MIB-II description object #define MIB_II_STR_LEN 255 -enum bmp_peer_down { - // Value of packet size of 'pkt_size' argument of bmp_peer_down() function - // used for pointing out that there was not any packet to pass - BMP_PEER_DOWN_NULL_PKT_SIZE = 0 -}; - // The following fields of this structure controls whether there will be put // specific routes into Route Monitoring message and send to BMP collector struct monitoring_rib { @@ -43,7 +37,6 @@ struct bmp_config { const char *sys_name; // sysName MIB-II [RFC1213] object ip_addr station_ip; // Monitoring station address u16 station_port; // Monitoring station TCP port - bool disabled; // Manually disabled bool monitoring_rib_in_pre_policy; // Route monitoring pre-policy Adj-Rib-In bool monitoring_rib_in_post_policy; // Route monitoring post-policy Adj-Rib-In bool monitoring_rib_local; // Route monitoring Local Rib @@ -82,10 +75,8 @@ struct bmp_proto { char sys_name[MIB_II_STR_LEN]; // sysName MIB-II [RFC1213] object ip_addr station_ip; // Monitoring station IP address u16 station_port; // Monitoring station TCP port - bool disabled; // Manually disabled struct monitoring_rib monitoring_rib; // Below fields are for internal use - int station_socket; // Socket associated with the BMP collector struct bmp_peer_map bgp_peers; // Stores 'bgp_proto' structure per BGP peer struct bmp_peer_open_msg peer_open_msg; // Stores sent and received BGP OPEN MSG per BGP peer pool *buffer_mpool; // Memory pool used for BMP buffer allocations diff --git a/proto/bmp/config.Y b/proto/bmp/config.Y index df7822ea..776d7ecc 100644 --- a/proto/bmp/config.Y +++ b/proto/bmp/config.Y @@ -25,7 +25,6 @@ proto: bmp_proto '}' ; bmp_proto_start: proto_start BMP { this_proto = proto_config_new(&proto_bmp, $1); - BMP_CFG->disabled = false; BMP_CFG->station_ip = IPA_NONE4; BMP_CFG->station_port = 0; BMP_CFG->sys_descr = "Not defined"; @@ -39,9 +38,8 @@ bmp_proto_start: proto_start BMP { bmp_station_address: /* empty */ | bmp_station_address IP ipa { - if (!BMP_CFG->disabled) - if (ipa_zero($3)) - cf_error("Invalid BMP monitoring station IP address"); + if (ipa_zero($3)) + cf_error("Invalid BMP monitoring station IP address"); BMP_CFG->station_ip = $3; } | bmp_station_address PORT expr { @@ -54,9 +52,6 @@ bmp_station_address: bmp_proto: bmp_proto_start proto_name '{' | bmp_proto proto_item ';' - | bmp_proto ENABLED bool ';' { - BMP_CFG->disabled = $3; - } | bmp_proto STATION ADDRESS bmp_station_address ';' | bmp_proto SYSTEM DESCRIPTION text ';' { if (!$4 || (strlen($4) == 0)) @@ -81,8 +76,6 @@ bmp_proto: | bmp_proto MONITORING RIB LOCAL bool ';' { BMP_CFG->monitoring_rib_local = $5; } - | bmp_proto DISABLED bool ';' { - BMP_CFG->disabled = $3; } ; CF_CODE -- cgit v1.2.3 From 4d56b70dc5facdf4b839b76bf80c93856bcbb121 Mon Sep 17 00:00:00 2001 From: "Ondrej Zajicek (work)" Date: Mon, 29 Mar 2021 04:43:04 +0200 Subject: BMP: Remove duplicate functions for update encoding Use existing BGP functions also for BMP update encoding. --- nest/protocol.h | 3 +- nest/rt-table.c | 10 +- proto/bgp/bgp.h | 5 +- proto/bgp/packets.c | 410 ++++++++++++---------------------------------------- proto/bmp/bmp.c | 8 +- 5 files changed, 101 insertions(+), 335 deletions(-) (limited to 'proto/bgp/bgp.h') diff --git a/nest/protocol.h b/nest/protocol.h index 03b8a8ec..da6d434e 100644 --- a/nest/protocol.h +++ b/nest/protocol.h @@ -214,8 +214,7 @@ struct proto { void (*if_notify)(struct proto *, unsigned flags, struct iface *i); void (*ifa_notify)(struct proto *, unsigned flags, struct ifa *a); void (*rt_notify)(struct proto *, struct channel *, struct network *net, struct rte *new, struct rte *old); - void (*rte_update_in_notify)(const struct proto *, const struct channel *, - const net *net, const struct rte *new, const struct rte *old, const struct rte_src *src); + void (*rte_update_in_notify)(struct channel *, const net_addr *, const struct rte *, const struct rte_src *); void (*neigh_notify)(struct neighbor *neigh); int (*preexport)(struct channel *, struct rte *rt); void (*reload_routes)(struct channel *); diff --git a/nest/rt-table.c b/nest/rt-table.c index 553e8223..2b065032 100644 --- a/nest/rt-table.c +++ b/nest/rt-table.c @@ -3097,7 +3097,7 @@ rte_update_in(struct channel *c, const net_addr *n, rte *new, struct rte_src *sr old->flags &= ~(REF_STALE | REF_DISCARD | REF_MODIFY); if (c->proto->rte_update_in_notify) - c->proto->rte_update_in_notify(c->proto, c, net, new, old, src); + c->proto->rte_update_in_notify(c, n, old, src); return 1; } @@ -3122,12 +3122,12 @@ rte_update_in(struct channel *c, const net_addr *n, rte *new, struct rte_src *sr if (!old) goto drop_withdraw; - if (c->proto->rte_update_in_notify) - c->proto->rte_update_in_notify(c->proto, c, net, new, old, src); - if (!net->routes) fib_delete(&tab->fib, net); + if (c->proto->rte_update_in_notify) + c->proto->rte_update_in_notify(c, n, NULL, src); + return 1; } @@ -3158,7 +3158,7 @@ rte_update_in(struct channel *c, const net_addr *n, rte *new, struct rte_src *sr tab->rt_count++; if (c->proto->rte_update_in_notify) - c->proto->rte_update_in_notify(c->proto, c, net, new, old, src); + c->proto->rte_update_in_notify(c, n, e, src); return 1; diff --git a/proto/bgp/bgp.h b/proto/bgp/bgp.h index 5f68e3de..7c96e851 100644 --- a/proto/bgp/bgp.h +++ b/proto/bgp/bgp.h @@ -434,6 +434,7 @@ struct bgp_write_state { int as4_session; int add_path; int mpls; + int sham; eattr *mp_next_hop; const adata *mpls_labels; @@ -624,9 +625,7 @@ 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(const struct proto *P, const struct channel *C, - const net *net, const struct rte *new, const struct rte *old, - const struct rte_src *src); +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); diff --git a/proto/bgp/packets.c b/proto/bgp/packets.c index bec8cd91..42016eae 100644 --- a/proto/bgp/packets.c +++ b/proto/bgp/packets.c @@ -1566,7 +1566,10 @@ bgp_encode_nlri_ip4(struct bgp_write_state *s, struct bgp_bucket *buck, byte *bu memcpy(pos, &a, b); ADVANCE(pos, size, b); - bgp_free_prefix(s->channel, px); + if (!s->sham) + bgp_free_prefix(s->channel, px); + else + rem_node(&px->buck_node); } return pos - buf; @@ -1651,7 +1654,10 @@ bgp_encode_nlri_ip6(struct bgp_write_state *s, struct bgp_bucket *buck, byte *bu memcpy(pos, &a, b); ADVANCE(pos, size, b); - bgp_free_prefix(s->channel, px); + if (!s->sham) + bgp_free_prefix(s->channel, px); + else + rem_node(&px->buck_node); } return pos - buf; @@ -1739,7 +1745,10 @@ bgp_encode_nlri_vpn4(struct bgp_write_state *s, struct bgp_bucket *buck, byte *b memcpy(pos, &a, b); ADVANCE(pos, size, b); - bgp_free_prefix(s->channel, px); + if (!s->sham) + bgp_free_prefix(s->channel, px); + else + rem_node(&px->buck_node); } return pos - buf; @@ -1836,7 +1845,10 @@ bgp_encode_nlri_vpn6(struct bgp_write_state *s, struct bgp_bucket *buck, byte *b memcpy(pos, &a, b); ADVANCE(pos, size, b); - bgp_free_prefix(s->channel, px); + if (!s->sham) + bgp_free_prefix(s->channel, px); + else + rem_node(&px->buck_node); } return pos - buf; @@ -1923,7 +1935,10 @@ bgp_encode_nlri_flow4(struct bgp_write_state *s, struct bgp_bucket *buck, byte * memcpy(pos, net->data, flen); ADVANCE(pos, size, flen); - bgp_free_prefix(s->channel, px); + if (!s->sham) + bgp_free_prefix(s->channel, px); + else + rem_node(&px->buck_node); } return pos - buf; @@ -2015,7 +2030,10 @@ bgp_encode_nlri_flow6(struct bgp_write_state *s, struct bgp_bucket *buck, byte * memcpy(pos, net->data, flen); ADVANCE(pos, size, flen); - bgp_free_prefix(s->channel, px); + if (!s->sham) + bgp_free_prefix(s->channel, px); + else + rem_node(&px->buck_node); } return pos - buf; @@ -2242,224 +2260,6 @@ bgp_update_next_hop(struct bgp_export_state *s, eattr *a, ea_list **to) #define MAX_ATTRS_LENGTH (end-buf+BGP_HEADER_LENGTH - 1024) -/** - * Following functions starting with prefix bgp_bmp_* compose BGP UPDATE messages. - * Their implementation has been adopted from relevant function without 'bmp_' part in - * their names. - */ - -// Buffer @buf should be big enough. It means that there should be available at least 19 bytes -static byte * -bgp_bmp_prepare_bgp_hdr(byte *buf, const u16 msg_size, const u8 msg_type) -{ - if (!buf) - { - return NULL; - } - - memset(buf + BGP_MSG_HDR_MARKER_POS, 0xff, BGP_MSG_HDR_MARKER_SIZE); - put_u16(buf + BGP_MSG_HDR_LENGTH_POS, msg_size); - put_u8(buf + BGP_MSG_HDR_TYPE_POS, msg_type); - - return buf + BGP_MSG_HDR_TYPE_POS + BGP_MSG_HDR_TYPE_SIZE; -} - -static uint -bgp_bmp_encode_nlri_ip4(struct bgp_write_state *s, const net *n, - const u32 path_id, byte *buf, uint size) -{ - const struct net_addr_ip4 *naddr = (net_addr_ip4 *)n->n.addr; - - byte *pos = buf; - /* Encode path ID */ - if (s->add_path) - { - put_u32(pos, path_id); - ADVANCE(pos, size, 4); - } - - /* Encode prefix length */ - *pos = naddr->pxlen; - ADVANCE(pos, size, 1); - - /* Encode MPLS labels */ - if (s->mpls) - { - bgp_encode_mpls_labels(s, s->mpls_labels, &pos, &size, pos - 1); - } - - /* Encode prefix body */ - ip4_addr a = ip4_hton(naddr->prefix); - uint b = (naddr->pxlen + 7) / 8; - memcpy(pos, &a, b); - ADVANCE(pos, size, b); - - return pos - buf; -} - -static uint -bgp_bmp_encode_nlri_ip6(struct bgp_write_state *s, const net *n, - const u32 path_id, byte *buf, uint size) -{ - if (size < BGP_NLRI_MAX) - { - return 0; - } - - const struct net_addr_ip6 *naddr = (net_addr_ip6 *)n->n.addr; - byte *pos = buf; - /* Encode path ID */ - if (s->add_path) - { - put_u32(pos, path_id); - ADVANCE(pos, size, 4); - } - - /* Encode prefix length */ - *pos = naddr->pxlen; - ADVANCE(pos, size, 1); - - /* Encode MPLS labels */ - if (s->mpls) - { - bgp_encode_mpls_labels(s, s->mpls_labels, &pos, &size, pos - 1); - } - - /* Encode prefix body */ - ip6_addr a = ip6_hton(naddr->prefix); - uint b = (naddr->pxlen + 7) / 8; - memcpy(pos, &a, b); - ADVANCE(pos, size, b); - - return pos - buf; -} - -static byte * -bgp_bmp_create_ip_reach(struct bgp_write_state *s, const net *n, - const struct rte *new, const struct rte *old, const u32 path_id, - byte *buf, uint size) -{ - /* - * 2 B Withdrawn Routes Length (zero) - * --- IPv4 Withdrawn Routes NLRI (unused) - * 2 B Total Path Attribute Length - * var Path Attributes - * var IPv4 Network Layer Reachability Information - */ - - int lr, la; // Route length, attribute length - ea_list *attrs = new ? new->attrs->eattrs : old->attrs->eattrs; - bgp_fix_attr_flags(attrs); - - la = bgp_encode_attrs(s, attrs, buf + 2, buf + size - 2); - if (la < 0) - { - /* Attribute list too long */ - log(L_ERR "Failed to encode UPDATE msg attributes"); - return NULL; - } - - put_u16(buf, la); - lr = bgp_bmp_encode_nlri_ip4(s, n, path_id, buf + 2 + la, size - (2 + la)); - - return buf + 2 + la + lr; -} - -static byte * -bgp_bmp_create_mp_reach(struct bgp_write_state *s, const net *n, - const struct rte *new, const struct rte *old, const u32 path_id, - byte *buf, uint size) -{ - /* - * 2 B IPv4 Withdrawn Routes Length (zero) - * --- IPv4 Withdrawn Routes NLRI (unused) - * 2 B Total Path Attribute Length - * 1 B MP_REACH_NLRI hdr - Attribute Flags - * 1 B MP_REACH_NLRI hdr - Attribute Type Code - * 2 B MP_REACH_NLRI hdr - Length of Attribute Data - * 2 B MP_REACH_NLRI data - Address Family Identifier - * 1 B MP_REACH_NLRI data - Subsequent Address Family Identifier - * 1 B MP_REACH_NLRI data - Length of Next Hop Network Address - * var MP_REACH_NLRI data - Network Address of Next Hop - * 1 B MP_REACH_NLRI data - Reserved (zero) - * var MP_REACH_NLRI data - Network Layer Reachability Information - * var Rest of Path Attributes - * --- IPv4 Network Layer Reachability Information (unused) - */ - - int lh, lr, la; /* Lengths of next hop, NLRI and attributes */ - - /* Begin of MP_REACH_NLRI atribute */ - buf[4] = BAF_OPTIONAL | BAF_EXT_LEN; - buf[5] = BA_MP_REACH_NLRI; - put_u16(buf+6, 0); /* Will be fixed later */ - put_af3(buf+8, s->channel->afi); - byte *pos = buf+11; - byte *end = buf + size; - /* Encode attributes to temporary buffer */ - byte *abuf = alloca(MAX_ATTRS_LENGTH); - - ea_list *attrs = new ? new->attrs->eattrs : old->attrs->eattrs; - bgp_fix_attr_flags(attrs); - - la = bgp_encode_attrs(s, attrs, abuf, abuf + MAX_ATTRS_LENGTH); - if (la < 0) - { - /* Attribute list too long */ - log(L_ERR "Failed to encode UPDATE msg attributes"); - return NULL; - } - - /* Encode the next hop */ - lh = bgp_encode_next_hop(s, s->mp_next_hop, pos+1); - *pos = lh; - pos += 1+lh; - - /* Reserved field */ - *pos++ = 0; - - /* Encode the NLRI */ - lr = bgp_bmp_encode_nlri_ip6(s, n, path_id, pos, end - (buf + la)); - pos += lr; - - /* End of MP_REACH_NLRI atribute, update data length */ - put_u16(buf+6, pos-buf-8); - - /* Copy remaining attributes */ - memcpy(pos, abuf, la); - pos += la; - - /* Initial UPDATE fields */ - put_u16(buf+0, 0); - put_u16(buf+2, pos-buf-4); - - return pos; -} - -static byte * -bgp_bmp_create_ip_unreach(struct bgp_write_state *s, const net *n, - const struct rte *new, const struct rte *old, const u32 path_id, - byte *buf, uint size) -{ - /* - * 2 B Withdrawn Routes Length - * var IPv4 Withdrawn Routes NLRI - * 2 B Total Path Attribute Length (zero) - * --- Path Attributes (unused) - * --- IPv4 Network Layer Reachability Information (unused) - */ - - uint len = 0; - bool is_withdrawn = !new && old; - if (is_withdrawn) - { - len = bgp_bmp_encode_nlri_ip4(s, n, path_id, buf + 2, size - 2); - } - - put_u16(buf, len); - return buf + 2 + len; -} - static byte * bgp_create_ip_reach(struct bgp_write_state *s, struct bgp_bucket *buck, byte *buf, byte *end) { @@ -2477,7 +2277,8 @@ bgp_create_ip_reach(struct bgp_write_state *s, struct bgp_bucket *buck, byte *bu if (la < 0) { /* Attribute list too long */ - bgp_withdraw_bucket(s->channel, buck); + if (!s->sham) + bgp_withdraw_bucket(s->channel, buck); return NULL; } @@ -2524,7 +2325,8 @@ bgp_create_mp_reach(struct bgp_write_state *s, struct bgp_bucket *buck, byte *bu if (la < 0) { /* Attribute list too long */ - bgp_withdraw_bucket(s->channel, buck); + if (!s->sham) + bgp_withdraw_bucket(s->channel, buck); return NULL; } @@ -2606,53 +2408,11 @@ bgp_create_mp_unreach(struct bgp_write_state *s, struct bgp_bucket *buck, byte * } static byte * -bgp_bmp_create_mp_unreach(struct bgp_write_state *s, const net *n, - const struct rte *new, const struct rte *old, const u32 path_id, - byte *buf, uint size) -{ - /* - * 2 B Withdrawn Routes Length (zero) - * --- IPv4 Withdrawn Routes NLRI (unused) - * 2 B Total Path Attribute Length - * 1 B MP_UNREACH_NLRI hdr - Attribute Flags - * 1 B MP_UNREACH_NLRI hdr - Attribute Type Code - * 2 B MP_UNREACH_NLRI hdr - Length of Attribute Data - * 2 B MP_UNREACH_NLRI data - Address Family Identifier - * 1 B MP_UNREACH_NLRI data - Subsequent Address Family Identifier - * var MP_UNREACH_NLRI data - Network Layer Reachability Information - * --- IPv4 Network Layer Reachability Information (unused) - */ - - uint len = 0; - bool is_withdrawn = !new && old; - if (is_withdrawn) - { - len = bgp_bmp_encode_nlri_ip6(s, n, path_id, buf + 11, size); - } - - put_u16(buf+0, 0); - put_u16(buf+2, 7+len); - - /* Begin of MP_UNREACH_NLRI atribute */ - buf[4] = BAF_OPTIONAL | BAF_EXT_LEN; - buf[5] = BA_MP_UNREACH_NLRI; - - put_u16(buf+6, 3+len); - put_af3(buf+8, s->channel->afi); - - return buf+11+len; -} - -void -bgp_rte_update_in_notify(const struct proto *P, const struct channel *C, - const net *n, const struct rte *new, const struct rte *old, - const struct rte_src *src) +bgp_create_update_bmp(struct bgp_channel *c, byte *buf, struct bgp_bucket *buck, bool update) { - struct bgp_proto *p = (struct bgp_proto *)P; - struct bgp_channel *c = (struct bgp_channel *)C; - byte buf[BGP_MAX_EXT_MSG_LENGTH] = { 0x00 }; - byte *pkt = buf + BGP_HEADER_LENGTH; - byte *end = pkt + (bgp_max_packet_length(p->conn) - BGP_HEADER_LENGTH); + struct bgp_proto *p = (void *) c->c.proto; + byte *end = buf + (BGP_MAX_EXT_MSG_LENGTH - BGP_HEADER_LENGTH); + /* FIXME: must be a bit shorter */ struct bgp_caps *peer = p->conn->remote_caps; const struct bgp_af_caps *rem = bgp_find_af_caps(peer, c->afi); @@ -2660,65 +2420,73 @@ bgp_rte_update_in_notify(const struct proto *P, const struct channel *C, .proto = p, .channel = c, .pool = tmp_linpool, - .mp_reach = (bgp_channel_is_ipv6(c) || rem->ext_next_hop), - .as4_session = peer->as4_support, + .mp_reach = (c->afi != BGP_AF_IPV4) || rem->ext_next_hop, + .as4_session = 1, .add_path = c->add_path_rx, .mpls = c->desc->mpls, + .sham = 1, }; - const u32 path_id = c->add_path_rx ? src->private_id : 0; - byte *pos = pkt; - if (!s.mp_reach) + if (!update) { - pos = bgp_bmp_create_ip_unreach(&s, n, new, old, path_id, pkt, end - pkt); - if (!pos) - { - log(L_ERR "Failed to create unreachable field in UPDATE message"); - return; - } - - pos = bgp_bmp_create_ip_reach(&s, n, new, old, path_id, pos, end - pos); - if (!pos) - { - log(L_ERR "Failed to create reachable field in UPDATE message"); - return; - } - - bgp_bmp_prepare_bgp_hdr(buf, pos - buf, PKT_UPDATE); - bmp_route_monitor_put_update_in_pre_msg(buf, pos - buf); + return !s.mp_reach ? + bgp_create_ip_unreach(&s, buck, buf, end): + bgp_create_mp_unreach(&s, buck, buf, end); } - else if (new) // && s.mp_reach + else { - pos = s.mp_reach - ? bgp_bmp_create_mp_reach(&s, n, new, old, path_id, pos, end - pos) - : bgp_bmp_create_ip_reach(&s, n, new, old, path_id, pos, end - pos); - if (!pos) - { - log(L_ERR "Failed to create reachable field in UPDATE message"); - return; - } - - bgp_bmp_prepare_bgp_hdr(buf, pos - buf, PKT_UPDATE); - bmp_route_monitor_put_update_in_pre_msg(buf, pos - buf); + return !s.mp_reach ? + bgp_create_ip_reach(&s, buck, buf, end): + bgp_create_mp_reach(&s, buck, buf, end); } +} - if (!new && old) - { - bmp_route_monitor_update_in_pre_commit(p); - bmp_route_monitor_update_in_pre_end(); - bmp_route_monitor_update_in_pre_begin(); - pkt = buf + BGP_HEADER_LENGTH; - end = pkt + (bgp_max_packet_length(p->conn) - BGP_HEADER_LENGTH); - pos = bgp_bmp_create_mp_unreach(&s, n, new, old, path_id, pkt, end - pkt); - if (!pos) - { - log(L_ERR "Failed to create unreachable field in UPDATE message"); - return; - } +static byte * +bgp_bmp_prepare_bgp_hdr(byte *buf, const u16 msg_size, const u8 msg_type) +{ + memset(buf + BGP_MSG_HDR_MARKER_POS, 0xff, BGP_MSG_HDR_MARKER_SIZE); + put_u16(buf + BGP_MSG_HDR_LENGTH_POS, msg_size); + put_u8(buf + BGP_MSG_HDR_TYPE_POS, msg_type); - bgp_bmp_prepare_bgp_hdr(buf, pos - buf, PKT_UPDATE); - bmp_route_monitor_put_update_in_pre_msg(buf, pos - buf); - } + 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) +{ +// struct bgp_proto *p = (void *) C->proto; + struct bgp_channel *c = (void *) C; + + byte buf[BGP_MAX_EXT_MSG_LENGTH]; + byte *pkt = buf + BGP_HEADER_LENGTH; + + ea_list *attrs = new ? new->attrs->eattrs : NULL; + uint ea_size = new ? (sizeof(ea_list) + attrs->count * sizeof(eattr)) : 0; + uint bucket_size = sizeof(struct bgp_bucket) + ea_size; + uint prefix_size = sizeof(struct bgp_prefix) + n->length; + + /* Sham bucket */ + struct bgp_bucket *b = alloca(bucket_size); + *b = (struct bgp_bucket) { }; + init_list(&b->prefixes); + + if (attrs) + memcpy(b->eattrs, attrs, ea_size); + + /* Sham prefix */ + struct bgp_prefix *px = alloca(prefix_size); + *px = (struct bgp_prefix) { }; + px->path_id = src->private_id; + net_copy(px->net, 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); } static byte * diff --git a/proto/bmp/bmp.c b/proto/bmp/bmp.c index 4728eaef..550e4c18 100644 --- a/proto/bmp/bmp.c +++ b/proto/bmp/bmp.c @@ -210,7 +210,7 @@ struct bmp_data_node { }; static void -bmp_route_monitor_pre_policy_table_in_snapshot(const struct channel *C); +bmp_route_monitor_pre_policy_table_in_snapshot(struct channel *C); static void bmp_common_hdr_serialize(buffer *stream, const enum bmp_message_type type, const u32 data_size) @@ -881,8 +881,8 @@ bmp_route_monitor_update_in_pre_end() } } -void -bmp_route_monitor_pre_policy_table_in_snapshot(const struct channel *C) +static void +bmp_route_monitor_pre_policy_table_in_snapshot(struct channel *C) { struct bmp_proto *p = g_bmp; @@ -915,7 +915,7 @@ bmp_route_monitor_pre_policy_table_in_snapshot(const struct channel *C) rte *e; for (e = n->routes; e; e = e->next) { - bgp_rte_update_in_notify(P, C, n, e, NULL, e->src); + bgp_rte_update_in_notify(C, n->n.addr, e, e->src); } bmp_route_monitor_update_in_pre_commit((struct bgp_proto *) P); -- cgit v1.2.3