summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--ryu/lib/packet/gre.py128
1 files changed, 108 insertions, 20 deletions
diff --git a/ryu/lib/packet/gre.py b/ryu/lib/packet/gre.py
index c22032e9..a62f0d18 100644
--- a/ryu/lib/packet/gre.py
+++ b/ryu/lib/packet/gre.py
@@ -15,10 +15,10 @@
import struct
+from ryu.lib.pack_utils import msg_pack_into
from . import packet_base
from . import packet_utils
-from . import ether_types as ether
-from ryu.lib.pack_utils import msg_pack_into
+from . import ether_types
GRE_CHECKSUM_FLG = 1 << 7
@@ -36,6 +36,7 @@ class gre(packet_base.PacketBase):
============== ========================================================
Attribute Description
============== ========================================================
+ version Version.
protocol Protocol Type field.
The Protocol Type is defined as "ETHER TYPES".
checksum Checksum field(optional).
@@ -44,6 +45,12 @@ class gre(packet_base.PacketBase):
key Key field(optional)
This field is intended to be used for identifying
an individual traffic flow within a tunnel.
+ vsid Virtual Subnet ID field(optional)
+ This field is a 24-bit value that is used
+ to identify the NVGRE-based Virtual Layer 2 Network.
+ flow_id FlowID field(optional)
+ This field is an 8-bit value that is used to provide
+ per-flow entropy for flows in the same VSID.
seq_number Sequence Number field(optional)
============== ========================================================
"""
@@ -54,16 +61,76 @@ class gre(packet_base.PacketBase):
_MIN_LEN = struct.calcsize(_PACK_STR)
_CHECKSUM_LEN = struct.calcsize(_CHECKSUM_PACK_STR)
_KEY_LEN = struct.calcsize(_KEY_PACK_STR)
-
- def __init__(self, protocol=ether.ETH_TYPE_IP,
- checksum=None, key=None, seq_number=None):
+ _SEQNUM_PACK_LEN = struct.calcsize(_SEQNUM_PACK_STR)
+
+ # GRE header
+ # 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
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ # |C| |K|S| Reserved0 | Ver | Protocol Type |
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ # | Checksum (optional) | Reserved1 (Optional) |
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ # | Key (optional) |
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ # | Sequence Number (Optional) |
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+ def __init__(self, version=0, protocol=ether_types.ETH_TYPE_IP,
+ checksum=None, key=None, vsid=None, flow_id=None,
+ seq_number=None):
super(gre, self).__init__()
+ self.version = version
self.protocol = protocol
self.checksum = checksum
- self.key = key
self.seq_number = seq_number
+ if key is not None:
+ self._key = key
+ self._vsid = self._key >> 8
+ self._flow_id = self._key & 0xff
+ elif (vsid is not None) and (flow_id is not None):
+ self._key = vsid << 8 | flow_id
+ self._vsid = vsid
+ self._flow_id = flow_id
+ else:
+ self._key = None
+ self._vsid = None
+ self._flow_id = None
+
+ @property
+ def key(self):
+ return self._key
+
+ @key.setter
+ def key(self, key):
+ if key is not None:
+ self._key = key
+ self._vsid = self._key >> 8
+ self._flow_id = self._key & 0xff
+ else:
+ self._key = None
+ self._vsid = None
+ self._flow_id = None
+
+ @property
+ def vsid(self):
+ return self._vsid
+
+ @vsid.setter
+ def vsid(self, vsid):
+ self._key = vsid << 8 | (self._key & 0xff)
+ self._vsid = vsid
+
+ @property
+ def flow_id(self):
+ return self._flow_id
+
+ @flow_id.setter
+ def flow_id(self, flow_id):
+ self._key = (self._key & 0xffffff00) | flow_id
+ self._flow_id = flow_id
+
@classmethod
def parser(cls, buf):
present, version, protocol = struct.unpack_from(cls._PACK_STR, buf)
@@ -82,25 +149,25 @@ class gre(packet_base.PacketBase):
if present & GRE_SEQUENCE_NUM_FLG:
seq_number, = struct.unpack_from(cls._SEQNUM_PACK_STR,
buf, gre_offset)
+ gre_offset += cls._SEQNUM_PACK_LEN
- msg = cls(protocol, checksum, key, seq_number)
+ msg = cls(version=version, protocol=protocol, checksum=checksum,
+ key=key, seq_number=seq_number)
from . import ethernet
- # Because the protocol type field could either Ethertype is set,
- # Set the _TYPES of ethernet, which owns the Ethernet types
- # available in Ryu.
gre._TYPES = ethernet.ethernet._TYPES
+ gre.register_packet_type(ethernet.ethernet,
+ ether_types.ETH_TYPE_TEB)
return msg, gre.get_packet_type(protocol), buf[gre_offset:]
def serialize(self, payload=None, prev=None):
present = 0
- version = 0
hdr = bytearray()
optional = bytearray()
- if self.checksum:
- present += GRE_CHECKSUM_FLG
+ if self.checksum is not None:
+ present |= GRE_CHECKSUM_FLG
# For purposes of computing the checksum,
# the value of the checksum field is zero.
@@ -108,16 +175,16 @@ class gre(packet_base.PacketBase):
# Set in conjunction with checksum.
optional += b'\x00' * self._CHECKSUM_LEN
- if self.key:
- present += GRE_KEY_FLG
- optional += struct.pack(self._KEY_PACK_STR, self.key)
+ if self._key is not None:
+ present |= GRE_KEY_FLG
+ optional += struct.pack(self._KEY_PACK_STR, self._key)
- if self.seq_number:
- present += GRE_SEQUENCE_NUM_FLG
+ if self.seq_number is not None:
+ present |= GRE_SEQUENCE_NUM_FLG
optional += struct.pack(self._SEQNUM_PACK_STR, self.seq_number)
- msg_pack_into(self._PACK_STR, hdr, 0,
- present, version, self.protocol)
+ msg_pack_into(self._PACK_STR, hdr, 0, present, self.version,
+ self.protocol)
hdr += optional
@@ -127,3 +194,24 @@ class gre(packet_base.PacketBase):
self.checksum)
return hdr
+
+
+def nvgre(version=0, vsid=0, flow_id=0):
+ """
+ Generate instance of GRE class with information for NVGRE (RFC7637).
+
+ :param version: Version.
+ :param vsid: Virtual Subnet ID.
+ :param flow_id: FlowID.
+ :return: Instance of GRE class with information for NVGRE.
+ """
+
+ # NVGRE header
+ # 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| |1|0| Reserved0 | Ver | Protocol Type 0x6558 |
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ # | Virtual Subnet ID (VSID) | FlowID |
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ return gre(version=version, protocol=ether_types.ETH_TYPE_TEB,
+ vsid=vsid, flow_id=flow_id)