Home | History | Annotate | Download | only in layers
      1 #! /usr/bin/env python
      2 # RFC 7348 - Virtual eXtensible Local Area Network (VXLAN):
      3 # A Framework for Overlaying Virtualized Layer 2 Networks over Layer 3 Networks
      4 # http://tools.ietf.org/html/rfc7348
      5 # https://www.ietf.org/id/draft-ietf-nvo3-vxlan-gpe-02.txt
      6 #
      7 # VXLAN Group Policy Option:
      8 # http://tools.ietf.org/html/draft-smith-vxlan-group-policy-00
      9 
     10 from scapy.packet import Packet, bind_layers
     11 from scapy.layers.l2 import Ether
     12 from scapy.layers.inet import IP, UDP
     13 from scapy.layers.inet6 import IPv6
     14 from scapy.fields import FlagsField, XByteField, ThreeBytesField, \
     15     ConditionalField, ShortField, ByteEnumField, X3BytesField
     16 
     17 _GP_FLAGS = ["R", "R", "R", "A", "R", "R", "D", "R"]
     18 
     19 
     20 class VXLAN(Packet):
     21     name = "VXLAN"
     22 
     23     fields_desc = [
     24         FlagsField("flags", 0x8, 8,
     25                    ['OAM', 'R', 'NextProtocol', 'Instance',
     26                     'V1', 'V2', 'R', 'G']),
     27         ConditionalField(
     28             ShortField("reserved0", 0),
     29             lambda pkt: pkt.flags.NextProtocol,
     30         ),
     31         ConditionalField(
     32             ByteEnumField('NextProtocol', 0,
     33                           {0: 'NotDefined',
     34                            1: 'IPv4',
     35                            2: 'IPv6',
     36                            3: 'Ethernet',
     37                            4: 'NSH'}),
     38             lambda pkt: pkt.flags.NextProtocol,
     39         ),
     40         ConditionalField(
     41             ThreeBytesField("reserved1", 0),
     42             lambda pkt: (not pkt.flags.G) and (not pkt.flags.NextProtocol),
     43         ),
     44         ConditionalField(
     45             FlagsField("gpflags", 0, 8, _GP_FLAGS),
     46             lambda pkt: pkt.flags.G,
     47         ),
     48         ConditionalField(
     49             ShortField("gpid", 0),
     50             lambda pkt: pkt.flags.G,
     51         ),
     52         X3BytesField("vni", 0),
     53         XByteField("reserved2", 0),
     54     ]
     55 
     56     # Use default linux implementation port
     57     overload_fields = {
     58         UDP: {'dport': 8472},
     59     }
     60 
     61     def mysummary(self):
     62         if self.flags.G:
     63             return self.sprintf("VXLAN (vni=%VXLAN.vni% gpid=%VXLAN.gpid%)")
     64         else:
     65             return self.sprintf("VXLAN (vni=%VXLAN.vni%)")
     66 
     67 bind_layers(UDP, VXLAN, dport=4789)  # RFC standard vxlan port
     68 bind_layers(UDP, VXLAN, dport=4790)  # RFC standard vxlan-gpe port
     69 bind_layers(UDP, VXLAN, dport=6633)  # New IANA assigned port for use with NSH
     70 bind_layers(UDP, VXLAN, dport=8472)  # Linux implementation port
     71 bind_layers(UDP, VXLAN, sport=4789)
     72 bind_layers(UDP, VXLAN, sport=4790)
     73 bind_layers(UDP, VXLAN, sport=6633)
     74 bind_layers(UDP, VXLAN, sport=8472)
     75 # By default, set both ports to the RFC standard
     76 bind_layers(UDP, VXLAN, sport=4789, dport=4789)
     77 
     78 bind_layers(VXLAN, Ether)
     79 bind_layers(VXLAN, IP, NextProtocol=1)
     80 bind_layers(VXLAN, IPv6, NextProtocol=2)
     81 bind_layers(VXLAN, Ether, flags=4, NextProtocol=0)
     82 bind_layers(VXLAN, IP, flags=4, NextProtocol=1)
     83 bind_layers(VXLAN, IPv6, flags=4, NextProtocol=2)
     84 bind_layers(VXLAN, Ether, flags=4, NextProtocol=3)
     85