summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorluqiuwen <[email protected]>2018-12-23 15:22:57 +0600
committerluqiuwen <[email protected]>2018-12-23 15:22:57 +0600
commita726a5d480383baf1657d32ac2f44aef0d47b1b3 (patch)
tree8cd7a9c1dc335433948a4af6548917a4261cfd01
parent4ba447f6fd1612347ea72ed0f81ac03d09f95d38 (diff)
增加Ethernet over MPLS的解析功能及对应的单元测试用例v4.3.3-20181223
-rw-r--r--infra/src/ldbc.c39
-rw-r--r--infra/test/TestPacketParser.cc78
-rw-r--r--infra/test/mpls_eth.pcapbin0 -> 471 bytes
-rw-r--r--infra/test/mpls_pw.pcapbin0 -> 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
new file mode 100644
index 0000000..906d788
--- /dev/null
+++ b/infra/test/mpls_eth.pcap
Binary files differ
diff --git a/infra/test/mpls_pw.pcap b/infra/test/mpls_pw.pcap
new file mode 100644
index 0000000..efa273b
--- /dev/null
+++ b/infra/test/mpls_pw.pcap
Binary files differ