Download as pdf or txt
Download as pdf or txt
You are on page 1of 6

5/19/2017 RouteFlow/l3_learning.

pyatmasterCPqD/RouteFlowGitHub

Features Business Explore Pricing This repository Search Sign in or Sign up

CPqD / RouteFlow Watch 43 Star 98 Fork 116

Code Issues 5 Pull requests 1 Projects 0 Wiki Pulse Graphs

Branch: master RouteFlow / pox / pox / forwarding / l3_learning.py Find file Copy path

alnvdl Removed DatapathConfig. 4e86e03 on May 3, 2013

1 contributor

343lines(284sloc) 12.3KB Raw Blame History

1 #Copyright2011,2012JamesMcCauley
2 #
3 #ThisfileispartofPOX.
4 #
5 #POXisfreesoftware:youcanredistributeitand/ormodify
6 #itunderthetermsoftheGNUGeneralPublicLicenseaspublishedby
7 #theFreeSoftwareFoundation,eitherversion3oftheLicense,or
8 #(atyouroption)anylaterversion.
9 #
10 #POXisdistributedinthehopethatitwillbeuseful,
11 #butWITHOUTANYWARRANTY;withouteventheimpliedwarrantyof
12 #MERCHANTABILITYorFITNESSFORAPARTICULARPURPOSE.Seethe
13 #GNUGeneralPublicLicenseformoredetails.
14 #
15 #YoushouldhavereceivedacopyoftheGNUGeneralPublicLicense
16 #alongwithPOX.Ifnot,see<http://www.gnu.org/licenses/>.
17
18 """
19 AstupidL3switch
20
21 Foreachswitch:
22 1)KeepatablethatmapsIPaddressestoMACaddressesandswitchports.
23 StockthistableusinginformationfromARPandIPpackets.
24 2)WhenyouseeanARPquery,trytoansweritusinginformationinthetable
25 fromstep1.Iftheinfointhetableisold,justfloodthequery.
26 3)FloodallotherARPs.
27 4)WhenyouseeanIPpacket,ifyouknowthedestinationport(becauseit's
28 inthetablefromstep1),installaflowforit.
29 """
30
31 frompox.coreimportcore
32 importpox
33 log=core.getLogger()
34
35 frompox.lib.packet.ethernetimportethernet,ETHER_BROADCAST
36 frompox.lib.packet.ipv4importipv4
37 frompox.lib.packet.arpimportarp
38 frompox.lib.addressesimportIPAddr,EthAddr
39 frompox.lib.utilimportstr_to_bool,dpidToStr
40 frompox.lib.recocoimportTimer
41
42 importpox.openflow.libopenflow_01asof
43
44 frompox.lib.reventimport*
45
46 importtime
47
48 #Timeoutforflows
49 FLOW_IDLE_TIMEOUT=10

https://github.com/CPqD/RouteFlow/blob/master/pox/pox/forwarding/l3_learning.py 1/6
5/19/2017 RouteFlow/l3_learning.pyatmasterCPqD/RouteFlowGitHub
50
51 #TimeoutforARPentries
52 ARP_TIMEOUT=60*2
53
54 #MaximumnumberofpackettobufferonaswitchforanunknownIP
55 MAX_BUFFERED_PER_IP=5
56
57 #MaximumtimetohangontoabufferforanunknownIPinseconds
58 MAX_BUFFER_TIME=5
59
60
61 classEntry(object):
62 """
63 NotstrictlyanARPentry.
64 Weusetheporttodeterminewhichporttoforwardtrafficoutof.
65 WeusetheMACtoanswerARPreplies.
66 WeusethetimeoutsothatifanentryisolderthanARP_TIMEOUT,we
67 floodtheARPrequestratherthantrytoansweritourselves.
68 """
69 def__init__(self,port,mac):
70 self.timeout=time.time()+ARP_TIMEOUT
71 self.port=port
72 self.mac=mac
73
74 def__eq__(self,other):
75 iftype(other)==tuple:
76 return(self.port,self.mac)==other
77 else:
78 return(self.port,self.mac)==(other.port,other.mac)
79 def__ne__(self,other):
80 returnnotself.__eq__(other)
81
82 defisExpired(self):
83 ifself.port==of.OFPP_NONE:returnFalse
84 returntime.time()>self.timeout
85
86
87 defdpid_to_mac(dpid):
88 returnEthAddr("%012x"%(dpid&0xffFFffFFffFF,))
89
90
91 classl3_switch(EventMixin):
92 def__init__(self,fakeways=[],arp_for_unknowns=False):
93 #Theseare"fakegateways"we'llanswerARPsforthemwithMAC
94 #oftheswitchthey'reconnectedto.
95 self.fakeways=set(fakeways)
96
97 #Ifthisistrueandweseeapacketforanunknown
98 #host,we'llARPforit.
99 self.arp_for_unknowns=arp_for_unknowns
100
101 #(dpid,IP)>expire_time
102 #WeusethistokeepfromspammingARPs
103 self.outstanding_arps={}
104
105 #(dpid,IP)>[(expire_time,buffer_id,in_port),...]
106 #Thesearebufferswe'vegottenatthisdatapathforthisIPwhich
107 #wecan'tdeliverbecausewedon'tknowwheretheygo.
108 self.lost_buffers={}
109
110 #Foreachswitch,wemapIPaddressestoEntries
111 self.arpTable={}
112
113 #Thistimerhandlesexpiringstuff
114 self._expire_timer=Timer(5,self._handle_expiration,recurring=True)
115
116 self.listenTo(core)

https://github.com/CPqD/RouteFlow/blob/master/pox/pox/forwarding/l3_learning.py 2/6
5/19/2017 RouteFlow/l3_learning.pyatmasterCPqD/RouteFlowGitHub
117
118 def_handle_expiration(self):
119 #Calledbyatimersothatwecanremoveolditems.
120 empty=[]
121 fork,vinself.lost_buffers.iteritems():
122 dpid,ip=k
123
124 foriteminlist(v):
125 expires_at,buffer_id,in_port=item
126 ifexpires_at<time.time():
127 #Thispacketisold.Tellthisswitchtodropit.
128 v.remove(item)
129 po=of.ofp_packet_out(buffer_id=buffer_id,in_port=in_port)
130 core.openflow.sendToDPID(dpid,po)
131 iflen(v)==0:empty.append(k)
132
133 #Removeemptybufferbins
134 forkinempty:
135 delself.lost_buffers[k]
136
137 def_send_lost_buffers(self,dpid,ipaddr,macaddr,port):
138 """
139 Wemayhave"lost"bufferspacketswegotbutdidn'tknow
140 wheretosendatthetime.Wemayknownow.Tryandsee.
141 """
142 if(dpid,ipaddr)inself.lost_buffers:
143 #Yup!
144 bucket=self.lost_buffers[(dpid,ipaddr)]
145 delself.lost_buffers[(dpid,ipaddr)]
146 log.debug("Sending%ibufferedpacketsto%sfrom%s"
147 %(len(bucket),ipaddr,dpidToStr(dpid)))
148 for_,buffer_id,in_portinbucket:
149 po=of.ofp_packet_out(buffer_id=buffer_id,in_port=in_port)
150 po.actions.append(of.ofp_action_dl_addr.set_dst(macaddr))
151 po.actions.append(of.ofp_action_output(port=port))
152 core.openflow.sendToDPID(dpid,po)
153
154 def_handle_GoingUpEvent(self,event):
155 self.listenTo(core.openflow)
156 log.debug("Up...")
157
158 def_handle_PacketIn(self,event):
159 dpid=event.connection.dpid
160 inport=event.port
161 packet=event.parsed
162 ifnotpacket.parsed:
163 log.warning("%i%iignoringunparsedpacket",dpid,inport)
164 return
165
166 ifdpidnotinself.arpTable:
167 #Newswitchcreateanemptytable
168 self.arpTable[dpid]={}
169 forfakeinself.fakeways:
170 self.arpTable[dpid][IPAddr(fake)]=Entry(of.OFPP_NONE,
171 dpid_to_mac(dpid))
172
173 ifpacket.type==ethernet.LLDP_TYPE:
174 #IgnoreLLDPpackets
175 return
176
177 ifisinstance(packet.next,ipv4):
178 log.debug("%i%iIP%s=>%s",dpid,inport,
179 packet.next.srcip,packet.next.dstip)
180
181 #Sendanywaitingpackets...
182 self._send_lost_buffers(dpid,packet.next.srcip,packet.src,inport)
183

https://github.com/CPqD/RouteFlow/blob/master/pox/pox/forwarding/l3_learning.py 3/6
5/19/2017 RouteFlow/l3_learning.pyatmasterCPqD/RouteFlowGitHub
184 #Learnorupdateport/MACinfo
185 ifpacket.next.srcipinself.arpTable[dpid]:
186 ifself.arpTable[dpid][packet.next.srcip]!=(inport,packet.src):
187 log.info("%i%iRElearned%s",dpid,inport,packet.next.srcip)
188 else:
189 log.debug("%i%ilearned%s",dpid,inport,str(packet.next.srcip))
190 self.arpTable[dpid][packet.next.srcip]=Entry(inport,packet.src)
191
192 #Trytoforward
193 dstaddr=packet.next.dstip
194 ifdstaddrinself.arpTable[dpid]:
195 #Wehaveinfoaboutwhatporttosenditouton...
196
197 prt=self.arpTable[dpid][dstaddr].port
198 mac=self.arpTable[dpid][dstaddr].mac
199 ifprt==inport:
200 log.warning("%i%inotsendingpacketfor%sbackoutofthe"+
201 "inputport"%(dpid,inport,str(dstaddr)))
202 else:
203 log.debug("%i%iinstallingflowfor%s=>%soutport%i"
204 %(dpid,inport,packet.next.srcip,dstaddr,prt))
205
206 actions=[]
207 actions.append(of.ofp_action_dl_addr.set_dst(mac))
208 actions.append(of.ofp_action_output(port=prt))
209 match=of.ofp_match.from_packet(packet,inport)
210 match.dl_src=None#WildcardsourceMAC
211
212 msg=of.ofp_flow_mod(command=of.OFPFC_ADD,
213 idle_timeout=FLOW_IDLE_TIMEOUT,
214 hard_timeout=of.OFP_FLOW_PERMANENT,
215 buffer_id=event.ofp.buffer_id,
216 actions=actions,
217 match=of.ofp_match.from_packet(packet,
218 inport))
219 event.connection.send(msg.pack())
220 elifself.arp_for_unknowns:
221 #Wedon'tknowthisdestination.
222 #First,wetrackthisbuffersothatwecantrytoresenditlater
223 #ifwelearnthedestination,secondweARPforthedestination,
224 #whichshouldultimatelyresultinitrespondinganduslearning
225 #whereitis
226
227 #Addtotrackedbuffers
228 if(dpid,dstaddr)notinself.lost_buffers:
229 self.lost_buffers[(dpid,dstaddr)]=[]
230 bucket=self.lost_buffers[(dpid,dstaddr)]
231 entry=(time.time()+MAX_BUFFER_TIME,event.ofp.buffer_id,inport)
232 bucket.append(entry)
233 whilelen(bucket)>MAX_BUFFERED_PER_IP:delbucket[0]
234
235 #ExpirethingsfromouroutstandingARPlist...
236 self.outstanding_arps={k:vfork,vin
237 self.outstanding_arps.iteritems()ifv>time.time()}
238
239 #Checkifwe'vealreadyARPedrecently
240 if(dpid,dstaddr)inself.outstanding_arps:
241 #Oop,we'vealreadydonethisonerecently.
242 return
243
244 #AndARP...
245 self.outstanding_arps[(dpid,dstaddr)]=time.time()+4
246
247 r=arp()
248 r.hwtype=r.HW_TYPE_ETHERNET
249 r.prototype=r.PROTO_TYPE_IP
250 r.hwlen=6

https://github.com/CPqD/RouteFlow/blob/master/pox/pox/forwarding/l3_learning.py 4/6
5/19/2017 RouteFlow/l3_learning.pyatmasterCPqD/RouteFlowGitHub
251 r.protolen=r.protolen
252 r.opcode=r.REQUEST
253 r.hwdst=ETHER_BROADCAST
254 r.protodst=dstaddr
255 r.hwsrc=packet.src
256 r.protosrc=packet.next.srcip
257 e=ethernet(type=ethernet.ARP_TYPE,src=packet.src,
258 dst=ETHER_BROADCAST)
259 e.set_payload(r)
260 log.debug("%i%iARPingfor%sonbehalfof%s"%(dpid,inport,
261 str(r.protodst),str(r.protosrc)))
262 msg=of.ofp_packet_out()
263 msg.data=e.pack()
264 msg.actions.append(of.ofp_action_output(port=of.OFPP_FLOOD))
265 msg.in_port=inport
266 event.connection.send(msg)
267
268 elifisinstance(packet.next,arp):
269 a=packet.next
270 log.debug("%i%iARP%s%s=>%s",dpid,inport,
271 {arp.REQUEST:"request",arp.REPLY:"reply"}.get(a.opcode,
272 'op:%i'%(a.opcode,)),str(a.protosrc),str(a.protodst))
273
274 ifa.prototype==arp.PROTO_TYPE_IP:
275 ifa.hwtype==arp.HW_TYPE_ETHERNET:
276 ifa.protosrc!=0:
277
278 #Learnorupdateport/MACinfo
279 ifa.protosrcinself.arpTable[dpid]:
280 ifself.arpTable[dpid][a.protosrc]!=(inport,packet.src):
281 log.info("%i%iRElearned%s",dpid,inport,str(a.protosrc))
282 else:
283 log.debug("%i%ilearned%s",dpid,inport,str(a.protosrc))
284 self.arpTable[dpid][a.protosrc]=Entry(inport,packet.src)
285
286 #Sendanywaitingpackets...
287 self._send_lost_buffers(dpid,a.protosrc,packet.src,inport)
288
289 ifa.opcode==arp.REQUEST:
290 #Maybewecananswer
291
292 ifa.protodstinself.arpTable[dpid]:
293 #Wehaveananswer...
294
295 ifnotself.arpTable[dpid][a.protodst].isExpired():
296 #..andit'srelativelycurrent,sowe'llreplyourselves
297
298 r=arp()
299 r.hwtype=a.hwtype
300 r.prototype=a.prototype
301 r.hwlen=a.hwlen
302 r.protolen=a.protolen
303 r.opcode=arp.REPLY
304 r.hwdst=a.hwsrc
305 r.protodst=a.protosrc
306 r.protosrc=a.protodst
307 r.hwsrc=self.arpTable[dpid][a.protodst].mac
308 e=ethernet(type=packet.type,src=dpid_to_mac(dpid),dst=a.hwsrc)
309 e.set_payload(r)
310 log.debug("%i%iansweringARPfor%s"%(dpid,inport,
311 str(r.protosrc)))
312 msg=of.ofp_packet_out()
313 msg.data=e.pack()
314 msg.actions.append(of.ofp_action_output(port=
315 of.OFPP_IN_PORT))
316 msg.in_port=inport
317 event.connection.send(msg)

https://github.com/CPqD/RouteFlow/blob/master/pox/pox/forwarding/l3_learning.py 5/6
5/19/2017 RouteFlow/l3_learning.pyatmasterCPqD/RouteFlowGitHub
318 return
319
320 #Didn'tknowhowtoanswerorotherwisehandlethisARP,sojustfloodit
321 log.debug("%i%ifloodingARP%s%s=>%s"%(dpid,inport,
322 {arp.REQUEST:"request",arp.REPLY:"reply"}.get(a.opcode,
323 'op:%i'%(a.opcode,)),str(a.protosrc),str(a.protodst)))
324
325 msg=of.ofp_packet_out(in_port=inport,action=of.ofp_action_output(port=of.OFPP_FLOOD))
326 ifevent.ofp.buffer_idisof.NO_BUFFER:
327 #Trysendingthe(probablyincomplete)rawdata
328 msg.data=event.data
329 else:
330 msg.buffer_id=event.ofp.buffer_id
331 event.connection.send(msg.pack())
332
333
334 deflaunch(fakeways="",arp_for_unknowns=None):
335 fakeways=fakeways.replace(",","").split()
336 fakeways=[IPAddr(x)forxinfakeways]
337 ifarp_for_unknownsisNone:
338 arp_for_unknowns=len(fakeways)>0
339 else:
340 arp_for_unknowns=str_to_bool(arp_for_unknowns)
341 core.registerNew(l3_switch,fakeways,arp_for_unknowns)
342

2017 GitHub, Inc. Terms Privacy Security Status Help Contact GitHub API Training Shop Blog About

https://github.com/CPqD/RouteFlow/blob/master/pox/pox/forwarding/l3_learning.py 6/6

You might also like