class VXLAN(Packet):
    name = 'VXLAN'
    fields_desc = [
        FlagsField('flags', default=1 << 3, size=8,
            names=['R', 'R', 'R', 'R', 'I', 'R', 'R', 'R']),
        XBitField('reserved1', default=0x000000, size=24),
        BitField('vni', None, size=24),
        XBitField('reserved2', default=0x00, size=8),
    ]
    overload_fields = { UDP: {"sport": 4789, "dport": 4789} }
    def mysummary(self):
        return self.sprintf("VXLAN (vni=%VXLAN.vni%)")

bind_layers(UDP, VXLAN, dport=4789)
bind_layers(VXLAN, Ether)

macdst = "00:1B:21:8E:B2:30" # test with ixgbe
#macdst = "68:05:CA:26:9B:10" # test with fortvile

iface = "ixgbe6"
count = 1
macsrc = get_if_hwaddr(iface)

def send_test_packets(hdr, iface, count):
    p = hdr.copy()
    p /= IP(src=RandIP(), dst=RandIP())
    p /= TCP(flags=0x10)/Raw(RandString(1400))
    # valid packet
    q = p.copy()
    sendp(q, iface=iface, count=count)
    # bad outer IP checksum
    q = p.copy()
    q[IP].chksum=0x1234
    sendp(q, iface=iface, count=count)
    if q.haslayer(UDP):
        # bad outer UDP checksum
        q = p.copy()
        q[UDP].chksum=0x1234
        sendp(q, iface=iface, count=count)
        # disable outer UDP checksum
        q = p.copy()
        q[UDP].chksum=0
        sendp(q, iface=iface, count=count)
    if q[IP].payload.haslayer(IP):
        # bad inner IP checksum
        q = p.copy()
        q[IP].payload[IP].chksum=0x1234
        sendp(q, iface=iface, count=count)
        # bad inner TCP checksum
        q = p.copy()
        q[IP].payload[TCP].chksum=0x1234
        sendp(q, iface=iface, count=count)

def do_test():
    # Ether packet
    p = Ether(dst=macdst, src=macsrc)
    send_test_packets(p, iface, count)
    # VxLAN packet
    p = Ether(dst=macdst, src=macsrc)/IP(src=RandIP(), dst=RandIP())
    p /= UDP(sport=4789, dport=4789)
    p /= VXLAN(vni=1234)/Ether(dst=macdst, src=macsrc)
    send_test_packets(p, iface, count)
    # Ethernet over GRE
    p = Ether(dst=macdst, src=macsrc)/IP(src=RandIP(), dst=RandIP())
    p /= GRE(proto=0x6558)/Ether(dst=macdst, src=macsrc)
    send_test_packets(p, iface, count)
    # IP over GRE
    p = Ether(dst=macdst, src=macsrc)/IP(src=RandIP(), dst=RandIP())
    p /= GRE()
    send_test_packets(p, iface, count)
    # IP over IP
    p = Ether(dst=macdst, src=macsrc)/IP(src=RandIP(), dst=RandIP())
    send_test_packets(p, iface, count)

do_test()
