TODO: Refactor this method as it's overloaded - each case statement can be its own method * Parse all EVPN nlri's * * * \details * Parsing based on https://tools.ietf.org/html/rfc7432. Will process all NLRI's in data. * * \param [in] data Pointer to the start of the prefixes to be parsed * \param [in] data_len Length of t
| 253 | * |
| 254 | */ |
| 255 | void EVPN::parseNlriData(u_char *data, uint16_t data_len) { |
| 256 | u_char *data_pointer = data; |
| 257 | u_char ip_binary[16]; |
| 258 | int addr_bytes; |
| 259 | char ip_char[40]; |
| 260 | int data_read = 0; |
| 261 | |
| 262 | while ((data_read + 10 /* min read */) < data_len) { |
| 263 | bgp::evpn_tuple tuple; |
| 264 | |
| 265 | //Cleanup variables in case of not modified |
| 266 | tuple.mpls_label_1 = 0; |
| 267 | tuple.mpls_label_2 = 0; |
| 268 | tuple.mac_len = 0; |
| 269 | tuple.ip_len = 0; |
| 270 | |
| 271 | |
| 272 | // TODO: Keep an eye on this, as we might need to support add-paths for evpn |
| 273 | tuple.path_id = 0; |
| 274 | tuple.originating_router_ip_len = 0; |
| 275 | |
| 276 | uint8_t route_type = *data_pointer; |
| 277 | data_pointer++; |
| 278 | |
| 279 | int len = *data_pointer; |
| 280 | data_pointer++; |
| 281 | |
| 282 | parseRouteDistinguisher( |
| 283 | data_pointer, |
| 284 | &tuple.rd_type, |
| 285 | &tuple.rd_assigned_number, |
| 286 | &tuple.rd_administrator_subfield |
| 287 | ); |
| 288 | data_pointer += 8; |
| 289 | |
| 290 | data_read += 10; |
| 291 | len -= 8; // len doesn't include the route type and len octets |
| 292 | |
| 293 | switch (route_type) { |
| 294 | case EVPN_ROUTE_TYPE_ETHERNET_AUTO_DISCOVERY: { |
| 295 | |
| 296 | if ((data_read + 17 /* expected read size */) <= data_len) { |
| 297 | |
| 298 | // Ethernet Segment Identifier (10 bytes) |
| 299 | parseEthernetSegmentIdentifier(data_pointer, &tuple.ethernet_segment_identifier); |
| 300 | data_pointer += 10; |
| 301 | |
| 302 | //Ethernet Tag Id (4 bytes), printing in hex. |
| 303 | |
| 304 | u_char ethernet_id[4]; |
| 305 | bzero(ðernet_id, 4); |
| 306 | memcpy(ðernet_id, data_pointer, 4); |
| 307 | data_pointer += 4; |
| 308 | |
| 309 | std::stringstream ethernet_tag_id_stream; |
| 310 | |
| 311 | for (int i = 0; i < 4; i++) { |
| 312 | ethernet_tag_id_stream << std::hex << setfill('0') << setw(2) << (int) ethernet_id[i]; |
no test coverage detected