| 1 |
1 |
import logging |
| 2 |
| |
| 3 |
1 |
from operator import attrgetter |
| 4 |
1 |
from ryu.base import app_manager |
| 5 |
1 |
from ryu.controller import ofp_event |
| 6 |
1 |
from ryu.controller.handler import CONFIG_DISPATCHER |
| 7 |
1 |
from ryu.controller.handler import MAIN_DISPATCHER |
| 8 |
1 |
from ryu.controller.handler import set_ev_cls |
| 9 |
1 |
from ryu.lib.packet import packet |
| 10 |
1 |
from ryu.lib.packet import ethernet |
| 11 |
1 |
from ryu.lib.packet import arp |
| 12 |
1 |
from ryu.lib.packet import ipv4 |
| 13 |
1 |
from ryu.lib.packet.packet import Packet |
| 14 |
1 |
from ryu.lib.packet.ethernet import ethernet |
| 15 |
1 |
from ryu.lib.packet.arp import arp |
| 16 |
1 |
from ryu.lib.packet.ipv4 import ipv4 |
| 17 |
1 |
from ryu.ofproto import ofproto_v1_3 |
| 18 |
1 |
from ryu.ofproto import ether |
| 19 |
1 |
from ryu.ofproto import inet |
| 20 |
| |
| 21 |
1 |
LOG = logging.getLogger('SimpleForward') |
| 22 |
1 |
LOG.setLevel(logging.DEBUG) |
| 23 |
1 |
logging.basicConfig() |
| 24 |
| |
| 25 |
1 |
HOST_IPADDR1 = "192.168.0.1" |
| 26 |
1 |
HOST_IPADDR2 = "192.168.1.1" |
| 27 |
1 |
ROUTER_IPADDR1 = "192.168.0.10" |
| 28 |
1 |
ROUTER_IPADDR2 = "192.168.1.10" |
| 29 |
1 |
ROUTER_MACADDR1 = "00:00:00:00:00:01" |
| 30 |
1 |
ROUTER_MACADDR2 = "00:00:00:00:00:02" |
| 31 |
1 |
ROUTER_PORT1 = 1 |
| 32 |
1 |
ROUTER_PORT2 = 2 |
| 33 |
| |
| 34 |
| |
| 35 |
1 |
class SimpleForward(app_manager.RyuApp): |
| 36 |
1 |
OFP_VERSIONS = [ofproto_v1_3.OFP_VERSION] |
| 37 |
| |
| 38 |
1 |
HOST_MACADDR1 = None |
| 39 |
1 |
HOST_MACADDR2 = None |
| 40 |
| |
| 41 |
1 |
def __init__(self, *args, **kwargs): |
| 42 |
1 |
super(SimpleForward, self).__init__(*args, **kwargs) |
| 43 |
| |
| 44 |
| |
| 45 |
1 |
@set_ev_cls(ofp_event.EventOFPSwitchFeatures, CONFIG_DISPATCHER) |
| 46 |
| def switch_features_handler(self, ev): |
| 47 |
0 |
msg = ev.msg |
| 48 |
0 |
datapath = msg.datapath |
| 49 |
0 |
ofproto = datapath.ofproto |
| 50 |
0 |
datapath.id = msg.datapath_id |
| 51 |
0 |
ofproto_parser = datapath.ofproto_parser |
| 52 |
| |
| 53 |
0 |
set_config = ofproto_parser.OFPSetConfig( |
| 54 |
| datapath, |
| 55 |
| datapath.ofproto.OFPC_FRAG_NORMAL, |
| 56 |
| datapath.ofproto.OFPCML_MAX |
| 57 |
| ) |
| 58 |
0 |
datapath.send_msg(set_config) |
| 59 |
0 |
self.install_table_miss(datapath, datapath.id) |
| 60 |
| |
| 61 |
| |
| 62 |
1 |
def install_table_miss(self, datapath, dpid): |
| 63 |
0 |
datapath.id = dpid |
| 64 |
| |
| 65 |
0 |
match = datapath.ofproto_parser.OFPMatch() |
| 66 |
| |
| 67 |
0 |
actions = [datapath.ofproto_parser.OFPActionOutput( |
| 68 |
| datapath.ofproto.OFPP_CONTROLLER, |
| 69 |
| datapath.ofproto.OFPCML_NO_BUFFER)] |
| 70 |
0 |
inst = [datapath.ofproto_parser.OFPInstructionActions( |
| 71 |
| datapath.ofproto.OFPIT_APPLY_ACTIONS, actions)] |
| 72 |
0 |
mod = datapath.ofproto_parser.OFPFlowMod( |
| 73 |
| datapath=datapath, |
| 74 |
| priority=0, |
| 75 |
| buffer_id=0xffffffff, |
| 76 |
| match=match, |
| 77 |
| instructions=inst) |
| 78 |
0 |
datapath.send_msg(mod) |
| 79 |
| |
| 80 |
| |
| 81 |
1 |
@set_ev_cls(ofp_event.EventOFPPacketIn, MAIN_DISPATCHER) |
| 82 |
| def packet_in_handler(self, ev): |
| 83 |
1 |
msg = ev.msg |
| 84 |
1 |
datapath = msg.datapath |
| 85 |
1 |
ofproto = datapath.ofproto |
| 86 |
1 |
inPort = msg.match['in_port'] |
| 87 |
| |
| 88 |
1 |
packet = Packet(msg.data) |
| 89 |
1 |
etherFrame = packet.get_protocol(ethernet) |
| 90 |
1 |
if etherFrame.ethertype == ether.ETH_TYPE_ARP: |
| 91 |
1 |
self.receive_arp(datapath, packet, etherFrame, inPort) |
| 92 |
1 |
return 0 |
| 93 |
1 |
elif etherFrame.ethertype == ether.ETH_TYPE_IP: |
| 94 |
1 |
self.receive_ip(datapath, packet, etherFrame, inPort) |
| 95 |
1 |
return 1 |
| 96 |
| else: |
| 97 |
0 |
LOG.debug("receive Unknown packet %s => %s (port%d)" |
| 98 |
| %(etherFrame.src, etherFrame.dst, inPort)) |
| 99 |
0 |
self.print_etherFrame(etherFrame) |
| 100 |
0 |
LOG.debug("Drop packet") |
| 101 |
0 |
return 2 |
| 102 |
| |
| 103 |
| |
| 104 |
1 |
def receive_ip(self, datapath, packet, etherFrame, inPort): |
| 105 |
1 |
ipPacket = packet.get_protocol(ipv4) |
| 106 |
1 |
LOG.debug("receive IP packet %s => %s (port%d)" |
| 107 |
| %(etherFrame.src, etherFrame.dst, inPort)) |
| 108 |
1 |
self.print_etherFrame(etherFrame) |
| 109 |
1 |
self.print_ipPacket(ipPacket) |
| 110 |
1 |
LOG.debug("Drop packet") |
| 111 |
| |
| 112 |
1 |
if inPort == ROUTER_PORT1 and ipPacket.src == HOST_IPADDR1: |
| 113 |
1 |
self.HOST_MACADDR1 = etherFrame.src |
| 114 |
1 |
elif inPort == ROUTER_PORT2 and ipPacket.src == HOST_IPADDR2: |
| 115 |
1 |
self.HOST_MACADDR2 = etherFrame.src |
| 116 |
| |
| 117 |
1 |
if self.HOST_MACADDR1 != None and self.HOST_MACADDR2 != None: |
| 118 |
1 |
if ipPacket.dst == HOST_IPADDR1 or ipPacket.dst == HOST_IPADDR2: |
| 119 |
0 |
self.send_flow(datapath) |
| 120 |
| else: |
| 121 |
1 |
LOG.debug("unknown ip received !") |
| 122 |
1 |
elif self.HOST_MACADDR1 == None or self.HOST_MACADDR2 == None: |
| 123 |
1 |
dstMac = "ff:ff:ff:ff:ff:ff" |
| 124 |
1 |
if ipPacket.dst == HOST_IPADDR2: |
| 125 |
1 |
self.send_arp(datapath, 1, ROUTER_MACADDR2, ROUTER_IPADDR2, |
| 126 |
| "ff:ff:ff:ff:ff:ff", HOST_IPADDR2, ROUTER_PORT2) |
| 127 |
1 |
LOG.debug("send ARP request %s => %s (port%d)" |
| 128 |
| %(ROUTER_MACADDR2, "ff:ff:ff:ff:ff:ff", ROUTER_PORT2)) |
| 129 |
0 |
elif ipPacket.dst == HOST_IPADDR1: |
| 130 |
0 |
self.send_arp(datapath, 1, ROUTER_MACADDR1, ROUTER_IPADDR1, |
| 131 |
| "ff:ff:ff:ff:ff:ff", HOST_IPADDR1, ROUTER_PORT1) |
| 132 |
0 |
LOG.debug("send ARP request %s => %s (port%d)" |
| 133 |
| %(ROUTER_MACADDR1, "ff:ff:ff:ff:ff:ff", ROUTER_PORT1)) |
| 134 |
| else: |
| 135 |
0 |
LOG.debug("unknown ip received !") |
| 136 |
| |
| 137 |
| |
| 138 |
1 |
def receive_arp(self, datapath, packet, etherFrame, inPort): |
| 139 |
1 |
arpPacket = packet.get_protocol(arp) |
| 140 |
1 |
if arpPacket.opcode == 1: |
| 141 |
1 |
operation = "ARP Request" |
| 142 |
1 |
arp_dstIp = arpPacket.dst_ip |
| 143 |
1 |
elif arpPacket.opcode == 2: |
| 144 |
1 |
operation = "ARP Reply" |
| 145 |
| |
| 146 |
1 |
LOG.debug("receive %s %s => %s (port%d)" |
| 147 |
| %(operation, etherFrame.src, etherFrame.dst, inPort)) |
| 148 |
1 |
self.print_etherFrame(etherFrame) |
| 149 |
1 |
self.print_arpPacket(arpPacket) |
| 150 |
| |
| 151 |
1 |
if arpPacket.opcode == 1: |
| 152 |
1 |
self.reply_arp(datapath, etherFrame, arpPacket, arp_dstIp, inPort) |
| 153 |
1 |
elif arpPacket.opcode == 2: |
| 154 |
1 |
if inPort == ROUTER_PORT1 and arpPacket.src_ip == HOST_IPADDR1: |
| 155 |
0 |
self.HOST_MACADDR1 = etherFrame.src |
| 156 |
1 |
elif inPort == ROUTER_PORT2 and arpPacket.src_ip == HOST_IPADDR2: |
| 157 |
1 |
self.HOST_MACADDR2 = etherFrame.src |
| 158 |
1 |
if self.HOST_MACADDR1 != None and self.HOST_MACADDR2 != None: |
| 159 |
1 |
self.send_flow(datapath) |
| 160 |
| |
| 161 |
| |
| 162 |
1 |
def reply_arp(self, datapath, etherFrame, arpPacket, arp_dstIp, inPort): |
| 163 |
1 |
dstIp = arpPacket.src_ip |
| 164 |
1 |
srcIp = arpPacket.dst_ip |
| 165 |
1 |
dstMac = etherFrame.src |
| 166 |
1 |
if arp_dstIp == ROUTER_IPADDR1: |
| 167 |
1 |
srcMac = ROUTER_MACADDR1 |
| 168 |
1 |
outPort = ROUTER_PORT1 |
| 169 |
0 |
elif arp_dstIp == ROUTER_IPADDR2: |
| 170 |
0 |
srcMac = ROUTER_MACADDR2 |
| 171 |
0 |
outPort = ROUTER_PORT2 |
| 172 |
| else: |
| 173 |
0 |
LOG.debug("unknown arp requst received !") |
| 174 |
| |
| 175 |
1 |
self.send_arp(datapath, 2, srcMac, srcIp, dstMac, dstIp, outPort) |
| 176 |
1 |
LOG.debug("send ARP reply %s => %s (port%d)" %(srcMac, dstMac, outPort)) |
| 177 |
| |
| 178 |
| |
| 179 |
1 |
def send_arp(self, datapath, opcode, srcMac, srcIp, dstMac, dstIp, outPort): |
| 180 |
1 |
if opcode == 1: |
| 181 |
1 |
targetMac = "00:00:00:00:00:00" |
| 182 |
1 |
targetIp = dstIp |
| 183 |
1 |
elif opcode == 2: |
| 184 |
1 |
targetMac = dstMac |
| 185 |
1 |
targetIp = dstIp |
| 186 |
| |
| 187 |
1 |
e = ethernet(dstMac, srcMac, ether.ETH_TYPE_ARP) |
| 188 |
1 |
a = arp(1, 0x0800, 6, 4, opcode, srcMac, srcIp, targetMac, targetIp) |
| 189 |
1 |
p = Packet() |
| 190 |
1 |
p.add_protocol(e) |
| 191 |
1 |
p.add_protocol(a) |
| 192 |
1 |
p.serialize() |
| 193 |
| |
| 194 |
1 |
actions = [datapath.ofproto_parser.OFPActionOutput(outPort, 0)] |
| 195 |
1 |
out = datapath.ofproto_parser.OFPPacketOut( |
| 196 |
| datapath=datapath, |
| 197 |
| buffer_id=0xffffffff, |
| 198 |
| in_port=datapath.ofproto.OFPP_CONTROLLER, |
| 199 |
| actions=actions, |
| 200 |
| data=p.data) |
| 201 |
1 |
datapath.send_msg(out) |
| 202 |
| |
| 203 |
| |
| 204 |
1 |
def send_flow(self, datapath): |
| 205 |
1 |
LOG.debug("Send Flow_mod packet for %s", HOST_IPADDR2) |
| 206 |
1 |
self.add_flow(datapath, ROUTER_PORT1, self.HOST_MACADDR1, |
| 207 |
| ROUTER_MACADDR1, ether.ETH_TYPE_IP, |
| 208 |
| HOST_IPADDR2, ROUTER_MACADDR2, |
| 209 |
| self.HOST_MACADDR2, ROUTER_PORT2) |
| 210 |
1 |
LOG.debug("Send Flow_mod packet for %s", HOST_IPADDR1) |
| 211 |
1 |
self.add_flow(datapath, ROUTER_PORT2, self.HOST_MACADDR2, |
| 212 |
| ROUTER_MACADDR2, ether.ETH_TYPE_IP, |
| 213 |
| HOST_IPADDR1, ROUTER_MACADDR1, |
| 214 |
| self.HOST_MACADDR1, ROUTER_PORT1) |
| 215 |
| |
| 216 |
| |
| 217 |
1 |
def add_flow(self, datapath, inPort, org_srcMac, org_dstMac, ethertype, |
| 218 |
| targetIp, mod_srcMac, mod_dstMac, outPort): |
| 219 |
| |
| 220 |
1 |
match = datapath.ofproto_parser.OFPMatch( |
| 221 |
| in_port=inPort, |
| 222 |
| eth_src=org_srcMac, |
| 223 |
| eth_dst=org_dstMac, |
| 224 |
| eth_type=ethertype, |
| 225 |
| ipv4_dst=targetIp ) |
| 226 |
1 |
actions =[datapath.ofproto_parser.OFPActionSetField(eth_src=mod_srcMac), |
| 227 |
| datapath.ofproto_parser.OFPActionSetField(eth_dst=mod_dstMac), |
| 228 |
| datapath.ofproto_parser.OFPActionOutput(outPort, 0)] |
| 229 |
1 |
inst = [datapath.ofproto_parser.OFPInstructionActions( |
| 230 |
| datapath.ofproto.OFPIT_APPLY_ACTIONS, actions)] |
| 231 |
1 |
mod = datapath.ofproto_parser.OFPFlowMod( |
| 232 |
| cookie=0, |
| 233 |
| cookie_mask=0, |
| 234 |
| flags=datapath.ofproto.OFPFF_CHECK_OVERLAP, |
| 235 |
| table_id=0, |
| 236 |
| command=datapath.ofproto.OFPFC_ADD, |
| 237 |
| datapath=datapath, |
| 238 |
| idle_timeout=0, |
| 239 |
| hard_timeout=0, |
| 240 |
| priority=0xff, |
| 241 |
| buffer_id=0xffffffff, |
| 242 |
| out_port=datapath.ofproto.OFPP_ANY, |
| 243 |
| out_group=datapath.ofproto.OFPG_ANY, |
| 244 |
| match=match, |
| 245 |
| instructions=inst) |
| 246 |
1 |
datapath.send_msg(mod) |
| 247 |
| |
| 248 |
| |
| 249 |
1 |
def print_etherFrame(self, etherFrame): |
| 250 |
1 |
LOG.debug("---------------------------------------") |
| 251 |
1 |
LOG.debug("eth_dst_address :%s", etherFrame.dst) |
| 252 |
1 |
LOG.debug("eth_src_address :%s", etherFrame.src) |
| 253 |
1 |
LOG.debug("eth_ethertype :0x%04x", etherFrame.ethertype) |
| 254 |
1 |
LOG.debug("---------------------------------------") |
| 255 |
| |
| 256 |
| |
| 257 |
1 |
def print_arpPacket(self, arpPacket): |
| 258 |
1 |
LOG.debug("arp_hwtype :%d", arpPacket.hwtype) |
| 259 |
1 |
LOG.debug("arp_proto :0x%04x", arpPacket.proto) |
| 260 |
1 |
LOG.debug("arp_hlen :%d", arpPacket.hlen) |
| 261 |
1 |
LOG.debug("arp_plen :%d", arpPacket.plen) |
| 262 |
1 |
LOG.debug("arp_opcode :%d", arpPacket.opcode) |
| 263 |
1 |
LOG.debug("arp_src_mac :%s", arpPacket.src_mac) |
| 264 |
1 |
LOG.debug("arp_src_ip :%s", arpPacket.src_ip) |
| 265 |
1 |
LOG.debug("arp_dst_mac :%s", arpPacket.dst_mac) |
| 266 |
1 |
LOG.debug("arp_dst_ip :%s", arpPacket.dst_ip) |
| 267 |
1 |
LOG.debug("---------------------------------------") |
| 268 |
| |
| 269 |
| |
| 270 |
1 |
def print_ipPacket(self, ipPacket): |
| 271 |
1 |
LOG.debug("ip_version :%d", ipPacket.version) |
| 272 |
1 |
LOG.debug("ip_header_length :%d", ipPacket.header_length) |
| 273 |
1 |
LOG.debug("ip_tos :%d", ipPacket.tos) |
| 274 |
1 |
LOG.debug("ip_total_length :%d", ipPacket.total_length) |
| 275 |
1 |
LOG.debug("ip_identification:%d", ipPacket.identification) |
| 276 |
1 |
LOG.debug("ip_flags :%d", ipPacket.flags) |
| 277 |
1 |
LOG.debug("ip_offset :%d", ipPacket.offset) |
| 278 |
1 |
LOG.debug("ip_ttl :%d", ipPacket.ttl) |
| 279 |
1 |
LOG.debug("ip_proto :%d", ipPacket.proto) |
| 280 |
1 |
LOG.debug("ip_csum :%d", ipPacket.csum) |
| 281 |
1 |
LOG.debug("ip_src :%s", ipPacket.src) |
| 282 |
1 |
LOG.debug("ip_dst :%s", ipPacket.dst) |
| 283 |
1 |
LOG.debug("---------------------------------------") |
| 284 |
| |
| 285 |
| |