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 |
| |