Ryu packet generation

In order to respond to the ARP requests, we need to do the following:

  • Catch the ARP request based on the right switch, or datapath, and know the IP it is sending an ARP for
  • Build the ARP response packet
  • Send the response back out the port it was originally received from

In initial part of the PacketIn function, most of the code is identical to the switch function, which corresponds to decoding the OpenFlow event as well as the packet itself. For our purposes, we do not need ofproto and parser for OpenFlow events, but for consistency, we are leaving them in:

@set_ev_cls(ofp_event.EventOFPPacketIn, MAIN_DISPATCHER)
def _packet_in_handler(self, ev):
msg = ev.msg
datapath = msg.datapath
ofproto = datapath.ofproto
parser = datapath.ofproto_parser
in_port = msg.match['in_port']


pkt = packet.Packet(msg.data)
eth = pkt.get_protocols(ethernet.ethernet)[0]

The next section catches ARP packets by identifying the right ether_type:

if eth.ethertype == ether_types.ETH_TYPE_ARP:
arp_packet = pkt.get_protocols(arp.arp)[0]
ethernet_src = eth.src

We can then identify the device and the IP it is sending an ARP for and continue on to build the packet. The packet-building process is similar to the tools we have seen before, such as Scapy, in that it took a layered approach where you can build the Ethernet header and then the ARP packet itself. We will construct a packet via ryu.lib.packet.Packet(), add the contents in, and serialize the packet:

if arp_packet.dst_ip == '192.168.2.1' and datapath.id == 2:
print('Received ARP for 192.168.2.1')

e = ethernet.ethernet(dst=eth.src, src=self.s2_gateway_mac, ethertype=ether.ETH_TYPE_ARP)
a = arp.arp(hwtype=1, proto=0x0800, hlen=6, plen=4, opcode=2,
src_mac=self.s2_gateway_mac, src_ip='192.168.2.1',
dst_mac=ethernet_src, dst_ip=arp_packet.src_ip)

p = packet.Packet()
p.add_protocol(e)
p.add_protocol(a)
p.serialize()
...

The last step would be to send the packet out to the port it was received from:

outPort = in_port
actions = [datapath.ofproto_parser.OFPActionOutput(outPort, 0)]
out = datapath.ofproto_parser.OFPPacketOut(
datapath=datapath,
buffer_id=0xffffffff,
in_port=datapath.ofproto.OFPP_CONTROLLER,
actions=actions,
data=p.data)
datapath.send_msg(out)

Notice that for the in_port, we use the special OFPP_CONTROLLER since we don't technically have an inbound port. We will repeat the ARP process for both gateways. The only additional code we have is to verbosely print out the packet we have received and its meta information:

# verbose iteration of packets
try:
for p in pkt.protocols:
print(p.protocol_name, p)
print("datapath: {} in_port: {}".format(datapath.id, in_port))
except:
pass

We are now ready to check on the final result of our code.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.116.62.168