diff --git a/scapy/contrib/geneve.py b/scapy/contrib/geneve.py index b44cb543331..f6d1a737e48 100644 --- a/scapy/contrib/geneve.py +++ b/scapy/contrib/geneve.py @@ -14,11 +14,13 @@ import struct -from scapy.fields import BitField, XByteField, XShortEnumField, X3BytesField, StrLenField, PacketListField +from scapy.fields import BitField, XByteField, XShortEnumField, X3BytesField, \ + StrLenField, PacketField, PacketListField, MultipleTypeField from scapy.packet import Packet, bind_layers from scapy.layers.inet import IP, UDP from scapy.layers.inet6 import IPv6 from scapy.layers.l2 import Ether, ETHER_TYPES +from scapy.contrib.int import INTMetaMd, INTMetaMx CLASS_IDS = {0x0100: "Linux", 0x0101: "Open vSwitch", @@ -49,6 +51,44 @@ def post_build(self, p, pay): p = p[:3] + struct.pack("!B", (p[3] & 0x3) | (tmp_len & 0x1f)) + p[4:] return p + pay + @classmethod + def dispatch_hook(cls, _pkt=None, *args, **kargs): + if _pkt and len(_pkt) >= 2: + classid = struct.unpack("!H", _pkt[:2])[0] + if classid == 0x0103: + return GeneveOptINT + return cls + + +class GeneveOptINT(Packet): + name = "Geneve Option INT" + fields_desc = [ + XShortEnumField("classid", 0x0000, CLASS_IDS), + XByteField("type", 0x03), + BitField("reserved", 0, 3), + BitField("length", 1, 5), + MultipleTypeField([ + (PacketField('metadata', None, INTMetaMd), lambda pkt: pkt.type == 1), + (PacketField('metadata', None, INTMetaMx), lambda pkt: pkt.type == 3), ], + PacketField('metadata', None, INTMetaMd) + ), + ] + + def post_build(self, pkt, pay): + tmp_len = len(self.metadata) // 4 + old_value = struct.unpack("B", pkt[3:4])[0] + new_value = (old_value & 0b11100000) | (tmp_len & 0b00011111) + pkt = pkt[:3] + struct.pack("B", new_value) + pkt[4:] + return pkt + pay + + @classmethod + def dispatch_hook(cls, _pkt=None, *args, **kargs): + if _pkt and len(_pkt) >= 2: + classid = struct.unpack("!H", _pkt[:2])[0] + if classid != 0x0103: + return GeneveOptions + return cls + class GENEVE(Packet): name = "GENEVE" diff --git a/scapy/contrib/int.py b/scapy/contrib/int.py new file mode 100644 index 00000000000..401d15b652c --- /dev/null +++ b/scapy/contrib/int.py @@ -0,0 +1,277 @@ +# scapy.contrib.description = Inband Network Telemetry Protocol (INT) +# scapy.contrib.status = loads + +''' +Inband Network Telemetry Protocol (INT) + +References: +https://staging.p4.org/p4-spec/docs/INT_v2_1.pdf +https://staging.p4.org/p4-spec/docs/telemetry_report_v2_0.pdf +https://github.com/p4lang/p4-applications + +Example Packet Formate: +INT-MX mode: +INToGre = Ether/IP/GRE/INTShimGre/INTMetaMx/Raw +INToTCP = Ether/IP/TCP/INTShimTcpUdp/INTMetaMx/Raw +INToUDP = Ether/IP/UDP/INTShimTcpUdp/INTMetaMx/Raw +INToVXLAN = Ether/IP/UDP/VXLAN/INTShimVxlan/INTMetaMx/Raw +INToGENEVE = Ether/IP/UDP/GENEVE/GeneveOptINT/INTMetaMx/Raw + +INT-MD mode: +INToGre = Ether/IP/GRE/INTShimGre/INTMetaMd/INTMetaHop/Raw +INToTCP = Ether/IP/TCP/INTShimTcpUdp/INTMetaMd/INTMetaHop/Raw +INToUDP = Ether/IP/UDP/INTShimTcpUdp/INTMetaMd/INTMetaHop/Raw +INToVXLAN = Ether/IP/UDP/VXLAN/INTShimVxlan/INTMetaMd/INTMetaHop/Raw +INToGENEVE = Ether/IP/UDP/GENEVE/GeneveOptINT/INTMetaMd/INTMetaHop/Raw +''' + +import struct +from scapy.packet import Packet, bind_layers +from scapy.fields import BitField, BitEnumField, FlagsField, ByteField, \ + ShortField, IntField, LongField, FieldLenField, ConditionalField, \ + MultipleTypeField, PacketField, PacketListField +from scapy.layers.l2 import GRE +from scapy.layers.inet import TCP, UDP +from scapy.layers.vxlan import VXLAN + +INT_PRI_MASK = 0x80 +INT_L4_DPORT = 0x4568 +INT_GRE_PROTOCOL = 0x4569 +INT_VXLAN_PROTOCOL = 0x82 +INT_GENEVE_CLASSID = 0x0103 + +_INT_TYPE = { + 1: 'INT-MD', + 2: 'INT-DST', + 3: 'INT-MX', +} + +_INT_GRE = { + 0: 'Original packet with GRE', + 1: 'Original packet without GRE', +} + +_INT_GPE = { + 0: 'Original packet used VXLAN GPE encapsulation', + 1: 'Original packet used VXLAN encapsulation', +} + +_INT_INSTR_BITMAP = [ + 'checksum', + 'reserved14', + 'reserved13', + 'reserved12', + 'reserved11', + 'reserved10', + 'reserved9', + 'buf_info', + 'tx_info', + 'l2_intf', + 'egr_ts', + 'igr_ts', + 'que_info', + 'latency', + 'l1_intf', + 'node_id', +] + + +class INTMetaHop(Packet): + name = 'INTMetaHop' + fields_desc = [ + ConditionalField( + IntField('node_id', 0), + lambda pkt:pkt.parent.instr_bitmap & (0x1 << (15 - 0)) + ), + ConditionalField( + ShortField('igr_l1_intf', 0), + lambda pkt:pkt.parent.instr_bitmap & (0x1 << (15 - 1)) + ), + ConditionalField( + ShortField('egr_l1_intf', 0), + lambda pkt:pkt.parent.instr_bitmap & (0x1 << (15 - 1)) + ), + ConditionalField( + IntField('latency', 0), + lambda pkt:pkt.parent.instr_bitmap & (0x1 << (15 - 2)) + ), + ConditionalField( + BitField('que_id', 0, 8), + lambda pkt:pkt.parent.instr_bitmap & (0x1 << (15 - 3)) + ), + ConditionalField( + BitField('que_occupy', 0, 24), + lambda pkt:pkt.parent.instr_bitmap & (0x1 << (15 - 3)) + ), + ConditionalField( + LongField('igr_ts', 0), + lambda pkt:pkt.parent.instr_bitmap & (0x1 << (15 - 4)) + ), + ConditionalField( + LongField('egr_ts', 0), + lambda pkt:pkt.parent.instr_bitmap & (0x1 << (15 - 5)) + ), + ConditionalField( + IntField('igr_l2_intf', 0), + lambda pkt:pkt.parent.instr_bitmap & (0x1 << (15 - 6)) + ), + ConditionalField( + IntField('egr_l2_intf', 0), + lambda pkt:pkt.parent.instr_bitmap & (0x1 << (15 - 6)) + ), + ConditionalField( + IntField('egr_tx_info', 0), + lambda pkt:pkt.parent.instr_bitmap & (0x1 << (15 - 7)) + ), + ConditionalField( + BitField('buf_id', 0, 8), + lambda pkt:pkt.parent.instr_bitmap & (0x1 << (15 - 8)) + ), + ConditionalField( + BitField('buf_occupy', 0, 24), + lambda pkt:pkt.parent.instr_bitmap & (0x1 << (15 - 8)) + ), + ConditionalField( + IntField('reserved9', 0xffffffff), + lambda pkt:pkt.parent.instr_bitmap & (0x1 << (15 - 9)) + ), + ConditionalField( + IntField('reserved10', 0xffffffff), + lambda pkt:pkt.parent.instr_bitmap & (0x1 << (15 - 10)) + ), + ConditionalField( + IntField('reserved11', 0xffffffff), + lambda pkt:pkt.parent.instr_bitmap & (0x1 << (15 - 11)) + ), + ConditionalField( + IntField('reserved12', 0xffffffff), + lambda pkt:pkt.parent.instr_bitmap & (0x1 << (15 - 12)) + ), + ConditionalField( + IntField('reserved13', 0xffffffff), + lambda pkt:pkt.parent.instr_bitmap & (0x1 << (15 - 13)) + ), + ConditionalField( + IntField('reserved14', 0xffffffff), + lambda pkt:pkt.parent.instr_bitmap & (0x1 << (15 - 14)) + ), + ConditionalField( + IntField('checksum', 0xffffffff), + lambda pkt:pkt.parent.instr_bitmap & (0x1 << (15 - 15)) + ), + ] + + def extract_padding(self, s): + return "", s + + +class INTMetaMx(Packet): + name = 'INTMetaMx' + fields_desc = [ + BitField('version', 0, 4), + BitField('discard', 0, 1), + BitField('reserved1', 0, 27), + FlagsField('instr_bitmap', 0xfe00, 16, _INT_INSTR_BITMAP), + ShortField('ds_id', 0), + ShortField('ds_instr', 0), + ShortField('ds_flags', 0), + ] + + def extract_padding(self, s): + return "", s + + +class INTMetaMd(Packet): + name = 'INTMetaMd' + fields_desc = [ + BitField('version', 0, 4), + BitField('discard', 0, 1), + BitField('exceed_mht', 0, 1), + BitField('exceed_mtu', 0, 1), + BitField('reserved0', 0, 12), + BitField('hop_len', 0, 5), + BitField('hop_left', 0, 8), + FlagsField('instr_bitmap', 0xfe00, 16, _INT_INSTR_BITMAP), + ShortField('ds_id', 0), + ShortField('ds_instr', 0), + ShortField('ds_flags', 0), + PacketListField('meta_hops', [], INTMetaHop, + length_from=lambda pkt: pkt.parent.length * 4 - 12), + ] + + def post_build(self, pkt, pay): + if self.meta_hops is not None: + tmp_len = len(self.meta_hops[0]) // 4 + old_value = struct.unpack("B", pkt[2:3])[0] + new_value = (old_value & 0b11100000) | (tmp_len & 0b00011111) + pkt = pkt[:2] + struct.pack("B", new_value) + pkt[3:] + return pkt + pay + + def extract_padding(self, s): + return "", s + + +class INTShimTcpUdp(Packet): + name = 'INTShimTcpUdp' + fields_desc = [ + BitEnumField('type', 1, 4, _INT_TYPE), + BitField('npt', 0, 2), + BitField('reserved1', 0, 2), + FieldLenField('length', None, + length_of="metadata", + adjust=lambda pkt, x: x // 4, fmt="B"), + ConditionalField(ByteField('reserved3', 0), lambda pkt: pkt.npt == 0), + ConditionalField(BitField('dscp', 0, 6), lambda pkt: pkt.npt == 0), + ConditionalField(BitField('reserved4', 0, 2), lambda pkt: pkt.npt == 0), + ConditionalField(ShortField('l4_dport', 0), lambda pkt: pkt.npt == 1), + ConditionalField(ByteField('ip_proto', 0), lambda pkt: pkt.npt == 2), + ConditionalField(ByteField('reserved5', 0), lambda pkt: pkt.npt == 2), + MultipleTypeField([ + (PacketField('metadata', None, INTMetaMd), lambda pkt: pkt.type == 1), + (PacketField('metadata', None, INTMetaMx), lambda pkt: pkt.type == 3), ], + PacketField('metadata', None, INTMetaMd) + ), + ] + + +class INTShimGre(Packet): + name = 'INTShimGre' + fields_desc = [ + BitEnumField('type', 1, 4, _INT_TYPE), + BitEnumField('gre', 0, 1, _INT_GRE), + BitField('reserved0', 0, 3), + FieldLenField('length', None, + length_of="metadata", + adjust=lambda pkt, x: x // 4, fmt="B"), + ShortField('gre_proto', 0), + MultipleTypeField([ + (PacketField('metadata', None, INTMetaMd), lambda pkt: pkt.type == 1), + (PacketField('metadata', None, INTMetaMx), lambda pkt: pkt.type == 3), ], + PacketField('metadata', None, INTMetaMd) + ), + ] + + +class INTShimVxlan(Packet): + name = 'INTShimVxlan' + fields_desc = [ + BitEnumField('type', 1, 4, _INT_TYPE), + BitField('reserved2', 0, 4), + FieldLenField('length', None, + length_of="metadata", + adjust=lambda pkt, x: x // 4, fmt="B"), + BitEnumField('gpe', 0, 1, _INT_GPE), + BitField('reserved6', 0, 7), + ByteField('vxlan_proto', 0), + MultipleTypeField([ + (PacketField('metadata', None, INTMetaMd), lambda pkt: pkt.type == 1), + (PacketField('metadata', None, INTMetaMx), lambda pkt: pkt.type == 3), ], + PacketField('metadata', None, INTMetaMd) + ), + ] + + +bind_layers(UDP, INTShimTcpUdp, dport=INT_L4_DPORT) +bind_layers(TCP, INTShimTcpUdp, dport=INT_L4_DPORT) +bind_layers(GRE, INTShimGre, proto=INT_GRE_PROTOCOL) +bind_layers(VXLAN, INTShimVxlan, NextProtocol=INT_VXLAN_PROTOCOL) diff --git a/scapy/layers/inet.py b/scapy/layers/inet.py index f46ed7f5e4e..b2bae593d05 100644 --- a/scapy/layers/inet.py +++ b/scapy/layers/inet.py @@ -806,6 +806,15 @@ def mysummary(self): else: return self.sprintf("TCP %TCP.sport% > %TCP.dport% %TCP.flags%") + def guess_payload_class(self, payload): + from scapy.contrib.int import INTShimTcpUdp, INT_PRI_MASK + if ((isinstance(self.underlayer, IP) and + ((self.underlayer.tos & INT_PRI_MASK) == INT_PRI_MASK)) or + (isinstance(self.underlayer, scapy.layers.inet6.IPv6) and + ((self.underlayer.tc & INT_PRI_MASK) == INT_PRI_MASK))): + return INTShimTcpUdp + return Packet.guess_payload_class(self, payload) + class UDP(Packet): name = "UDP" @@ -862,6 +871,15 @@ def mysummary(self): else: return self.sprintf("UDP %UDP.sport% > %UDP.dport%") + def guess_payload_class(self, payload): + from scapy.contrib.int import INTShimTcpUdp, INT_PRI_MASK + if ((isinstance(self.underlayer, IP) and + ((self.underlayer.tos & INT_PRI_MASK) == INT_PRI_MASK)) or + (isinstance(self.underlayer, scapy.layers.inet6.IPv6) and + ((self.underlayer.tc & INT_PRI_MASK) == INT_PRI_MASK))): + return INTShimTcpUdp + return Packet.guess_payload_class(self, payload) + icmptypes = {0: "echo-reply", 3: "dest-unreach", diff --git a/test/contrib/int.uts b/test/contrib/int.uts new file mode 100644 index 00000000000..b658b3b8b24 --- /dev/null +++ b/test/contrib/int.uts @@ -0,0 +1,698 @@ +% INT unit test + +# +# execute test: +# > test/run_tests -P "load_contrib('int')" -P "load_contrib('geneve')" -t test/contrib/int.uts +# TBD: IPv6 with ext header +# + ++ INT testsuit + + += Build & Dissect, INT MD Over IPv4 UDP, Identifier=DSCP/TC + +def check_int_shim(pkt:Packet): + if pkt.haslayer(INTShimTcpUdp): + assert (((pkt[INTShimTcpUdp].type == 1) and (pkt[INTShimTcpUdp].length == 23)) or + ((pkt[INTShimTcpUdp].type == 3) and (pkt[INTShimTcpUdp].length == 3))) + assert (((pkt[INTShimTcpUdp].npt == 0) and (pkt[INTShimTcpUdp].dscp == 0)) or + ((pkt[INTShimTcpUdp].npt == 1) and (pkt[INTShimTcpUdp].l4_dport == 9028))) + elif pkt.haslayer(INTShimGre): + assert (((pkt[INTShimGre].type == 1) and (pkt[INTShimGre].length == 23)) or + ((pkt[INTShimGre].type == 3) and (pkt[INTShimGre].length == 3))) + assert pkt[INTShimGre].gre == 0 + assert pkt[INTShimGre].gre_proto == 0x6558 + elif pkt.haslayer(INTShimVxlan): + assert (((pkt[INTShimVxlan].type == 1) and (pkt[INTShimVxlan].length == 23)) or + ((pkt[INTShimVxlan].type == 3) and (pkt[INTShimVxlan].length == 3))) + assert pkt[INTShimVxlan].gpe == 0 + assert pkt[INTShimVxlan].vxlan_proto == 3 + elif pkt.haslayer(GeneveOptINT): + assert (((pkt[GeneveOptINT].type == 1) and (pkt[GeneveOptINT].length == 23)) or + ((pkt[GeneveOptINT].type == 3) and (pkt[GeneveOptINT].length == 3))) + assert pkt[GeneveOptINT].classid == 0x0103 + else: + assert False + +def check_int_meta(pkt:Packet): + if pkt.haslayer(INTMetaMx): + assert pkt[INTMetaMx].version == 2 + assert pkt[INTMetaMx].discard == 0 + assert pkt[INTMetaMx].instr_bitmap == 0xfe00 + assert pkt[INTMetaMx].ds_id == 0x7777 + assert pkt[INTMetaMx].ds_instr == 0x8888 + assert pkt[INTMetaMx].ds_flags == 0x9999 + elif pkt.haslayer(INTMetaMd): + assert pkt[INTMetaMd].version == 2 + assert pkt[INTMetaMd].discard == 0 + assert pkt[INTMetaMd].hop_len == 10 + assert pkt[INTMetaMd].hop_left == 7 + assert pkt[INTMetaMd].instr_bitmap == 0xfe00 + assert pkt[INTMetaMd].ds_id == 0x7777 + assert pkt[INTMetaMd].ds_instr == 0x8888 + assert pkt[INTMetaMd].ds_flags == 0x9999 + assert len(pkt[INTMetaMd].meta_hops) == 2 + assert pkt[INTMetaMd].meta_hops[0].node_id == 0xb22 + assert pkt[INTMetaMd].meta_hops[0].igr_l1_intf == 20 + assert pkt[INTMetaMd].meta_hops[0].egr_l1_intf == 21 + assert pkt[INTMetaMd].meta_hops[0].latency == 0 + assert pkt[INTMetaMd].meta_hops[0].que_id == 0 + assert pkt[INTMetaMd].meta_hops[0].que_occupy == 0 + assert pkt[INTMetaMd].meta_hops[0].igr_ts == 0 + assert pkt[INTMetaMd].meta_hops[0].egr_ts == 0 + assert pkt[INTMetaMd].meta_hops[0].igr_l2_intf == 5 + assert pkt[INTMetaMd].meta_hops[0].egr_l2_intf == 6 + assert pkt[INTMetaMd].meta_hops[1].node_id == 0xa11 + assert pkt[INTMetaMd].meta_hops[1].igr_l1_intf == 10 + assert pkt[INTMetaMd].meta_hops[1].egr_l1_intf == 11 + assert pkt[INTMetaMd].meta_hops[1].latency == 0 + assert pkt[INTMetaMd].meta_hops[1].que_id == 0 + assert pkt[INTMetaMd].meta_hops[1].que_occupy == 0 + assert pkt[INTMetaMd].meta_hops[1].igr_ts == 0 + assert pkt[INTMetaMd].meta_hops[1].egr_ts == 0 + assert pkt[INTMetaMd].meta_hops[1].igr_l2_intf == 1 + assert pkt[INTMetaMd].meta_hops[1].egr_l2_intf == 2 + else: + assert False + +meta_hop0 = INTMetaHop(node_id=0xb22, igr_l1_intf=20, egr_l1_intf=21, igr_l2_intf=5, egr_l2_intf=6) +meta_hop1 = INTMetaHop(node_id=0xa11, igr_l1_intf=10, egr_l1_intf=11, igr_l2_intf=1, egr_l2_intf=2) +int_md = INTMetaMd(version=2, discard=0, hop_left=7, instr_bitmap=0xfe00, ds_id=0x7777, ds_instr=0x8888, ds_flags=0x9999, meta_hops=[meta_hop0, meta_hop1]) +int_mx = INTMetaMx(version=2, discard=0, instr_bitmap=0xfe00, ds_id=0x7777, ds_instr=0x8888, ds_flags=0x9999) + +pkt=Ether(src="b6:18:00:11:11:00", dst="b6:18:00:22:22:00")/ \ + IP(src="198.1.1.17", dst="198.1.2.18", ttl=63, tos=INT_PRI_MASK)/ \ + UDP(sport=4196, dport=9028)/ \ + INTShimTcpUdp(type=1, npt=0, dscp=0, metadata=int_md)/ \ + Raw('a'*64) + +pkt=Ether(raw(pkt)) +# pkt.show2() + +assert (pkt[IP].tos & INT_PRI_MASK) == INT_PRI_MASK +assert pkt[IP].proto == socket.IPPROTO_UDP +assert pkt[IP].chksum == 0xeb8a +assert pkt[UDP].sport == 4196 +assert pkt[UDP].dport == 9028 +assert pkt[UDP].chksum == 0x286c +check_int_shim(pkt) +check_int_meta(pkt) + += Build & Dissect, INT MD Over IPv4 TCP, Identifier=DSCP/TC + +pkt=Ether(src="b6:18:00:11:11:00", dst="b6:18:00:22:22:00")/ \ + IP(src="198.1.1.17", dst="198.1.2.18", ttl=63, tos=INT_PRI_MASK)/ \ + TCP(sport=4196, dport=9028)/ \ + INTShimTcpUdp(type=1, npt=0, dscp=0, metadata=int_md)/ \ + Raw('a'*64) + +pkt=Ether(raw(pkt)) +# pkt.show2() + +assert (pkt[IP].tos & INT_PRI_MASK) == INT_PRI_MASK +assert pkt[IP].proto == socket.IPPROTO_TCP +assert pkt[IP].chksum == 0xeb89 +assert pkt[TCP].sport == 4196 +assert pkt[TCP].dport == 9028 +assert pkt[TCP].chksum == 0xb910 +check_int_shim(pkt) +check_int_meta(pkt) + + += Build & Dissect, INT MD Over IPv6 UDP, Identifier=DSCP/TC + +pkt=Ether(src="b6:18:00:11:11:00", dst="b6:18:00:22:22:00")/ \ + IPv6(src="2000::1", dst="5000::1", hlim=63, tc=INT_PRI_MASK)/ \ + UDP(sport=4196, dport=9028)/ \ + INTShimTcpUdp(type=1, npt=0, dscp=0, metadata=int_md)/ \ + Raw('a'*64) + +pkt=Ether(raw(pkt)) +# pkt.show2() + +assert (pkt[IPv6].tc & INT_PRI_MASK) == INT_PRI_MASK +assert pkt[IPv6].nh == socket.IPPROTO_UDP +assert pkt[UDP].sport == 4196 +assert pkt[UDP].dport == 9028 +assert pkt[UDP].chksum == 0x4790 +check_int_shim(pkt) +check_int_meta(pkt) + + += Build & Dissect, INT MD Over IPv6 TCP, Identifier=DSCP/TC + +pkt=Ether(src="b6:18:00:11:11:00", dst="b6:18:00:22:22:00")/ \ + IPv6(src="2000::1", dst="5000::1", hlim=63, tc=INT_PRI_MASK)/ \ + TCP(sport=4196, dport=9028)/ \ + INTShimTcpUdp(type=1, npt=0, dscp=0, metadata=int_md)/ \ + Raw('a'*64) + +pkt=Ether(raw(pkt)) +# pkt.show2() + +assert (pkt[IPv6].tc & INT_PRI_MASK) == INT_PRI_MASK +assert pkt[IPv6].nh == socket.IPPROTO_TCP +assert pkt[TCP].sport == 4196 +assert pkt[TCP].dport == 9028 +assert pkt[TCP].chksum == 0xd834 +check_int_shim(pkt) +check_int_meta(pkt) + + += Build & Dissect, INT MX Over IPv4 UDP, Identifier=DSCP/TC + +pkt=Ether(src="b6:18:00:11:11:00", dst="b6:18:00:22:22:00")/ \ + IP(src="198.1.1.17", dst="198.1.2.18", ttl=63, tos=INT_PRI_MASK)/ \ + UDP(sport=4196, dport=9028)/ \ + INTShimTcpUdp(type=3, npt=0, dscp=0, metadata=int_mx)/ \ + Raw('a'*64) + +pkt=Ether(raw(pkt)) +# pkt.show2() + +assert (pkt[IP].tos & INT_PRI_MASK) == INT_PRI_MASK +assert pkt[IP].proto == socket.IPPROTO_UDP +assert pkt[IP].chksum == 0xebda +assert pkt[UDP].sport == 4196 +assert pkt[UDP].dport == 9028 +assert pkt[UDP].chksum == 0x28a6 +check_int_shim(pkt) +check_int_meta(pkt) + + += Build & Dissect, INT MX Over IPv4 TCP, Identifier=DSCP/TC + +pkt=Ether(src="b6:18:00:11:11:00", dst="b6:18:00:22:22:00")/ \ + IP(src="198.1.1.17", dst="198.1.2.18", ttl=63, tos=INT_PRI_MASK)/ \ + TCP(sport=4196, dport=9028)/ \ + INTShimTcpUdp(type=3, npt=0, dscp=0, metadata=int_mx)/ \ + Raw('a'*64) + +pkt=Ether(raw(pkt)) +# pkt.show2() + +assert (pkt[IP].tos & INT_PRI_MASK) == INT_PRI_MASK +assert pkt[IP].proto == socket.IPPROTO_TCP +assert pkt[IP].chksum == 0xebd9 +assert pkt[TCP].sport == 4196 +assert pkt[TCP].dport == 9028 +assert pkt[TCP].chksum == 0xb8fa +check_int_shim(pkt) +check_int_meta(pkt) + + += Build & Dissect, INT MX Over IPv6 UDP, Identifier=DSCP/TC + +pkt=Ether(src="b6:18:00:11:11:00", dst="b6:18:00:22:22:00")/ \ + IPv6(src="2000::1", dst="5000::1", hlim=63, tc=INT_PRI_MASK)/ \ + UDP(sport=4196, dport=9028)/ \ + INTShimTcpUdp(type=3, npt=0, dscp=0, metadata=int_mx)/ \ + Raw('a'*64) + +pkt=Ether(raw(pkt)) +# pkt.show2() + +assert (pkt[IPv6].tc & INT_PRI_MASK) == INT_PRI_MASK +assert pkt[IPv6].nh == socket.IPPROTO_UDP +assert pkt[UDP].sport == 4196 +assert pkt[UDP].dport == 9028 +assert pkt[UDP].chksum == 0x47ca +check_int_shim(pkt) +check_int_meta(pkt) + + += Build & Dissect, INT MX Over IPv6 TCP, Identifier=DSCP/TC + +pkt=Ether(src="b6:18:00:11:11:00", dst="b6:18:00:22:22:00")/ \ + IPv6(src="2000::1", dst="5000::1", hlim=63, tc=INT_PRI_MASK)/ \ + TCP(sport=4196, dport=9028)/ \ + INTShimTcpUdp(type=3, npt=0, dscp=0, metadata=int_mx)/ \ + Raw('a'*64) + +pkt=Ether(raw(pkt)) +# pkt.show2() + +assert (pkt[IPv6].tc & INT_PRI_MASK) == INT_PRI_MASK +assert pkt[IPv6].nh == socket.IPPROTO_TCP +assert pkt[TCP].sport == 4196 +assert pkt[TCP].dport == 9028 +assert pkt[TCP].chksum == 0xd81e +check_int_shim(pkt) +check_int_meta(pkt) + + += Build & Dissect, INT MD Over IPv4 UDP, Identifier=L4_DPORT + +pkt=Ether(src="b6:18:00:11:11:00", dst="b6:18:00:22:22:00")/ \ + IP(src="198.1.1.17", dst="198.1.2.18", ttl=63)/ \ + UDP(sport=4196, dport=INT_L4_DPORT)/ \ + INTShimTcpUdp(type=1, npt=1, l4_dport=9028, metadata=int_md)/ \ + Raw('a'*64) + +pkt=Ether(raw(pkt)) +# pkt.show2() + +assert pkt[IP].tos == 0 +assert pkt[IP].proto == socket.IPPROTO_UDP +assert pkt[IP].chksum == 0xec0a +assert pkt[UDP].sport == 4196 +assert pkt[UDP].dport == INT_L4_DPORT +assert pkt[UDP].chksum == 0xdf03 +check_int_shim(pkt) +check_int_meta(pkt) + + += Build & Dissect, INT MD Over IPv4 TCP, Identifier=L4_DPORT + +pkt=Ether(src="b6:18:00:11:11:00", dst="b6:18:00:22:22:00")/ \ + IP(src="198.1.1.17", dst="198.1.2.18", ttl=63)/ \ + TCP(sport=4196, dport=INT_L4_DPORT)/ \ + INTShimTcpUdp(type=1, npt=1, l4_dport=9028, metadata=int_md)/ \ + Raw('a'*64) + +pkt=Ether(raw(pkt)) +# pkt.show2() + +assert pkt[IP].tos == 0 +assert pkt[IP].proto == socket.IPPROTO_TCP +assert pkt[IP].chksum == 0xec09 +assert pkt[TCP].sport == 4196 +assert pkt[TCP].dport == INT_L4_DPORT +assert pkt[TCP].chksum == 0x6fa8 +check_int_shim(pkt) +check_int_meta(pkt) + + += Build & Dissect, INT MD Over IPv6 UDP, Identifier=L4_DPORT + +pkt=Ether(src="b6:18:00:11:11:00", dst="b6:18:00:22:22:00")/ \ + IPv6(src="2000::1", dst="5000::1", hlim=63)/ \ + UDP(sport=4196, dport=INT_L4_DPORT)/ \ + INTShimTcpUdp(type=1, npt=1, l4_dport=9028, metadata=int_md)/ \ + Raw('a'*64) + +pkt=Ether(raw(pkt)) +# pkt.show2() + +assert pkt[IPv6].tc == 0 +assert pkt[IPv6].nh == socket.IPPROTO_UDP +assert pkt[UDP].sport == 4196 +assert pkt[UDP].dport == INT_L4_DPORT +assert pkt[UDP].chksum == 0xfe27 +check_int_shim(pkt) +check_int_meta(pkt) + + += Build & Dissect, INT MD Over IPv6 TCP, Identifier=L4_DPORT + +pkt=Ether(src="b6:18:00:11:11:00", dst="b6:18:00:22:22:00")/ \ + IPv6(src="2000::1", dst="5000::1", hlim=63)/ \ + TCP(sport=4196, dport=INT_L4_DPORT)/ \ + INTShimTcpUdp(type=1, npt=1, l4_dport=9028, metadata=int_md)/ \ + Raw('a'*64) + +pkt=Ether(raw(pkt)) +# pkt.show2() + +assert pkt[IPv6].tc == 0 +assert pkt[IPv6].nh == socket.IPPROTO_TCP +assert pkt[TCP].sport == 4196 +assert pkt[TCP].dport == INT_L4_DPORT +assert pkt[TCP].chksum == 0x8ecc +check_int_shim(pkt) +check_int_meta(pkt) + + += Build & Dissect, INT MX Over IPv4 UDP, Identifier=L4_DPORT + +pkt=Ether(src="b6:18:00:11:11:00", dst="b6:18:00:22:22:00")/ \ + IP(src="198.1.1.17", dst="198.1.2.18", ttl=63)/ \ + UDP(sport=4196, dport=INT_L4_DPORT)/ \ + INTShimTcpUdp(type=3, npt=1, l4_dport=9028, metadata=int_mx)/ \ + Raw('a'*64) + +pkt=Ether(raw(pkt)) +# pkt.show2() + +assert pkt[IP].tos == 0 +assert pkt[IP].proto == socket.IPPROTO_UDP +assert pkt[IP].chksum == 0xec5a +assert pkt[UDP].sport == 4196 +assert pkt[UDP].dport == INT_L4_DPORT +assert pkt[UDP].chksum == 0xdf3d +check_int_shim(pkt) +check_int_meta(pkt) + + += Build & Dissect, INT MX Over IPv4 TCP, Identifier=L4_DPORT + +pkt=Ether(src="b6:18:00:11:11:00", dst="b6:18:00:22:22:00")/ \ + IP(src="198.1.1.17", dst="198.1.2.18", ttl=63)/ \ + TCP(sport=4196, dport=INT_L4_DPORT)/ \ + INTShimTcpUdp(type=3, npt=1, l4_dport=9028, metadata=int_mx)/ \ + Raw('a'*64) + +pkt=Ether(raw(pkt)) +# pkt.show2() + +assert pkt[IP].tos == 0 +assert pkt[IP].proto == socket.IPPROTO_TCP +assert pkt[IP].chksum == 0xec59 +assert pkt[TCP].sport == 4196 +assert pkt[TCP].dport == INT_L4_DPORT +assert pkt[TCP].chksum == 0x6f92 +check_int_shim(pkt) +check_int_meta(pkt) + + += Build & Dissect, INT MX Over IPv6 UDP, Identifier=L4_DPORT + +pkt=Ether(src="b6:18:00:11:11:00", dst="b6:18:00:22:22:00")/ \ + IPv6(src="2000::1", dst="5000::1", hlim=63)/ \ + UDP(sport=4196, dport=INT_L4_DPORT)/ \ + INTShimTcpUdp(type=3, npt=1, l4_dport=9028, metadata=int_mx)/ \ + Raw('a'*64) + +pkt=Ether(raw(pkt)) +# pkt.show2() + +assert pkt[IPv6].tc == 0 +assert pkt[IPv6].nh == socket.IPPROTO_UDP +assert pkt[UDP].sport == 4196 +assert pkt[UDP].dport == INT_L4_DPORT +assert pkt[UDP].chksum == 0xfe61 +check_int_shim(pkt) +check_int_meta(pkt) + + += Build & Dissect, INT MX Over IPv6 TCP, Identifier=L4_DPORT + +pkt=Ether(src="b6:18:00:11:11:00", dst="b6:18:00:22:22:00")/ \ + IPv6(src="2000::1", dst="5000::1", hlim=63)/ \ + TCP(sport=4196, dport=INT_L4_DPORT)/ \ + INTShimTcpUdp(type=3, npt=1, l4_dport=9028, metadata=int_mx)/ \ + Raw('a'*64) + +pkt=Ether(raw(pkt)) +# pkt.show2() + +assert pkt[IPv6].tc == 0 +assert pkt[IPv6].nh == socket.IPPROTO_TCP +assert pkt[TCP].sport == 4196 +assert pkt[TCP].dport == INT_L4_DPORT +assert pkt[TCP].chksum == 0x8eb6 +check_int_shim(pkt) +check_int_meta(pkt) + + += Build & Dissect, INT MD Over IPv4 GRE + +pkt=Ether(src="b6:18:00:11:11:00", dst="b6:18:00:22:22:00")/ \ + IP(src="198.1.1.17", dst="198.1.2.18", ttl=63)/ \ + GRE(proto=INT_GRE_PROTOCOL)/ \ + INTShimGre(type=1, gre=0, gre_proto=0x6558, metadata=int_md)/ \ + Ether(dst='b6:18:00:88:88:00', src='b6:18:00:99:99:00')/ \ + IP(src='192.168.1.5', dst='192.168.6.9', ttl=128)/ \ + TCP(sport=6677, dport=8899)/ \ + Raw('a'*64) + +pkt=Ether(raw(pkt)) +# pkt.show2() + +assert pkt[IP].tos == 0 +assert pkt[IP].proto == socket.IPPROTO_GRE +assert pkt[IP].chksum == 0xebba +assert pkt[GRE].proto == INT_GRE_PROTOCOL +check_int_shim(pkt) +check_int_meta(pkt) + + += Build & Dissect, INT MD Over IPv6 GRE + +pkt=Ether(src="b6:18:00:11:11:00", dst="b6:18:00:22:22:00")/ \ + IPv6(src="2000::1", dst="5000::1", hlim=63)/ \ + GRE(proto=INT_GRE_PROTOCOL)/ \ + INTShimGre(type=1, gre=0, gre_proto=0x6558, metadata=int_md)/ \ + Ether(dst='b6:18:00:88:88:00', src='b6:18:00:99:99:00')/ \ + IP(src='192.168.1.5', dst='192.168.6.9', ttl=128)/ \ + TCP(sport=6677, dport=8899)/ \ + Raw('a'*64) + +pkt=Ether(raw(pkt)) +# pkt.show2() + +assert pkt[IPv6].tc == 0 +assert pkt[IPv6].nh == socket.IPPROTO_GRE +assert pkt[GRE].proto == INT_GRE_PROTOCOL +check_int_shim(pkt) +check_int_meta(pkt) + + += Build & Dissect, INT MX Over IPv4 GRE + +pkt=Ether(src="b6:18:00:11:11:00", dst="b6:18:00:22:22:00")/ \ + IP(src="198.1.1.17", dst="198.1.2.18", ttl=63)/ \ + GRE(proto=INT_GRE_PROTOCOL)/ \ + INTShimGre(type=3, gre=0, gre_proto=0x6558, metadata=int_mx)/ \ + Ether(dst='b6:18:00:88:88:00', src='b6:18:00:99:99:00')/ \ + IP(src='192.168.1.5', dst='192.168.6.9', ttl=128)/ \ + TCP(sport=6677, dport=8899)/ \ + Raw('a'*64) + +pkt=Ether(raw(pkt)) +# pkt.show2() + +assert pkt[IP].tos == 0 +assert pkt[IP].proto == socket.IPPROTO_GRE +assert pkt[IP].chksum == 0xec0a +assert pkt[GRE].proto == INT_GRE_PROTOCOL +check_int_shim(pkt) +check_int_meta(pkt) + + += Build & Dissect, INT MX Over IPv6 GRE + +pkt=Ether(src="b6:18:00:11:11:00", dst="b6:18:00:22:22:00")/ \ + IPv6(src="2000::1", dst="5000::1", hlim=63)/ \ + GRE(proto=INT_GRE_PROTOCOL)/ \ + INTShimGre(type=3, gre=0, gre_proto=0x6558, metadata=int_mx)/ \ + Ether(dst='b6:18:00:88:88:00', src='b6:18:00:99:99:00')/ \ + IP(src='192.168.1.5', dst='192.168.6.9', ttl=128)/ \ + TCP(sport=6677, dport=8899)/ \ + Raw('a'*64) + +pkt=Ether(raw(pkt)) +# pkt.show2() + +assert pkt[IPv6].tc == 0 +assert pkt[IPv6].nh == socket.IPPROTO_GRE +assert pkt[GRE].proto == INT_GRE_PROTOCOL +check_int_shim(pkt) +check_int_meta(pkt) + + += Build & Dissect, INT MD Over IPv4 VXLAN + +pkt=Ether(src="b6:18:00:11:11:00", dst="b6:18:00:22:22:00")/ \ + IP(src="198.1.1.17", dst="198.1.2.18", ttl=63)/ \ + UDP(sport=4196, dport=4790)/ \ + VXLAN(flags='NextProtocol', NextProtocol=INT_VXLAN_PROTOCOL, vni=5000)/ \ + INTShimVxlan(type=1, gpe=0, vxlan_proto=3, metadata=int_md)/ \ + Ether(dst='b6:18:00:88:88:00', src='b6:18:00:99:99:00')/ \ + IP(src='192.168.1.5', dst='192.168.6.9', ttl=128)/ \ + TCP(sport=6677, dport=8899)/ \ + Raw('a'*64) + +pkt=Ether(raw(pkt)) +# pkt.show2() + +assert pkt[IP].tos == 0 +assert pkt[IP].proto == socket.IPPROTO_UDP +assert pkt[IP].chksum == 0xebcc +assert pkt[UDP].sport == 4196 +assert pkt[UDP].dport == 4790 +assert pkt[UDP].chksum == 0xca77 +assert pkt[VXLAN].NextProtocol == INT_VXLAN_PROTOCOL +assert pkt[VXLAN].vni == 5000 +check_int_shim(pkt) +check_int_meta(pkt) + + += Build & Dissect, INT MD Over IPv6 VXLAN + +pkt=Ether(src="b6:18:00:11:11:00", dst="b6:18:00:22:22:00")/ \ + IPv6(src="2000::1", dst="5000::1", hlim=63)/ \ + UDP(sport=4196, dport=4790)/ \ + VXLAN(flags='NextProtocol', NextProtocol=INT_VXLAN_PROTOCOL, vni=5000)/ \ + INTShimVxlan(type=1, gpe=0, vxlan_proto=3, metadata=int_md)/ \ + Ether(dst='b6:18:00:88:88:00', src='b6:18:00:99:99:00')/ \ + IP(src='192.168.1.5', dst='192.168.6.9', ttl=128)/ \ + TCP(sport=6677, dport=8899)/ \ + Raw('a'*64) + +pkt=Ether(raw(pkt)) +# pkt.show2() + +assert pkt[IPv6].tc == 0 +assert pkt[IPv6].nh == socket.IPPROTO_UDP +assert pkt[UDP].sport == 4196 +assert pkt[UDP].dport == 4790 +assert pkt[UDP].chksum == 0xe99b +assert pkt[VXLAN].NextProtocol == INT_VXLAN_PROTOCOL +assert pkt[VXLAN].vni == 5000 +check_int_shim(pkt) +check_int_meta(pkt) + + += Build & Dissect, INT MX Over IPv4 VXLAN + +pkt=Ether(src="b6:18:00:11:11:00", dst="b6:18:00:22:22:00")/ \ + IP(src="198.1.1.17", dst="198.1.2.18", ttl=63)/ \ + UDP(sport=4196, dport=4790)/ \ + VXLAN(flags='NextProtocol', NextProtocol=INT_VXLAN_PROTOCOL, vni=5000)/ \ + INTShimVxlan(type=3, gpe=0, vxlan_proto=3, metadata=int_mx)/ \ + Ether(dst='b6:18:00:88:88:00', src='b6:18:00:99:99:00')/ \ + IP(src='192.168.1.5', dst='192.168.6.9', ttl=128)/ \ + TCP(sport=6677, dport=8899)/ \ + Raw('a'*64) + +pkt=Ether(raw(pkt)) +# pkt.show2() + +assert pkt[IP].tos == 0 +assert pkt[IP].proto == socket.IPPROTO_UDP +assert pkt[IP].chksum == 0xec1c +assert pkt[UDP].sport == 4196 +assert pkt[UDP].dport == 4790 +assert pkt[UDP].chksum == 0xcab1 +assert pkt[VXLAN].NextProtocol == INT_VXLAN_PROTOCOL +assert pkt[VXLAN].vni == 5000 +check_int_shim(pkt) +check_int_meta(pkt) + + += Build & Dissect, INT MX Over IPv6 VXLAN + +pkt=Ether(src="b6:18:00:11:11:00", dst="b6:18:00:22:22:00")/ \ + IPv6(src="2000::1", dst="5000::1", hlim=63)/ \ + UDP(sport=4196, dport=4790)/ \ + VXLAN(flags='NextProtocol', NextProtocol=INT_VXLAN_PROTOCOL, vni=5000)/ \ + INTShimVxlan(type=3, gpe=0, vxlan_proto=3, metadata=int_mx)/ \ + Ether(dst='b6:18:00:88:88:00', src='b6:18:00:99:99:00')/ \ + IP(src='192.168.1.5', dst='192.168.6.9', ttl=128)/ \ + TCP(sport=6677, dport=8899)/ \ + Raw('a'*64) + +pkt=Ether(raw(pkt)) +# pkt.show2() + +assert pkt[IPv6].tc == 0 +assert pkt[IPv6].nh == socket.IPPROTO_UDP +assert pkt[UDP].sport == 4196 +assert pkt[UDP].dport == 4790 +assert pkt[UDP].chksum == 0xe9d5 +assert pkt[VXLAN].NextProtocol == INT_VXLAN_PROTOCOL +assert pkt[VXLAN].vni == 5000 +check_int_shim(pkt) +check_int_meta(pkt) + + += Build & Dissect, INT MD Over IPv4 GENEVE + +pkt=Ether(src="b6:18:00:11:11:00", dst="b6:18:00:22:22:00")/ \ + IP(src="198.1.1.17", dst="198.1.2.18", ttl=63)/ \ + UDP(sport=4196, dport=6081)/ \ + GENEVE(proto=0x6558, vni=5000, options=GeneveOptINT(classid=INT_GENEVE_CLASSID, type=1, metadata=int_md))/ \ + Ether(dst='b6:18:00:88:88:00', src='b6:18:00:99:99:00')/ \ + IP(src='192.168.1.5', dst='192.168.6.9', ttl=128)/ \ + TCP(sport=6677, dport=8899)/ \ + Raw('a'*64) + +pkt=Ether(raw(pkt)) +# pkt.show2() + +assert pkt[IP].tos == 0 +assert pkt[IP].proto == socket.IPPROTO_UDP +assert pkt[IP].chksum == 0xebcc +assert pkt[UDP].sport == 4196 +assert pkt[UDP].dport == 6081 +assert pkt[UDP].chksum == 0x5a96 +assert pkt[GENEVE].proto == 0x6558 +assert pkt[GENEVE].vni == 5000 +check_int_shim(pkt) +check_int_meta(pkt) + + += Build & Dissect, INT MD Over IPv6 GENEVE + +pkt=Ether(src="b6:18:00:11:11:00", dst="b6:18:00:22:22:00")/ \ + IPv6(src="2000::1", dst="5000::1", hlim=63)/ \ + UDP(sport=4196, dport=6081)/ \ + GENEVE(proto=0x6558, vni=5000, options=GeneveOptINT(classid=INT_GENEVE_CLASSID, type=1, metadata=int_md))/ \ + Ether(dst='b6:18:00:88:88:00', src='b6:18:00:99:99:00')/ \ + IP(src='192.168.1.5', dst='192.168.6.9', ttl=128)/ \ + TCP(sport=6677, dport=8899)/ \ + Raw('a'*64) + +pkt=Ether(raw(pkt)) +# pkt.show2() + +assert pkt[IPv6].tc == 0 +assert pkt[IPv6].nh == socket.IPPROTO_UDP +assert pkt[UDP].sport == 4196 +assert pkt[UDP].dport == 6081 +assert pkt[UDP].chksum == 0x79ba +assert pkt[GENEVE].proto == 0x6558 +assert pkt[GENEVE].vni == 5000 +check_int_shim(pkt) +check_int_meta(pkt) + += Build & Dissect, INT MX Over IPv4 GENEVE + +pkt=Ether(src="b6:18:00:11:11:00", dst="b6:18:00:22:22:00")/ \ + IP(src="198.1.1.17", dst="198.1.2.18", ttl=63)/ \ + UDP(sport=4196, dport=6081)/ \ + GENEVE(proto=0x6558, vni=5000, options=GeneveOptINT(classid=INT_GENEVE_CLASSID, type=3, metadata=int_mx))/ \ + Ether(dst='b6:18:00:88:88:00', src='b6:18:00:99:99:00')/ \ + IP(src='192.168.1.5', dst='192.168.6.9', ttl=128)/ \ + TCP(sport=6677, dport=8899)/ \ + Raw('a'*64) + +pkt=Ether(raw(pkt)) +# pkt.show2() + +assert pkt[IP].tos == 0 +assert pkt[IP].proto == socket.IPPROTO_UDP +assert pkt[IP].chksum == 0xec1c +assert pkt[UDP].sport == 4196 +assert pkt[UDP].dport == 6081 +assert pkt[UDP].chksum == 0x8cd0 +assert pkt[GENEVE].proto == 0x6558 +assert pkt[GENEVE].vni == 5000 +check_int_shim(pkt) +check_int_meta(pkt) + + += Build & Dissect, INT MX Over IPv6 GENEVE + +pkt=Ether(src="b6:18:00:11:11:00", dst="b6:18:00:22:22:00")/ \ + IPv6(src="2000::1", dst="5000::1", hlim=63)/ \ + UDP(sport=4196, dport=6081)/ \ + GENEVE(proto=0x6558, vni=5000, options=GeneveOptINT(classid=INT_GENEVE_CLASSID, type=3, metadata=int_mx))/ \ + Ether(dst='b6:18:00:88:88:00', src='b6:18:00:99:99:00')/ \ + IP(src='192.168.1.5', dst='192.168.6.9', ttl=128)/ \ + TCP(sport=6677, dport=8899)/ \ + Raw('a'*64) + +pkt=Ether(raw(pkt)) +# pkt.show2() + +assert pkt[IPv6].tc == 0 +assert pkt[IPv6].nh == socket.IPPROTO_UDP +assert pkt[UDP].sport == 4196 +assert pkt[UDP].dport == 6081 +assert pkt[UDP].chksum == 0xabf4 +assert pkt[GENEVE].proto == 0x6558 +assert pkt[GENEVE].vni == 5000 +check_int_shim(pkt) +check_int_meta(pkt)