diff --git a/lib/bgp/parsebgp_bgp_update_mp_reach_evpn.c b/lib/bgp/parsebgp_bgp_update_mp_reach_evpn.c new file mode 100644 index 0000000..c1f0a53 --- /dev/null +++ b/lib/bgp/parsebgp_bgp_update_mp_reach_evpn.c @@ -0,0 +1,434 @@ +#include "parsebgp_bgp_update_mp_reach_evpn.h" +#include "parsebgp_error.h" +#include "parsebgp_utils.h" +#include "parsebgp_bgp_common.h" +#include +#include + +static parsebgp_error_t +parsebgp_bgp_update_mp_reach_evpn_ethernet(parsebgp_opts_t *opts, + parsebgp_bgp_update_mp_reach_evpn_t *msg, + uint8_t *buf, + size_t *lenp, + size_t remain) { + + size_t len = *lenp, nread = 0; + + if (msg->length + != sizeof(parsebgp_bgp_update_mp_reach_evpn_ethernet_ad_route_t)) { + PARSEBGP_RETURN_INVALID_MSG_ERR; + } + + PARSEBGP_DESERIALIZE_VAL(buf, + len, + nread, + msg->route_type_specific.eth_ad_route.route_distinguisher); + PARSEBGP_DESERIALIZE_VAL(buf, + len, + nread, + msg->route_type_specific.eth_ad_route.ethernet_segment_identifier); + PARSEBGP_DESERIALIZE_VAL(buf, + len, + nread, + msg->route_type_specific.eth_ad_route.ethernet_tag_id); + PARSEBGP_DESERIALIZE_VAL(buf, + len, + nread, + msg->route_type_specific.eth_ad_route.mpls_label); + + *lenp = nread; + return PARSEBGP_OK; +} + +static parsebgp_error_t +parsebgp_bgp_update_mp_reach_evpn_mac_ip_adv(parsebgp_opts_t *opts, + parsebgp_bgp_update_mp_reach_evpn_t *msg, + uint8_t *buf, + size_t *lenp, + size_t remain) { + + size_t len = *lenp, nread = 0; + + PARSEBGP_DESERIALIZE_VAL(buf, + len, + nread, + msg->route_type_specific.mac_ip_adv_route.route_distinguisher); + PARSEBGP_DESERIALIZE_VAL(buf, + len, + nread, + msg->route_type_specific.mac_ip_adv_route.ethernet_segment_identifier); + PARSEBGP_DESERIALIZE_VAL(buf, + len, + nread, + msg->route_type_specific.mac_ip_adv_route.ethernet_tag_id); + PARSEBGP_DESERIALIZE_VAL(buf, + len, + nread, + msg->route_type_specific.mac_ip_adv_route.mac_addr_len); + + if (msg->route_type_specific.mac_ip_adv_route.mac_addr_len > len) { + return PARSEBGP_PARTIAL_MSG; + } + + memcpy(msg->route_type_specific.mac_ip_adv_route.mac_addr, + buf, + msg->route_type_specific.mac_ip_adv_route.mac_addr_len); + nread += msg->route_type_specific.mac_ip_adv_route.mac_addr_len; + buf += msg->route_type_specific.mac_ip_adv_route.mac_addr_len; + + PARSEBGP_DESERIALIZE_VAL(buf, + len, + nread, + msg->route_type_specific.mac_ip_adv_route.ip_addr_len); + + if (msg->route_type_specific.mac_ip_adv_route.ip_addr_len > len) { + return PARSEBGP_PARTIAL_MSG; + } + + memcpy(msg->route_type_specific.mac_ip_adv_route.ip_addr, + buf, + msg->route_type_specific.mac_ip_adv_route.ip_addr_len); + nread += msg->route_type_specific.mac_ip_adv_route.ip_addr_len; + buf += msg->route_type_specific.mac_ip_adv_route.ip_addr_len; + + PARSEBGP_DESERIALIZE_VAL(buf, + len, + nread, + msg->route_type_specific.mac_ip_adv_route.mpls_label1); + PARSEBGP_DESERIALIZE_VAL(buf, + len, + nread, + msg->route_type_specific.mac_ip_adv_route.mpls_label2); + + *lenp = nread; + return PARSEBGP_OK; +} + +static parsebgp_error_t +parsebgp_bgp_update_mp_reach_evpn_inc_multicast_eth(parsebgp_opts_t *opts, + parsebgp_bgp_update_mp_reach_evpn_t *msg, + uint8_t *buf, + size_t *lenp, + size_t remain) { + + size_t len = *lenp, nread = 0; + + PARSEBGP_DESERIALIZE_VAL(buf, + len, + nread, + msg->route_type_specific.incl_multicast_eth_tag_route.route_distinguisher); + PARSEBGP_DESERIALIZE_VAL(buf, + len, + nread, + msg->route_type_specific.incl_multicast_eth_tag_route.ethernet_tag_id); + PARSEBGP_DESERIALIZE_VAL(buf, + len, + nread, + msg->route_type_specific.incl_multicast_eth_tag_route.ip_addr_len); + + if (msg->route_type_specific.incl_multicast_eth_tag_route.ip_addr_len > len) { + return PARSEBGP_PARTIAL_MSG; + } + + memcpy(msg->route_type_specific.incl_multicast_eth_tag_route.ip_addr, + buf, + msg->route_type_specific.incl_multicast_eth_tag_route.ip_addr_len); + nread += msg->route_type_specific.incl_multicast_eth_tag_route.ip_addr_len; + buf += msg->route_type_specific.incl_multicast_eth_tag_route.ip_addr_len; + + *lenp = nread; + return PARSEBGP_OK; +} + +static parsebgp_error_t +parsebgp_bgp_update_mp_reach_evpn_ethernet_seg_route(parsebgp_opts_t *opts, + parsebgp_bgp_update_mp_reach_evpn_t *msg, + uint8_t *buf, + size_t *lenp, + size_t remain) { + + size_t len = *lenp, nread = 0; + + PARSEBGP_DESERIALIZE_VAL(buf, + len, + nread, + msg->route_type_specific.eth_segment_route.route_distinguisher); + PARSEBGP_DESERIALIZE_VAL(buf, + len, + nread, + msg->route_type_specific.eth_segment_route.ethernet_segment_identifier); + PARSEBGP_DESERIALIZE_VAL(buf, + len, + nread, + msg->route_type_specific.eth_segment_route.ip_addr_len); + + if (msg->route_type_specific.eth_segment_route.ip_addr_len > len) { + return PARSEBGP_PARTIAL_MSG; + } + + memcpy(msg->route_type_specific.eth_segment_route.ip_addr, + buf, + msg->route_type_specific.eth_segment_route.ip_addr_len); + nread += msg->route_type_specific.eth_segment_route.ip_addr_len; + buf += msg->route_type_specific.eth_segment_route.ip_addr_len; + + *lenp = nread; + return PARSEBGP_OK; +} + +parsebgp_error_t +parsebgp_bgp_update_mp_reach_evpn_decode(parsebgp_opts_t *opts, + parsebgp_bgp_update_mp_reach_evpn_t *msg, + uint8_t *buf, + size_t *lenp, + size_t remain) { + + size_t len = *lenp, nread = 0, slen; + parsebgp_error_t err; + + PARSEBGP_DESERIALIZE_VAL(buf, len, nread, msg->length); + if (msg->length > len) { + return PARSEBGP_PARTIAL_MSG; + } + + PARSEBGP_DESERIALIZE_VAL(buf, len, nread, msg->route_type); + + switch (msg->route_type) { + + case PARSEBGP_BGP_UPDATE_MP_REACH_EVPN_ETHERNET_AD: + slen = len - nread; + if ((err = parsebgp_bgp_update_mp_reach_evpn_ethernet(opts, msg, buf, &slen, + remain - nread)) + != PARSEBGP_OK) { + return err; + } + nread += slen; + buf += slen; + break; + + case PARSEBGP_BGP_UPDATE_MP_REACH_EVPN_MAC_IP_ADVERTISMENT: + slen = len - nread; + if ((err = + parsebgp_bgp_update_mp_reach_evpn_mac_ip_adv(opts, msg, buf, &slen, + remain - nread)) + != PARSEBGP_OK) { + return err; + } + nread += slen; + buf += slen; + break; + + case PARSEBGP_BGP_UPDATE_MP_REACH_EVPN_INCLUSIVE_MULTICAST_ETHERNET_TAG: + slen = len - nread; + if ((err = parsebgp_bgp_update_mp_reach_evpn_inc_multicast_eth(opts, + msg, + buf, + &slen, + remain + - nread)) + != PARSEBGP_OK) { + return err; + } + nread += slen; + buf += slen; + break; + + case PARSEBGP_BGP_UPDATE_MP_REACH_EVPN_ETHERNET_SEGMENT_ROUTE: + + slen = len - nread; + if ((err = parsebgp_bgp_update_mp_reach_evpn_ethernet_seg_route(opts, + msg, + buf, + &slen, + remain + - nread)) + != PARSEBGP_OK) { + return err; + } + nread += slen; + buf += slen; + break; + default: + PARSEBGP_SKIP_NOT_IMPLEMENTED(opts, buf, nread, remain - nread, + "Unsupported SAFI (%d)", msg->route_type); + + } + + *lenp = nread; + return PARSEBGP_OK; + +} + +void parsebgp_bgp_update_mp_reach_evpn_dump( + parsebgp_bgp_update_mp_reach_evpn_t *msg, int depth) { + + PARSEBGP_DUMP_STRUCT_HDR(parsebgp_bgp_update_mp_reach_evpn_t, depth); + + PARSEBGP_DUMP_INT(depth, "Route Type", msg->route_type); + PARSEBGP_DUMP_INT(depth, "Length", msg->length); + + depth++; + switch (msg->route_type) { + + case PARSEBGP_BGP_UPDATE_MP_REACH_EVPN_ETHERNET_AD: + PARSEBGP_DUMP_STRUCT_HDR( + parsebgp_bgp_update_mp_reach_evpn_ethernet_ad_route_t, + depth); + + PARSEBGP_DUMP_DATA(depth, + "Route Distinguisher", + msg->route_type_specific.eth_ad_route.route_distinguisher, + sizeof(msg->route_type_specific.eth_ad_route.route_distinguisher)); + PARSEBGP_DUMP_DATA(depth, + "Ethernet Segment Identifier", + msg->route_type_specific.eth_ad_route.ethernet_segment_identifier, + sizeof(msg->route_type_specific.eth_ad_route.ethernet_segment_identifier)); + PARSEBGP_DUMP_INT(depth, "Ethernet Tag ID", + msg->route_type_specific.eth_ad_route.ethernet_tag_id); + PARSEBGP_DUMP_DATA(depth, + "MPLS Label", + msg->route_type_specific.eth_ad_route.mpls_label, + sizeof(msg->route_type_specific.eth_ad_route.mpls_label)); + break; + + case PARSEBGP_BGP_UPDATE_MP_REACH_EVPN_MAC_IP_ADVERTISMENT: + PARSEBGP_DUMP_STRUCT_HDR( + parsebgp_bgp_update_mp_reach_evpn_mac_ip_advertisement_route_t, + depth); + + PARSEBGP_DUMP_DATA(depth, + "Route Distinguisher", + msg->route_type_specific.mac_ip_adv_route.route_distinguisher, + sizeof(msg->route_type_specific.mac_ip_adv_route.route_distinguisher)); + PARSEBGP_DUMP_DATA(depth, + "Ethernet Segment Identifier", + msg->route_type_specific.mac_ip_adv_route.ethernet_segment_identifier, + sizeof(msg->route_type_specific.mac_ip_adv_route.ethernet_segment_identifier)); + PARSEBGP_DUMP_INT(depth, + "Ethernet Tag ID", + msg->route_type_specific.mac_ip_adv_route.ethernet_tag_id); + + PARSEBGP_DUMP_INT(depth, "MAC Address Length", + msg->route_type_specific.mac_ip_adv_route.mac_addr_len); + + if (msg->route_type_specific.mac_ip_adv_route.mac_addr_len == 4) { + PARSEBGP_DUMP_IP(depth, + "MAC Address", + PARSEBGP_BGP_AFI_IPV4, + msg->route_type_specific.mac_ip_adv_route.mac_addr + ); + } else { + PARSEBGP_DUMP_IP(depth, + "MAC Address", + PARSEBGP_BGP_AFI_IPV6, + msg->route_type_specific.mac_ip_adv_route.mac_addr + ); + } + + PARSEBGP_DUMP_INT(depth, "IP Address Length", + msg->route_type_specific.mac_ip_adv_route.ip_addr_len); + + if (msg->route_type_specific.mac_ip_adv_route.ip_addr_len == 4) { + PARSEBGP_DUMP_IP(depth, + "IP Address", + PARSEBGP_BGP_AFI_IPV4, + msg->route_type_specific.mac_ip_adv_route.ip_addr + ); + } else if(msg->route_type_specific.mac_ip_adv_route.ip_addr_len == 16) { + PARSEBGP_DUMP_IP(depth, + "IP Address", + PARSEBGP_BGP_AFI_IPV6, + msg->route_type_specific.mac_ip_adv_route.ip_addr + ); + } + + PARSEBGP_DUMP_DATA(depth, + "MPLS Label 1", + msg->route_type_specific.mac_ip_adv_route.mpls_label1, + sizeof(msg->route_type_specific.mac_ip_adv_route.mpls_label1)); + PARSEBGP_DUMP_DATA(depth, + "MPLS Label 2", + msg->route_type_specific.mac_ip_adv_route.mpls_label1, + sizeof(msg->route_type_specific.mac_ip_adv_route.mpls_label1)); + + + break; + + case PARSEBGP_BGP_UPDATE_MP_REACH_EVPN_INCLUSIVE_MULTICAST_ETHERNET_TAG: + PARSEBGP_DUMP_STRUCT_HDR( + parsebgp_bgp_update_mp_reach_evpn_inclusive_multicast_ethernet_tag_route_t, + depth); + + PARSEBGP_DUMP_DATA(depth, + "Route Distinguisher", + msg->route_type_specific.incl_multicast_eth_tag_route.route_distinguisher, + sizeof(msg->route_type_specific.incl_multicast_eth_tag_route.route_distinguisher)); + PARSEBGP_DUMP_INT(depth, + "Ethernet Tag ID", + msg->route_type_specific.incl_multicast_eth_tag_route.ethernet_tag_id); + + PARSEBGP_DUMP_INT(depth, "IP Address Length", + msg->route_type_specific.incl_multicast_eth_tag_route.ip_addr_len); + + if (msg->route_type_specific.incl_multicast_eth_tag_route.ip_addr_len == 4) { + PARSEBGP_DUMP_IP(depth, + "IP Address", + PARSEBGP_BGP_AFI_IPV4, + msg->route_type_specific.incl_multicast_eth_tag_route.ip_addr + ); + } else { + PARSEBGP_DUMP_IP(depth, + "IP Address", + PARSEBGP_BGP_AFI_IPV6, + msg->route_type_specific.incl_multicast_eth_tag_route.ip_addr + ); + } + + break; + + case PARSEBGP_BGP_UPDATE_MP_REACH_EVPN_ETHERNET_SEGMENT_ROUTE: + PARSEBGP_DUMP_STRUCT_HDR( + parsebgp_bgp_update_mp_reach_evpn_ethernet_segment_route_t, + depth); + + PARSEBGP_DUMP_DATA(depth, + "Route Distinguisher", + msg->route_type_specific.eth_segment_route.route_distinguisher, + sizeof(msg->route_type_specific.eth_segment_route.route_distinguisher)); + PARSEBGP_DUMP_DATA(depth, + "Ethernet Segment Identifier", + msg->route_type_specific.eth_segment_route.ethernet_segment_identifier, + sizeof(msg->route_type_specific.eth_segment_route.ethernet_segment_identifier)); + + PARSEBGP_DUMP_INT(depth, "IP Address Length", + msg->route_type_specific.eth_segment_route.ip_addr_len); + + if (msg->route_type_specific.eth_segment_route.ip_addr_len == 4) { + PARSEBGP_DUMP_IP(depth, + "IP Address", + PARSEBGP_BGP_AFI_IPV4, + msg->route_type_specific.eth_segment_route.ip_addr + ); + } else { + PARSEBGP_DUMP_IP(depth, + "IP Address", + PARSEBGP_BGP_AFI_IPV6, + msg->route_type_specific.eth_segment_route.ip_addr + ); + } + + break; + } + +} + +void parsebgp_bgp_update_mp_reach_evpn_destroy( + parsebgp_bgp_update_mp_reach_evpn_t *msg) { + return; +} + +void parsebgp_bgp_update_mp_reach_evpn_clear( + parsebgp_bgp_update_mp_reach_evpn_t *msg) { + return; +} + diff --git a/lib/bgp/parsebgp_bgp_update_mp_reach_evpn.h b/lib/bgp/parsebgp_bgp_update_mp_reach_evpn.h new file mode 100644 index 0000000..37cdbfc --- /dev/null +++ b/lib/bgp/parsebgp_bgp_update_mp_reach_evpn.h @@ -0,0 +1,171 @@ +#ifndef __PARSEBGP_BGP_UPDATE_MP_REACH_EVPN_H +#define __PARSEBGP_BGP_UPDATE_MP_REACH_EVPN_H + +#include "parsebgp_error.h" +#include "parsebgp_opts.h" +#include +#include + +typedef enum{ + + /** Type = 1 Ethernet Auto-Discovery (A - D) route */ + PARSEBGP_BGP_UPDATE_MP_REACH_EVPN_ETHERNET_AD = 1, + + /** Type = 2 MAC/IP Advertisement route */ + PARSEBGP_BGP_UPDATE_MP_REACH_EVPN_MAC_IP_ADVERTISMENT = 2, + + /** Type = 3 Inclusive Multicast Ethernet Tag route */ + PARSEBGP_BGP_UPDATE_MP_REACH_EVPN_INCLUSIVE_MULTICAST_ETHERNET_TAG = 3, + + /** Type = 4 Ethernet Segment route */ + PARSEBGP_BGP_UPDATE_MP_REACH_EVPN_ETHERNET_SEGMENT_ROUTE = 4, + +}parsebgp_bgp_update_mp_reach_evpn_route_types_t; + +/** + * Struct for ethernet Auto-discovery route + */ +typedef struct parsebgp_bgp_update_mp_reach_evpn_ethernet_ad_route { + + /** Route Distinguisher */ + uint8_t route_distinguisher[8]; + + /** Ethernet Segment Identifier */ + uint8_t ethernet_segment_identifier[10]; + + /** Ethernet Tag ID */ + uint32_t ethernet_tag_id; + + /** MPLS Label */ + uint8_t mpls_label[3]; + +} parsebgp_bgp_update_mp_reach_evpn_ethernet_ad_route_t; + +/** + * Struct for MAC/IP Advertisement Route + */ +typedef struct parsebgp_bgp_update_mp_reach_evpn_mac_ip_advertisement_route { + /** Route Distinguisher */ + uint8_t route_distinguisher[8]; + + /** Ethernet Segment Identifier */ + uint8_t ethernet_segment_identifier[10]; + + /** Ethernet Tag ID */ + uint32_t ethernet_tag_id; + + /** MAC Address Length */ + uint8_t mac_addr_len; + + /** MAC Address */ + uint8_t mac_addr[6]; + + /** IP Address Length */ + uint8_t ip_addr_len; + + /** IP Address (0, 4, 16) */ + uint8_t ip_addr[16]; + + /** MPLS Label */ + uint8_t mpls_label1[3]; + + /** MPLS Label */ + uint8_t mpls_label2[3]; + +} parsebgp_bgp_update_mp_reach_evpn_mac_ip_advertisement_route_t; + +/** + * Struct for Inclusive Multicast Ethernet Tag Route + */ +typedef struct parsebgp_bgp_update_mp_reach_evpn_inclusive_multicast_ethernet_tag_route { + /** Route Distinguisher */ + uint8_t route_distinguisher[8]; + + /** Ethernet Tag ID */ + uint32_t ethernet_tag_id; + + /** IP Address Length */ + uint8_t ip_addr_len; + + /** IP Address (4, 16) */ + uint8_t ip_addr[16]; + +} parsebgp_bgp_update_mp_reach_evpn_inclusive_multicast_ethernet_tag_route_t; + +/** + * Struct for Ethernet Segment Route + */ +typedef struct parsebgp_bgp_update_mp_reach_evpn_ethernet_segment_route { + /** Route Distinguisher */ + uint8_t route_distinguisher[8]; + + /** Ethernet Segment Identifier */ + uint8_t ethernet_segment_identifier[10]; + + /** IP Address Length */ + uint8_t ip_addr_len; + + /** IP Address (4, 16) */ + uint8_t ip_addr[16]; + +} parsebgp_bgp_update_mp_reach_evpn_ethernet_segment_route_t; + +/** + * Struct is used for evpn + */ +typedef struct parsebgp_bgp_update_mp_reach_evpn { + + /** Route Type definrs the encoding of the rest of message (len = 1)*/ + uint8_t route_type; + + /** Length of the rest of the message (len = 1) */ + uint8_t length; + + + union route_specific { + /** Ethernet Auto-Discovery route type specific EVPN NLRI */ + parsebgp_bgp_update_mp_reach_evpn_ethernet_ad_route_t eth_ad_route; + + /** MAC/IP Advertisement route type specific EVPN NLRI */ + parsebgp_bgp_update_mp_reach_evpn_mac_ip_advertisement_route_t mac_ip_adv_route; + + /** Inclusive Multicast Ethernet Tag route type specific EVPN NLRI */ + parsebgp_bgp_update_mp_reach_evpn_inclusive_multicast_ethernet_tag_route_t incl_multicast_eth_tag_route; + + /** Ethernet Segment route type specific EVPN NLRI */ + parsebgp_bgp_update_mp_reach_evpn_ethernet_segment_route_t eth_segment_route; + } route_type_specific; + +} parsebgp_bgp_update_mp_reach_evpn_t; + +/** Decode a BGP LS message */ +parsebgp_error_t +parsebgp_bgp_update_mp_reach_evpn_decode(parsebgp_opts_t *opts, + parsebgp_bgp_update_mp_reach_evpn_t *msg, + uint8_t *buf, size_t *lenp, size_t remain); + +/** + * Dump a human-readable version of the message to stdout + * + * @param msg Pointer to the parsed MP_REACH_EVPN attribute to dump + * @param depth Depth of the message within the overall message + * + * The output from these functions is designed to help with debugging the + * library and also includes internal implementation information like the names + * and sizes of structures. It may be useful to potential users of the library + * to get a sense of their data. + */ +void parsebgp_bgp_update_mp_reach_evpn_dump( + parsebgp_bgp_update_mp_reach_evpn_t *msg, int depth); + +/** Destroy a BGP Link State message */ +void parsebgp_bgp_update_mp_reach_evpn_destroy( + parsebgp_bgp_update_mp_reach_evpn_t *msg); + +/** Clear a BGP Link State message */ +void parsebgp_bgp_update_mp_reach_evpn_clear( + parsebgp_bgp_update_mp_reach_evpn_t *msg); + + + +#endif //__PARSEBGP_BGP_UPDATE_MP_REACH_EVPN_H