diff options
Diffstat (limited to 'proto/bgp')
-rw-r--r-- | proto/bgp/attrs.c | 44 | ||||
-rw-r--r-- | proto/bgp/bgp.c | 2 | ||||
-rw-r--r-- | proto/bgp/bgp.h | 5 | ||||
-rw-r--r-- | proto/bgp/config.Y | 4 | ||||
-rw-r--r-- | proto/bgp/packets.c | 29 |
5 files changed, 62 insertions, 22 deletions
diff --git a/proto/bgp/attrs.c b/proto/bgp/attrs.c index b8371f32..0309c1f7 100644 --- a/proto/bgp/attrs.c +++ b/proto/bgp/attrs.c @@ -191,7 +191,7 @@ validate_as4_path(struct bgp_proto *p, struct adata *path) } static int -bgp_check_next_hop(struct bgp_proto *p UNUSED, byte *a, int len) +bgp_check_next_hop(struct bgp_proto *p UNUSED, byte *a UNUSED6, int len UNUSED6) { #ifdef IPV6 return IGNORE; @@ -289,6 +289,12 @@ bgp_check_ext_community(struct bgp_proto *p UNUSED, byte *a UNUSED, int len) return ((len % 8) == 0) ? 0 : WITHDRAW; } +static int +bgp_check_large_community(struct bgp_proto *p UNUSED, byte *a UNUSED, int len) +{ + return ((len % 12) == 0) ? 0 : WITHDRAW; +} + static struct attr_desc bgp_attr_table[] = { { NULL, -1, 0, 0, 0, /* Undefined */ @@ -325,7 +331,10 @@ static struct attr_desc bgp_attr_table[] = { { "as4_path", -1, BAF_OPTIONAL | BAF_TRANSITIVE, EAF_TYPE_OPAQUE, 1, /* BA_AS4_PATH */ NULL, NULL }, { "as4_aggregator", -1, BAF_OPTIONAL | BAF_TRANSITIVE, EAF_TYPE_OPAQUE, 1, /* BA_AS4_PATH */ - NULL, NULL } + NULL, NULL }, + [BA_LARGE_COMMUNITY] = + { "large_community", -1, BAF_OPTIONAL | BAF_TRANSITIVE, EAF_TYPE_LC_SET, 1, + bgp_check_large_community, NULL } }; /* BA_AS4_PATH is type EAF_TYPE_OPAQUE and not type EAF_TYPE_AS_PATH. @@ -575,7 +584,7 @@ bgp_encode_attrs(struct bgp_proto *p, byte *w, ea_list *attrs, int remains) len = bgp_get_attr_len(a); /* Skip empty sets */ - if (((type == EAF_TYPE_INT_SET) || (type == EAF_TYPE_EC_SET)) && (len == 0)) + if (((type == EAF_TYPE_INT_SET) || (type == EAF_TYPE_EC_SET) || (type == EAF_TYPE_LC_SET)) && (len == 0)) continue; if (remains < len + 4) @@ -601,6 +610,7 @@ bgp_encode_attrs(struct bgp_proto *p, byte *w, ea_list *attrs, int remains) break; } case EAF_TYPE_INT_SET: + case EAF_TYPE_LC_SET: case EAF_TYPE_EC_SET: { u32 *z = int_set_get_data(a->u.ptr); @@ -683,6 +693,25 @@ bgp_normalize_ec_set(struct adata *ad, u32 *src, int internal) qsort(dst, ad->length / 8, 8, (int(*)(const void *, const void *)) bgp_compare_ec); } +static int +bgp_compare_lc(const u32 *x, const u32 *y) +{ + if (x[0] != y[0]) + return (x[0] > y[0]) ? 1 : -1; + if (x[1] != y[1]) + return (x[1] > y[1]) ? 1 : -1; + if (x[2] != y[2]) + return (x[2] > y[2]) ? 1 : -1; + return 0; +} + +static inline void +bgp_normalize_lc_set(u32 *dest, u32 *src, unsigned cnt) +{ + memcpy(dest, src, LCOMM_LENGTH * cnt); + qsort(dest, cnt, LCOMM_LENGTH, (int(*)(const void *, const void *)) bgp_compare_lc); +} + static void bgp_rehash_buckets(struct bgp_proto *p) { @@ -827,6 +856,14 @@ bgp_get_bucket(struct bgp_proto *p, net *n, ea_list *attrs, int originate) d->u.ptr = z; break; } + case EAF_TYPE_LC_SET: + { + struct adata *z = alloca(sizeof(struct adata) + d->u.ptr->length); + z->length = d->u.ptr->length; + bgp_normalize_lc_set((u32 *) z->data, (u32 *) d->u.ptr->data, z->length / LCOMM_LENGTH); + d->u.ptr = z; + break; + } default: ; } d++; @@ -1797,6 +1834,7 @@ bgp_decode_attrs(struct bgp_conn *conn, byte *attr, uint len, struct linpool *po ipa_ntoh(*(ip_addr *)ad->data); break; case EAF_TYPE_INT_SET: + case EAF_TYPE_LC_SET: case EAF_TYPE_EC_SET: { u32 *z = (u32 *) ad->data; diff --git a/proto/bgp/bgp.c b/proto/bgp/bgp.c index 0ae3db7b..cac5d4c4 100644 --- a/proto/bgp/bgp.c +++ b/proto/bgp/bgp.c @@ -807,7 +807,7 @@ bgp_find_proto(sock *sk) * closes the new connection by sending a Notification message. */ static int -bgp_incoming_connection(sock *sk, int dummy UNUSED) +bgp_incoming_connection(sock *sk, uint dummy UNUSED) { struct bgp_proto *p; int acc, hops; diff --git a/proto/bgp/bgp.h b/proto/bgp/bgp.h index b1cca2d9..b4067f3a 100644 --- a/proto/bgp/bgp.h +++ b/proto/bgp/bgp.h @@ -191,7 +191,7 @@ struct bgp_bucket { #define BGP_RX_BUFFER_EXT_SIZE 65535 #define BGP_TX_BUFFER_EXT_SIZE 65535 -static inline int bgp_max_packet_length(struct bgp_proto *p) +static inline uint bgp_max_packet_length(struct bgp_proto *p) { return p->ext_messages ? BGP_MAX_EXT_MSG_LENGTH : BGP_MAX_MESSAGE_LENGTH; } extern struct linpool *bgp_linpool; @@ -268,7 +268,7 @@ void mrt_dump_bgp_state_change(struct bgp_conn *conn, unsigned old, unsigned new void bgp_schedule_packet(struct bgp_conn *conn, int type); void bgp_kick_tx(void *vconn); void bgp_tx(struct birdsock *sk); -int bgp_rx(struct birdsock *sk, int size); +int bgp_rx(struct birdsock *sk, uint size); 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); @@ -308,6 +308,7 @@ void bgp_log_error(struct bgp_proto *p, u8 class, char *msg, unsigned code, unsi #define BA_EXT_COMMUNITY 0x10 /* [RFC4360] */ #define BA_AS4_PATH 0x11 /* [RFC4893] */ #define BA_AS4_AGGREGATOR 0x12 +#define BA_LARGE_COMMUNITY 0x20 /* [draft-ietf-idr-large-community] */ /* BGP connection states */ diff --git a/proto/bgp/config.Y b/proto/bgp/config.Y index 33561bff..bdbb6007 100644 --- a/proto/bgp/config.Y +++ b/proto/bgp/config.Y @@ -27,7 +27,7 @@ CF_KEYWORDS(BGP, LOCAL, NEIGHBOR, AS, HOLD, TIME, CONNECT, RETRY, INTERPRET, COMMUNITIES, BGP_ORIGINATOR_ID, BGP_CLUSTER_LIST, IGP, TABLE, GATEWAY, DIRECT, RECURSIVE, MED, TTL, SECURITY, DETERMINISTIC, SECONDARY, ALLOW, BFD, ADD, PATHS, RX, TX, GRACEFUL, RESTART, AWARE, - CHECK, LINK, PORT, EXTENDED, MESSAGES, SETKEY) + CHECK, LINK, PORT, EXTENDED, MESSAGES, SETKEY, BGP_LARGE_COMMUNITY) CF_GRAMMAR @@ -153,6 +153,8 @@ CF_ADDTO(dynamic_attr, BGP_CLUSTER_LIST { $$ = f_new_dynamic_attr(EAF_TYPE_INT_SET, T_CLIST, EA_CODE(EAP_BGP, BA_CLUSTER_LIST)); }) CF_ADDTO(dynamic_attr, BGP_EXT_COMMUNITY { $$ = f_new_dynamic_attr(EAF_TYPE_EC_SET, T_ECLIST, EA_CODE(EAP_BGP, BA_EXT_COMMUNITY)); }) +CF_ADDTO(dynamic_attr, BGP_LARGE_COMMUNITY + { $$ = f_new_dynamic_attr(EAF_TYPE_LC_SET, T_LCLIST, EA_CODE(EAP_BGP, BA_LARGE_COMMUNITY)); }) diff --git a/proto/bgp/packets.c b/proto/bgp/packets.c index 0cf38edf..3e816839 100644 --- a/proto/bgp/packets.c +++ b/proto/bgp/packets.c @@ -191,7 +191,7 @@ bgp_put_cap_gr1(struct bgp_proto *p, byte *buf) } static byte * -bgp_put_cap_gr2(struct bgp_proto *p, byte *buf) +bgp_put_cap_gr2(struct bgp_proto *p UNUSED, byte *buf) { *buf++ = 64; /* Capability 64: Support for graceful restart */ *buf++ = 2; /* Capability data length */ @@ -931,7 +931,7 @@ bgp_parse_options(struct bgp_conn *conn, byte *opt, int len) } static void -bgp_rx_open(struct bgp_conn *conn, byte *pkt, int len) +bgp_rx_open(struct bgp_conn *conn, byte *pkt, uint len) { struct bgp_conn *other; struct bgp_proto *p = conn->bgp; @@ -944,7 +944,7 @@ bgp_rx_open(struct bgp_conn *conn, byte *pkt, int len) { bgp_error(conn, 5, fsm_err_subcode[conn->state], NULL, 0); return; } /* Check message contents */ - if (len < 29 || len != 29 + pkt[28]) + if (len < 29 || len != 29U + pkt[28]) { bgp_error(conn, 1, 2, pkt+16, 2); return; } if (pkt[19] != BGP_VERSION) { bgp_error(conn, 2, 1, pkt+19, 1); return; } /* RFC 1771 says 16 bits, draft-09 tells to use 8 */ @@ -1256,16 +1256,15 @@ bgp_do_rx_update(struct bgp_conn *conn, #else /* IPv6 version */ #define DO_NLRI(name) \ - start = x = p->name##_start; \ + x = p->name##_start; \ len = len0 = p->name##_len; \ if (len) \ { \ if (len < 3) { err=9; goto done; } \ af = get_u16(x); \ - sub = x[2]; \ x += 3; \ len -= 3; \ - DBG("\tNLRI AF=%d sub=%d len=%d\n", af, sub, len);\ + DBG("\tNLRI AF=%d sub=%d len=%d\n", af, x[-1], len);\ } \ else \ af = 0; \ @@ -1291,15 +1290,15 @@ bgp_attach_next_hop(rta *a0, byte *x) static void bgp_do_rx_update(struct bgp_conn *conn, - byte *withdrawn, int withdrawn_len, - byte *nlri, int nlri_len, + byte *withdrawn UNUSED, int withdrawn_len, + byte *nlri UNUSED, int nlri_len, byte *attrs, int attr_len) { struct bgp_proto *p = conn->bgp; struct rte_src *src = p->p.main_source; - byte *start, *x; + byte *x; int len, len0; - unsigned af, sub; + unsigned af; rta *a0, *a = NULL; ip_addr prefix; int pxlen, err = 0; @@ -1375,11 +1374,11 @@ bgp_do_rx_update(struct bgp_conn *conn, #endif static void -bgp_rx_update(struct bgp_conn *conn, byte *pkt, int len) +bgp_rx_update(struct bgp_conn *conn, byte *pkt, uint len) { struct bgp_proto *p = conn->bgp; byte *withdrawn, *attrs, *nlri; - int withdrawn_len, attr_len, nlri_len; + uint withdrawn_len, attr_len, nlri_len; BGP_TRACE_RL(&rl_rcv_update, D_PACKETS, "Got UPDATE"); @@ -1525,7 +1524,7 @@ bgp_log_error(struct bgp_proto *p, u8 class, char *msg, unsigned code, unsigned } static void -bgp_rx_notification(struct bgp_conn *conn, byte *pkt, int len) +bgp_rx_notification(struct bgp_conn *conn, byte *pkt, uint len) { struct bgp_proto *p = conn->bgp; if (len < 21) @@ -1591,7 +1590,7 @@ bgp_rx_keepalive(struct bgp_conn *conn) } static void -bgp_rx_route_refresh(struct bgp_conn *conn, byte *pkt, int len) +bgp_rx_route_refresh(struct bgp_conn *conn, byte *pkt, uint len) { struct bgp_proto *p = conn->bgp; @@ -1680,7 +1679,7 @@ bgp_rx_packet(struct bgp_conn *conn, byte *pkt, unsigned len) * bgp_rx_packet(). */ int -bgp_rx(sock *sk, int size) +bgp_rx(sock *sk, uint size) { struct bgp_conn *conn = sk->data; struct bgp_proto *p = conn->bgp; |