0% found this document useful (0 votes)
98 views6 pages

RouteFlow l3 Learning

sdn
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
98 views6 pages

RouteFlow l3 Learning

sdn
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 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