forked from scbzyhx/sdn_access_network
/
host_tracker.py
117 lines (96 loc) · 3.56 KB
/
host_tracker.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
# Copyright (C) 2014 SDN Hub
#
# Licensed under the GNU GENERAL PUBLIC LICENSE, Version 3.
# You may not use this file except in compliance with this License.
# You may obtain a copy of the License at
#
# http://www.gnu.org/licenses/gpl-3.0.txt
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
import logging
import json
from webob import Response
import time
from threading import Timer
from ryu.base import app_manager
from ryu.controller import ofp_event
from ryu.controller.handler import MAIN_DISPATCHER
from ryu.controller.handler import set_ev_cls
from ryu.controller import dpset
from ryu.app.wsgi import ControllerBase, WSGIApplication
from ryu.lib.packet import packet
from ryu.lib.packet import ethernet
from ryu.lib.packet import ipv4
from ryu.lib.packet import arp
from ryu.ofproto import ether
from ryu.ofproto import ofproto_v1_0, ofproto_v1_3
from ryu.lib import dpid as dpid_lib
class HostTracker(app_manager.RyuApp):
def __init__(self, *args, **kwargs):
super(HostTracker, self).__init__(*args, **kwargs)
self.hosts = {}
self.routers = []
self.IDLE_TIMEOUT = 300
if self.CONF.enable_debugger:
self.logger.setLevel(logging.DEBUG)
Timer(self.IDLE_TIMEOUT, self.expireHostEntries).start()
def expireHostEntries(self):
expiredEntries = []
for key,val in self.hosts.iteritems():
if int(time.time()) > val['timestamp'] + self.IDLE_TIMEOUT:
expiredEntries.append(key)
for ip in expiredEntries:
del self.hosts[ip]
Timer(self.IDLE_TIMEOUT, self.expireHostEntries).start()
# The hypothesis is that a router will be the srcMAC
# for many IP addresses at the same time
def isRouter(self, mac):
if mac in self.routers:
return True
ip_list = []
for key,val in self.hosts.iteritems():
if val['mac'] == mac:
ip_list.append(key)
if len(ip_list) > 1:
for ip in ip_list:
del self.hosts[ip]
self.routers.append(mac)
return true
return False
def updateHostTable(self, srcIP, dpid, port):
self.hosts[srcIP]['timestamp'] = int(time.time())
self.hosts[srcIP]['dpid'] = dpid
self.hosts[srcIP]['port'] = port
@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]
if eth.ethertype == ether.ETH_TYPE_ARP:
arp_pkt = pkt.get_protocols(arp.arp)[0]
srcMac = arp_pkt.src_mac
srcIP = arp_pkt.src_ip
elif eth.ethertype == ether.ETH_TYPE_IP:
ip = pkt.get_protocols(ipv4.ipv4)[0]
srcMac = eth.src
srcIP = ip.src
else:
return
##from srcIP to inport
"""
if self.isRouter(srcMac):
return
"""
if srcIP not in self.hosts:
self.hosts[srcIP] = {}
# Always update MAC and switch-port location, just in case
# DHCP reassigned the IP or the host moved
self.hosts[srcIP]['mac'] = srcMac
self.updateHostTable(srcIP, dpid_lib.dpid_to_str(datapath.id), in_port)