packet lib: serialize in reverse order

- we need to serialize in reverse order since some need to know
  payload.
- TCP and UDP need the previous protocol info (IP) to calculate the
  checksum.

Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
This commit is contained in:
FUJITA Tomonori 2012-08-27 11:37:24 +09:00
parent b3e491349a
commit d0cc259e3b
6 changed files with 29 additions and 26 deletions

View File

@ -15,7 +15,6 @@
import struct
from . import packet_base
from ryu.ofproto.ofproto_parser import msg_pack_into
class arp(packet_base.PacketBase):
@ -42,7 +41,8 @@ class arp(packet_base.PacketBase):
return cls(hwtype, proto, hlen, plen, opcode, src_mac, src_ip,
dst_mac, dst_ip), None
def serialize(self, buf, offset):
msg_pack_into(arp._PACK_STR, buf, offset, self.hwtype, self.proto,
self.hlen, self.plen, self.opcode,
self.src_mac, self.src_ip, self.dst_mac, self.dst_ip)
def serialize(self, payload, prev):
return struct.pack(arp._PACK_STR, self.hwtype, self.proto,
self.hlen, self.plen, self.opcode,
self.src_mac, self.src_ip, self.dst_mac,
self.dst_ip)

View File

@ -17,7 +17,6 @@ import struct
from . import packet_base
from . import vlan
from ryu.ofproto import ether
from ryu.ofproto.ofproto_parser import msg_pack_into
class ethernet(packet_base.PacketBase):
@ -35,9 +34,9 @@ class ethernet(packet_base.PacketBase):
dst, src, ethertype = struct.unpack_from(cls._PACK_STR, buf)
return cls(dst, src, ethertype), ethernet.get_packet_type(ethertype)
def serialize(self, buf, offset):
msg_pack_into(ethernet._PACK_STR, buf, offset,
self.dst, self.src, self.ethertype)
def serialize(self, payload, prev):
return struct.pack(ethernet._PACK_STR, self.dst, self.src,
self.ethertype)
# copy vlan _TYPES

View File

@ -16,7 +16,6 @@
import struct
from . import packet_base
from . import udp
from ryu.ofproto.ofproto_parser import msg_pack_into
from ryu.ofproto import inet
@ -69,13 +68,15 @@ class ipv4(packet_base.PacketBase):
s = self.carry_around_add(s, w)
return ~s & 0xffff
def serialize(self, buf, offset):
def serialize(self, payload, prev):
hdr = bytearray().zfill(self.header_length * 4)
version = self.version << 4 | self.header_length
flags = self.flags << 15 | self.offset
msg_pack_into(ipv4._PACK_STR, buf, offset, version, self.tos,
self.total_length, self.identification, flags,
self.ttl, self.proto, 0, self.src, self.dst)
self.csum = self.checksum(buf[offset:offset + self.length])
msg_pack_into('H', buf, offset + 10, self.csum)
struct.pack_into(ipv4._PACK_STR, hdr, 0, version, self.tos,
self.total_length, self.identification, flags,
self.ttl, self.proto, 0, self.src, self.dst)
self.csum = self.checksum(hdr)
struct.pack_into('H', hdr, 10, self.csum)
return hdr
ipv4.register_packet_type(udp.udp, inet.IPPROTO_UDP)

View File

@ -34,11 +34,15 @@ class Packet(object):
self.protocols.append(proto)
def serialize(self):
offset = 0
self.data = bytearray()
for p in self.protocols:
p.serialize(self.data, offset)
offset += p.length
r = self.protocols[::-1]
for i, p in enumerate(r):
if i == len(r) - 1:
prev = None
else:
prev = r[i + 1]
data = p.serialize(self.data, prev)
self.data = data + self.data
def add_protocol(self, proto):
self.protocols.append(proto)

View File

@ -15,7 +15,6 @@
import struct
from . import packet_base
from ryu.ofproto.ofproto_parser import msg_pack_into
class udp(packet_base.PacketBase):
@ -39,6 +38,6 @@ class udp(packet_base.PacketBase):
return msg, None
def serialize(self, buf, offset):
msg_pack_into(udp._PACK_STR, buf, offset, self.src_port, self.dst_port,
self.length, self.csum)
def serialize(self, payload, prev):
return struct.pack(udp._PACK_STR, self.src_port, self.dst_port,
self.length, self.csum)

View File

@ -40,9 +40,9 @@ class vlan(packet_base.PacketBase):
vid = tci & ((1 << 12) - 1)
return cls(pcp, cfi, vid, ethertype), vlan.get_packet_type(ethertype)
def serialize(self, buf, offset):
def serialize(self, payload, prev):
tci = self.pcp << 15 | self.cfi << 12 | self.vid
msg_pack_into(vlan._PACK_STR, buf, offset, tci, self.ethertype)
return struct.pack(vlan._PACK_STR, tci, self.ethertype)
vlan.register_packet_type(arp.arp, ether.ETH_TYPE_ARP)
vlan.register_packet_type(ipv4.ipv4, ether.ETH_TYPE_IP)