From a244c5524b30874e24fc4dfbdb8cef243bd33178 Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Wed, 3 Nov 2010 01:40:36 +0100 Subject: Added support for sending and handling the multicast capability --- conf/conf.h | 1 + nest/config.Y | 12 ++++++++++-- proto/bgp/bgp.c | 7 +++++-- proto/bgp/bgp.h | 14 ++++++++++++-- proto/bgp/config.Y | 4 +++- proto/bgp/packets.c | 42 ++++++++++++++++++++++++++++++++++-------- 6 files changed, 65 insertions(+), 15 deletions(-) diff --git a/conf/conf.h b/conf/conf.h index 6c784d7..c03b5f1 100644 --- a/conf/conf.h +++ b/conf/conf.h @@ -28,6 +28,7 @@ struct config { ip_addr listen_bgp_addr; /* Listening BGP socket should use this address */ unsigned listen_bgp_port; /* Listening BGP socket should use this port (0 is default) */ u32 listen_bgp_flags; /* Listening BGP socket should use these flags */ + int enable_multicast; /* Enable multicast capabilities */ unsigned proto_default_debug; /* Default protocol debug mask */ unsigned proto_default_mrtdump; /* Default protocol mrtdump mask */ struct timeformat tf_route; /* Time format for 'show route' */ diff --git a/nest/config.Y b/nest/config.Y index 39cd901..cd00310 100644 --- a/nest/config.Y +++ b/nest/config.Y @@ -43,8 +43,8 @@ CF_DECLS CF_KEYWORDS(ROUTER, ID, PROTOCOL, PREFERENCE, DISABLED, DEBUG, ALL, OFF, DIRECT) CF_KEYWORDS(INTERFACE, IMPORT, EXPORT, FILTER, NONE, TABLE, STATES, ROUTES, FILTERS) CF_KEYWORDS(PASSWORD, FROM, PASSIVE, TO, ID, EVENTS, PACKETS, PROTOCOLS, INTERFACES) -CF_KEYWORDS(PRIMARY, STATS, COUNT, FOR, COMMANDS, PREEXPORT, GENERATE) -CF_KEYWORDS(LISTEN, BGP, V6ONLY, ADDRESS, PORT, PASSWORDS, DESCRIPTION) +CF_KEYWORDS(PRIMARY, STATS, COUNT, FOR, COMMANDS, PREEXPORT, GENERATE, ENABLE) +CF_KEYWORDS(LISTEN, BGP, V6ONLY, ADDRESS, PORT, PASSWORDS, DESCRIPTION, MULTICAST) CF_KEYWORDS(RELOAD, IN, OUT, MRTDUMP, MESSAGES, RESTRICT, MEMORY, IGP_METRIC) CF_ENUM(T_ENUM_RTS, RTS_, DUMMY, STATIC, INHERIT, DEVICE, STATIC_DEVICE, REDIRECT, @@ -101,6 +101,14 @@ listen_opt: ; +CF_ADDTO(conf, multicast) + +multicast: ENABLE MULTICAST bool ';' { + new_config->enable_multicast = $3; + } + ; + + /* Creation of routing tables */ CF_ADDTO(conf, newtab) diff --git a/proto/bgp/bgp.c b/proto/bgp/bgp.c index ba5d755..cbffc65 100644 --- a/proto/bgp/bgp.c +++ b/proto/bgp/bgp.c @@ -408,6 +408,8 @@ bgp_send_open(struct bgp_conn *conn) conn->start_state = conn->bgp->start_state; conn->want_as4_support = conn->bgp->cf->enable_as4 && (conn->start_state != BSS_CONNECT_NOCAP); conn->peer_as4_support = 0; // Default value, possibly changed by receiving capability. + conn->want_multicast_support = conn->bgp->cf->c.global->enable_multicast && conn->bgp->cf->enable_multicast && (conn->start_state != BSS_CONNECT_NOCAP); + conn->peer_multicast_support = 0; // Default value, possibly changed by receiving capability. conn->advertised_as = 0; DBG("BGP: Sending open\n"); @@ -1067,9 +1069,10 @@ bgp_show_proto_info(struct proto *P) cli_msg(-1006, " Neighbor ID: %R", p->remote_id); cli_msg(-1006, " Neighbor address: %I", p->cf->remote_ip); cli_msg(-1006, " Source address: %I", p->source_addr); - cli_msg(-1006, " Neighbor caps: %s%s", + cli_msg(-1006, " Neighbor caps: %s%s%s", c->peer_refresh_support ? " refresh" : "", - c->peer_as4_support ? " AS4" : ""); + c->peer_as4_support ? " AS4" : "", + c->peer_multicast_support ? " multicast" : ""); if (p->cf->route_limit) cli_msg(-1006, " Route limit: %d/%d", p->p.stats.imp_routes, p->cf->route_limit); diff --git a/proto/bgp/bgp.h b/proto/bgp/bgp.h index b06f20a..359bd9c 100644 --- a/proto/bgp/bgp.h +++ b/proto/bgp/bgp.h @@ -32,6 +32,7 @@ struct bgp_config { int capabilities; /* Enable capability handshake [RFC3392] */ int enable_refresh; /* Enable local support for route refresh [RFC2918] */ int enable_as4; /* Enable local support for 4B AS numbers [RFC4893] */ + int enable_multicast; /* Enable local support for multicast routes [RFC4760] */ u32 rr_cluster_id; /* Route reflector cluster ID, if different from local ID */ int rr_client; /* Whether neighbor is RR client of me */ int rs_client; /* Whether neighbor is RS client of me */ @@ -73,6 +74,8 @@ struct bgp_conn { int start_state; /* protocol start_state snapshot when connection established */ int want_as4_support; /* Connection tries to establish AS4 session */ int peer_as4_support; /* Peer supports 4B AS numbers [RFC4893] */ + int want_multicast_support; /* We want to exchange multicast routes */ + int peer_multicast_support; /* Peer supports multicast routes [RFC4760] */ int peer_refresh_support; /* Peer supports route refresh [RFC2918] */ unsigned hold_time, keepalive_time; /* Times calculated from my and neighbor's requirements */ }; @@ -108,11 +111,9 @@ struct bgp_proto { u8 last_error_class; /* Error class of last error */ u32 last_error_code; /* Error code of last error. BGP protocol errors are encoded as (bgp_err_code << 16 | bgp_err_subcode) */ -#ifdef IPV6 byte *mp_reach_start, *mp_unreach_start; /* Multiprotocol BGP attribute notes */ unsigned mp_reach_len, mp_unreach_len; ip_addr local_link; /* Link-level version of source_addr */ -#endif }; struct bgp_prefix { @@ -297,6 +298,12 @@ void bgp_log_error(struct bgp_proto *p, u8 class, char *msg, unsigned code, unsi #define ORIGIN_EGP 1 #define ORIGIN_INCOMPLETE 2 +/* Capabilities */ + +#define BGP_CAP_MP 1 +#define BGP_CAP_REFRESH 2 +#define BGP_CAP_AS4 65 + /* Address families */ #define BGP_AF_IPV4 1 @@ -308,4 +315,7 @@ void bgp_log_error(struct bgp_proto *p, u8 class, char *msg, unsigned code, unsi #define BGP_AF BGP_AF_IPV4 #endif +#define BGP_SAF_UNICAST 1 +#define BGP_SAF_MULTICAST 2 + #endif diff --git a/proto/bgp/config.Y b/proto/bgp/config.Y index e932a7f..2e76159 100644 --- a/proto/bgp/config.Y +++ b/proto/bgp/config.Y @@ -25,7 +25,7 @@ CF_KEYWORDS(BGP, LOCAL, NEIGHBOR, AS, HOLD, TIME, CONNECT, RETRY, ADVERTISE, IPV4, CAPABILITIES, LIMIT, PASSIVE, PREFER, OLDER, MISSING, LLADDR, DROP, IGNORE, ROUTE, REFRESH, INTERPRET, COMMUNITIES, BGP_ORIGINATOR_ID, BGP_CLUSTER_LIST, IGP, TABLE, - GATEWAY, DIRECT, RECURSIVE) + GATEWAY, DIRECT, RECURSIVE, MULTICAST) CF_GRAMMAR @@ -45,6 +45,7 @@ bgp_proto_start: proto_start BGP { BGP_CFG->error_delay_time_max = 300; BGP_CFG->enable_refresh = 1; BGP_CFG->enable_as4 = 1; + BGP_CFG->enable_multicast = 1; BGP_CFG->capabilities = 2; BGP_CFG->advertise_ipv4 = 1; BGP_CFG->interpret_communities = 1; @@ -90,6 +91,7 @@ bgp_proto: | bgp_proto DISABLE AFTER ERROR bool ';' { BGP_CFG->disable_after_error = $5; } | bgp_proto ENABLE ROUTE REFRESH bool ';' { BGP_CFG->enable_refresh = $5; } | bgp_proto ENABLE AS4 bool ';' { BGP_CFG->enable_as4 = $4; } + | bgp_proto ENABLE MULTICAST bool ';' { BGP_CFG->enable_multicast = $4; } | bgp_proto CAPABILITIES bool ';' { BGP_CFG->capabilities = $3; } | bgp_proto ADVERTISE IPV4 bool ';' { BGP_CFG->advertise_ipv4 = $4; } | bgp_proto PASSWORD TEXT ';' { BGP_CFG->password = $3; } diff --git a/proto/bgp/packets.c b/proto/bgp/packets.c index bf98640..1a1e7b7 100644 --- a/proto/bgp/packets.c +++ b/proto/bgp/packets.c @@ -117,12 +117,12 @@ bgp_create_notification(struct bgp_conn *conn, byte *buf) static byte * bgp_put_cap_ipv6(struct bgp_conn *conn UNUSED, byte *buf) { - *buf++ = 1; /* Capability 1: Multiprotocol extensions */ + *buf++ = BGP_CAP_MP; /* Capability 1: Multiprotocol extensions */ *buf++ = 4; /* Capability data length */ *buf++ = 0; /* We support AF IPv6 */ *buf++ = BGP_AF_IPV6; *buf++ = 0; /* RFU */ - *buf++ = 1; /* and SAFI 1 */ + *buf++ = BGP_SAF_UNICAST; /* and SAFI 1 */ return buf; } @@ -131,20 +131,32 @@ bgp_put_cap_ipv6(struct bgp_conn *conn UNUSED, byte *buf) static byte * bgp_put_cap_ipv4(struct bgp_conn *conn UNUSED, byte *buf) { - *buf++ = 1; /* Capability 1: Multiprotocol extensions */ + *buf++ = BGP_CAP_MP; /* Capability 1: Multiprotocol extensions */ *buf++ = 4; /* Capability data length */ *buf++ = 0; /* We support AF IPv4 */ *buf++ = BGP_AF_IPV4; *buf++ = 0; /* RFU */ - *buf++ = 1; /* and SAFI 1 */ + *buf++ = BGP_SAF_UNICAST; /* and SAFI 1 */ return buf; } #endif +static byte * +bgp_put_cap_multicast(struct bgp_conn *conn UNUSED, byte *buf) +{ + *buf++ = BGP_CAP_MP; /* Capability 1: Multiprotocol extensions */ + *buf++ = 4; /* Capability data length */ + *buf++ = 0; + *buf++ = BGP_AF; + *buf++ = 0; /* RFU */ + *buf++ = BGP_SAF_MULTICAST; /* and SAFI 2 */ + return buf; +} + static byte * bgp_put_cap_rr(struct bgp_conn *conn UNUSED, byte *buf) { - *buf++ = 2; /* Capability 2: Support for route refresh */ + *buf++ = BGP_CAP_REFRESH; /* Capability 2: Support for route refresh */ *buf++ = 0; /* Capability data length */ return buf; } @@ -152,7 +164,7 @@ bgp_put_cap_rr(struct bgp_conn *conn UNUSED, byte *buf) static byte * bgp_put_cap_as4(struct bgp_conn *conn, byte *buf) { - *buf++ = 65; /* Capability 65: Support for 4-octet AS number */ + *buf++ = BGP_CAP_AS4; /* Capability 65: Support for 4-octet AS number */ *buf++ = 4; /* Capability data length */ put_u32(buf, conn->bgp->local_as); return buf + 4; @@ -197,6 +209,9 @@ bgp_create_open(struct bgp_conn *conn, byte *buf) if (conn->want_as4_support) cap = bgp_put_cap_as4(conn, cap); + if (conn->want_multicast_support) + cap = bgp_put_cap_multicast(conn, cap); + cap_len = cap - buf - 12; if (cap_len > 0) { @@ -625,13 +640,24 @@ bgp_parse_capabilities(struct bgp_conn *conn, byte *opt, int len) switch (opt[0]) { - case 2: /* Route refresh capability, RFC 2918 */ + case BGP_CAP_MP: /* Multiprotocol capability, RFC 4760 */ + if (cl != 4) + goto err; + + if (get_u16(opt + 2) != BGP_AF) + break; + + if (opt[5] == BGP_SAF_MULTICAST) + conn->peer_multicast_support = 1; + break; + + case BGP_CAP_REFRESH: /* Route refresh capability, RFC 2918 */ if (cl != 0) goto err; conn->peer_refresh_support = 1; break; - case 65: /* AS4 capability, RFC 4893 */ + case BGP_CAP_AS4: /* AS4 capability, RFC 4893 */ if (cl != 4) goto err; conn->peer_as4_support = 1; -- cgit v1.2.3