diff options
| author | luqiuwen <[email protected]> | 2018-12-23 15:22:57 +0600 |
|---|---|---|
| committer | luqiuwen <[email protected]> | 2018-12-23 15:22:57 +0600 |
| commit | a726a5d480383baf1657d32ac2f44aef0d47b1b3 (patch) | |
| tree | 8cd7a9c1dc335433948a4af6548917a4261cfd01 | |
| parent | 4ba447f6fd1612347ea72ed0f81ac03d09f95d38 (diff) | |
增加Ethernet over MPLS的解析功能及对应的单元测试用例v4.3.3-20181223
| -rw-r--r-- | infra/src/ldbc.c | 39 | ||||
| -rw-r--r-- | infra/test/TestPacketParser.cc | 78 | ||||
| -rw-r--r-- | infra/test/mpls_eth.pcap | bin | 0 -> 471 bytes | |||
| -rw-r--r-- | infra/test/mpls_pw.pcap | bin | 0 -> 159 bytes |
4 files changed, 111 insertions, 6 deletions
diff --git a/infra/src/ldbc.c b/infra/src/ldbc.c index f1e3fa1..0c90978 100644 --- a/infra/src/ldbc.c +++ b/infra/src/ldbc.c @@ -132,7 +132,7 @@ static const void * __complex_parser_ipv4(struct pkt_parser * handler, return data; struct ipv4_hdr * ipv4_hdr = (struct ipv4_hdr *)data; - unsigned int ipv4_hdr_len = (ipv4_hdr->version_ihl & 0xf) * 4; + unsigned int ipv4_hdr_len = (ipv4_hdr->version_ihl & 0xf) * 4u; void * data_next_layer = (uint8_t *)data + ipv4_hdr_len; switch (ipv4_hdr->next_proto_id) @@ -206,14 +206,41 @@ static const void * __complex_parser_mpls_uc(struct pkt_parser * handler, unsigned int mpls_bls = (ntohl(*_mpls_header) & MPLS_BLS_MASK) >> 8; void * data_next_layer = _mpls_header + 1; + uint8_t * __data_next_layer = (uint8_t *)data_next_layer; // 判断MPLS是否是最后一个,如果是,认为下一层是IPv4 - // TODO: 解析下一层协议类型。路由器是怎么解析的? - + // 下一层协议解析,参看Linux内核实现,直接判断IPv4/IPv6版本号。 + // 现网中遇到了MPLS后是以太头的报文,不符合RFC。现直接判断是否为v4/v6,否则按以太报文处理。 + // https://github.com/torvalds/linux/blob/9097a058d49e049925d8da72db07fffcee24efa0/drivers/net/tun.c#L1876 if (mpls_bls == 1) - { - return __complex_parser_ipv4(handler, data_next_layer, LAYER_TYPE_IPV4); - } + { + uint8_t ip_version = (__data_next_layer[0]) >> 4; + if (ip_version == 4) + { + return __complex_parser_ipv4(handler, data_next_layer, LAYER_TYPE_IPV4); + } + else if (ip_version == 6) + { + return __complex_parser_ipv6(handler, data_next_layer, LAYER_TYPE_IPV6); + } + + /* PW Ethernet Control Word, + * 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + |0 0 0 0| Reserved | Sequence Number | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * Reference: https://tools.ietf.org/html/rfc4448 + */ + else if(ip_version == 0) + { + return __complex_parser_ether(handler, data_next_layer + 4, LAYER_TYPE_ETHER); + } + else + { + return __complex_parser_ether(handler, data_next_layer, LAYER_TYPE_ETHER); + } + } // 如果不是,嵌套的MPLS标签,解下一个 else diff --git a/infra/test/TestPacketParser.cc b/infra/test/TestPacketParser.cc index 462526c..ce77505 100644 --- a/infra/test/TestPacketParser.cc +++ b/infra/test/TestPacketParser.cc @@ -183,6 +183,51 @@ static const unsigned char pkt94[98] = { 0x05, 0xb4 /* .. */ }; +/* Frame (119 bytes) + * 81.211.157.203 10.160.72.52 UDP 119 6564 → 13530 Len=39 + */ +static const unsigned char pkt_mpls_pw[119] = { + 0x18, 0x10, 0x04, 0x00, 0x00, 0x1c, 0x00, 0x00, /* ........ */ + 0x00, 0x00, 0x04, 0x36, 0x88, 0x47, 0x93, 0x75, /* ...6.G.u */ + 0x0a, 0xff, 0x4a, 0xe5, 0x0a, 0xff, 0xc3, 0x60, /* ..J....` */ + 0x2b, 0xff, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x49, /* +......I */ + 0x0b, 0xc0, 0x71, 0xca, 0x28, 0xa6, 0xdb, 0xee, /* ..q.(... */ + 0xb0, 0xd0, 0x81, 0x00, 0xa4, 0xad, 0x81, 0x00, /* ........ */ + 0xa1, 0x04, 0x08, 0x00, 0x45, 0xb8, 0x00, 0x43, /* ....E..C */ + 0x52, 0xee, 0x00, 0x00, 0x3e, 0x11, 0xe6, 0x91, /* R...>... */ + 0x51, 0xd3, 0x9d, 0xcb, 0x0a, 0xa0, 0x48, 0x34, /* Q.....H4 */ + 0x19, 0xa4, 0x34, 0xda, 0x00, 0x2f, 0x00, 0x00, /* ..4../.. */ + 0x8e, 0x2e, 0x09, 0x08, 0x02, 0x1b, 0x30, 0x0a, /* ......0. */ + 0x20, 0x88, 0xec, 0xfc, 0xcf, 0x2f, 0xa4, 0x3f, /* ..../.? */ + 0x59, 0x58, 0xb4, 0x05, 0x90, 0x84, 0x05, 0x0c, /* YX...... */ + 0x06, 0x86, 0x9e, 0x3b, 0x79, 0xa9, 0x0f, 0x0d, /* ...;y... */ + 0x11, 0x08, 0xf8, 0x64, 0x90, 0x32, 0x06 /* ...d.2. */ +}; + +/* Frame (143 bytes) + * 10.33.60.116 217.76.77.34 GTP <DNS> 143 Standard query 0xc4a8 A config.inmobi.com + * */ +static const unsigned char pkt_mpls_eth[143] = { + 0x18, 0x10, 0x04, 0x00, 0x00, 0x1c, 0x00, 0x00, /* ........ */ + 0x00, 0x00, 0x04, 0x17, 0x88, 0x47, 0x40, 0x14, /* .....G@. */ + 0x41, 0xfd, 0x04, 0x27, 0x58, 0x6f, 0x9f, 0x8d, /* A..'Xo.. */ + 0x28, 0xa6, 0xdb, 0xee, 0xb0, 0x97, 0x81, 0x00, /* (....... */ + 0x01, 0x4d, 0x81, 0x00, 0x02, 0xc3, 0x88, 0x47, /* .M.....G */ + 0x08, 0x05, 0x21, 0xff, 0x45, 0x00, 0x00, 0x63, /* ..!.E..c */ + 0x86, 0xbe, 0x00, 0x00, 0xfd, 0x11, 0x54, 0x69, /* ......Ti */ + 0x51, 0xd3, 0x87, 0x91, 0x51, 0xd3, 0xb7, 0x2a, /* Q...Q..* */ + 0x08, 0x68, 0x08, 0x68, 0x00, 0x4f, 0x33, 0xa3, /* .h.h.O3. */ + 0x30, 0xff, 0x00, 0x3f, 0x0d, 0x24, 0x07, 0x59, /* 0..?.$.Y */ + 0x45, 0x00, 0x00, 0x3f, 0x7f, 0x24, 0x40, 0x00, /* E..?.$@. */ + 0x40, 0x11, 0x4e, 0x86, 0x0a, 0x21, 0x3c, 0x74, /* @.N..!<t */ + 0xd9, 0x4c, 0x4d, 0x22, 0x9c, 0x5c, 0x00, 0x35, /* .LM".\.5 */ + 0x00, 0x2b, 0x3f, 0x00, 0xc4, 0xa8, 0x01, 0x00, /* .+?..... */ + 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ + 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x06, /* .config. */ + 0x69, 0x6e, 0x6d, 0x6f, 0x62, 0x69, 0x03, 0x63, /* inmobi.c */ + 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01 /* om..... */ +}; + #define TestCheckIPv4Addr(__result, __str_src_addr, __str_dst_addr) \ do { \ struct ipv4_hdr * _ipv4_hdr = (struct ipv4_hdr *)__result->data; \ @@ -260,6 +305,39 @@ TEST(PacketParseOuterL3, EtherIPv6) "3ffe:501:410:0:2c0:dfff:fe47:33e"); } +TEST(PacketParserOuterL3, EthernetOverMPLSWithPW) +{ + struct pkt_parser _pkt_mpls_handler; + _pkt_mpls_handler.expect_layer_type = LAYER_TYPE_L3; + _pkt_mpls_handler.nr_expect_results = 1; + _pkt_mpls_handler.nr_results = 0; + + ASSERT_TRUE(complex_parser_ether(&_pkt_mpls_handler, pkt_mpls_pw) != NULL); + EXPECT_EQ(_pkt_mpls_handler.nr_results, 1); + + struct pkt_parser_result * result = &_pkt_mpls_handler.results[0]; + EXPECT_EQ(result->this_layer_type, LAYER_TYPE_IPV4); + EXPECT_TRUE(result->data != NULL); + + TestCheckIPv4Addr(result, "81.211.157.203", "10.160.72.52"); +} + +TEST(PacketParserOuterL3, EthernetOverMPLSWithoutPW) +{ + struct pkt_parser _pkt_mpls_handler; + _pkt_mpls_handler.expect_layer_type = LAYER_TYPE_L3; + _pkt_mpls_handler.nr_expect_results = 1; + _pkt_mpls_handler.nr_results = 0; + + ASSERT_TRUE(complex_parser_ether(&_pkt_mpls_handler, pkt_mpls_eth) != NULL); + EXPECT_EQ(_pkt_mpls_handler.nr_results, 1); + + struct pkt_parser_result * result = &_pkt_mpls_handler.results[0]; + EXPECT_EQ(result->this_layer_type, LAYER_TYPE_IPV4); + EXPECT_TRUE(result->data != NULL); + TestCheckIPv4Addr(result, "81.211.135.145", "81.211.183.42"); +} + TEST(PacketParseOuterL4, EtherIPv4TCP) { struct pkt_parser _pkt_031_handler; diff --git a/infra/test/mpls_eth.pcap b/infra/test/mpls_eth.pcap Binary files differnew file mode 100644 index 0000000..906d788 --- /dev/null +++ b/infra/test/mpls_eth.pcap diff --git a/infra/test/mpls_pw.pcap b/infra/test/mpls_pw.pcap Binary files differnew file mode 100644 index 0000000..efa273b --- /dev/null +++ b/infra/test/mpls_pw.pcap |
