From d7b900f5698289beaa2c6368cc68ddb9ff323db3 Mon Sep 17 00:00:00 2001 From: Gabriel Ganne Date: Tue, 7 Apr 2015 15:00:09 +0200 Subject: [PATCH] VXLAN: add Generic Packet Encapsulation (GPE) support Since part of the previously reserved Bytes are now used to annouce the next header, this also updates the vxlan unit tests. Original commit by: Christophe Fontaine Signed-off-by: Gabriel Ganne --- scapy/layers/vxlan.py | 27 +++++++++++++++++++++------ test/regression.uts | 4 ++-- 2 files changed, 23 insertions(+), 8 deletions(-) diff --git a/scapy/layers/vxlan.py b/scapy/layers/vxlan.py index 6b620d56c..c3027de29 100644 --- a/scapy/layers/vxlan.py +++ b/scapy/layers/vxlan.py @@ -1,24 +1,35 @@ +#! /usr/bin/env python # RFC 7348 - Virtual eXtensible Local Area Network (VXLAN): # A Framework for Overlaying Virtualized Layer 2 Networks over Layer 3 Networks # http://tools.ietf.org/html/rfc7348 +# https://www.ietf.org/id/draft-ietf-nvo3-vxlan-gpe-02.txt # # VXLAN Group Policy Option: # http://tools.ietf.org/html/draft-smith-vxlan-group-policy-00 from scapy.packet import Packet, bind_layers from scapy.layers.l2 import Ether -from scapy.layers.inet import UDP +from scapy.layers.inet import IP, UDP +from scapy.layers.inet6 import IPv6 from scapy.fields import FlagsField, XByteField, ThreeBytesField, \ - ConditionalField, ShortField + ConditionalField, ShortField, ByteEnumField, X3BytesField -_VXLAN_FLAGS = ["R", "R", "R", "I", "R", "R", "R", "G"] _GP_FLAGS = ["R", "R", "R", "A", "R", "R", "D", "R"] + class VXLAN(Packet): name = "VXLAN" fields_desc = [ - FlagsField("flags", 0x8, 8, _VXLAN_FLAGS), + FlagsField("flags", 0x8, 8, + ['OAM', 'R', 'NextProtocol', 'Instance', + 'V1', 'V2', 'R', 'G']), + ByteEnumField('NextProtocol', 0, + {0: 'NotDefined', + 1: 'IPv4', + 2: 'IPv6', + 3: 'Ethernet', + 4: 'NSH'}), ConditionalField( ThreeBytesField("reserved1", 0x000000), lambda pkt: not pkt.flags & 0x80, @@ -31,7 +42,7 @@ class VXLAN(Packet): ShortField("gpid", 0), lambda pkt: pkt.flags & 0x80, ), - ThreeBytesField("vni", 0), + X3BytesField("vni", 0), XByteField("reserved2", 0x00), ] @@ -47,5 +58,9 @@ class VXLAN(Packet): return self.sprintf("VXLAN (vni=%VXLAN.vni%)") bind_layers(UDP, VXLAN, dport=4789) # RFC standard port +bind_layers(UDP, VXLAN, dport=6633) # New IANA assigned port when used with NSH bind_layers(UDP, VXLAN, dport=8472) # Linux implementation port -bind_layers(VXLAN, Ether) +bind_layers(VXLAN, Ether, {'flags': 0x8}, NextProtocol=0) +bind_layers(VXLAN, IP, {'flags': 0xC, 'NextProtocol': 1}, NextProtocol=1) +bind_layers(VXLAN, IPv6, {'flags': 0xC, 'NextProtocol': 2}, NextProtocol=2) +bind_layers(VXLAN, Ether, {'flags': 0xC, 'NextProtocol': 3}, NextProtocol=3) diff --git a/test/regression.uts b/test/regression.uts index b0d5a4385..e5458164e 100644 --- a/test/regression.uts +++ b/test/regression.uts @@ -6123,10 +6123,10 @@ assert(p.data[0].ifname.startswith("lo")) + VXLAN layer = Build a VXLAN packet with VNI of 42 -str(UDP(sport=1024, dport=4789, len=None, chksum=None)/VXLAN(flags=0x08, vni=42)) == "\x04\x00\x12\xb5\x00\x10\x00\x00\x08\x00\x00\x00\x00\x00\x2a\x00" +str(UDP(sport=1024, dport=4789, len=None, chksum=None)/VXLAN(flags=0x08, vni=42)) == '\x04\x00\x12\xb5\x00\x11\x00\x00\x08\x00\x00\x00\x00\x00\x00\x2a\x00' = Verify VXLAN Ethernet Binding -str(VXLAN(vni=23)/Ether(dst="11:11:11:11:11:11", src="11:11:11:11:11:11", type=0x800)) == "\x08\x00\x00\x00\x00\x00\x17\x00\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x08\x00" +str(VXLAN(vni=23)/Ether(dst="11:11:11:11:11:11", src="11:11:11:11:11:11", type=0x800)) == '\x0c\x03\x00\x00\x00\x00\x00\x17\x00\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x08\x00' = Verify UDP dport overloading p = Ether(dst="11:11:11:11:11:11", src="22:22:22:22:22:22")