blob: f75a2b06a74a128013aac2f4c0003497695a9c85 [file] [log] [blame]
Jonathan Hartd857ad62013-12-14 18:08:17 -08001package net.onrc.onos.ofcontroller.devicemanager;
2
3import java.util.ArrayList;
4import java.util.Collection;
5import java.util.Date;
6import java.util.HashMap;
7import java.util.List;
8import java.util.Map;
9
10import net.floodlightcontroller.core.FloodlightContext;
11import net.floodlightcontroller.core.IFloodlightProviderService;
12import net.floodlightcontroller.core.IOFMessageListener;
13import net.floodlightcontroller.core.IOFSwitch;
14import net.floodlightcontroller.core.IUpdate;
15import net.floodlightcontroller.core.module.FloodlightModuleContext;
16import net.floodlightcontroller.core.module.FloodlightModuleException;
17import net.floodlightcontroller.core.module.IFloodlightModule;
18import net.floodlightcontroller.core.module.IFloodlightService;
19import net.floodlightcontroller.packet.ARP;
20import net.floodlightcontroller.packet.DHCP;
21import net.floodlightcontroller.packet.Ethernet;
22import net.floodlightcontroller.packet.IPv4;
23import net.floodlightcontroller.packet.UDP;
24import net.floodlightcontroller.util.MACAddress;
25import net.onrc.onos.ofcontroller.core.IDeviceStorage;
26import net.onrc.onos.ofcontroller.core.internal.DeviceStorageImpl;
27
28import org.openflow.protocol.OFMessage;
29import org.openflow.protocol.OFPacketIn;
30import org.openflow.protocol.OFType;
31
32public class OnosDeviceManager implements IFloodlightModule, IOFMessageListener,
33 IOnosDeviceService {
34 private IDeviceStorage deviceStorage;
35
36 private IFloodlightProviderService floodlightProvider;
37
Jonathan Hart18ad9502013-12-15 18:28:00 -080038 private class OnosDeviceUpdate implements IUpdate {
Jonathan Hartd857ad62013-12-14 18:08:17 -080039 private OnosDevice device;
40
41 public OnosDeviceUpdate(OnosDevice device) {
42 this.device = device;
43 }
44
45 @Override
46 public void dispatch() {
47 deviceStorage.addOnosDevice(device);
48 }
49 }
50
51 @Override
52 public String getName() {
53 return "onosdevicemanager";
54 }
55
56 @Override
57 public boolean isCallbackOrderingPrereq(OFType type, String name) {
Jonathan Hart18ad9502013-12-15 18:28:00 -080058 // We want link discovery to consume LLDP first otherwise we'll
59 // end up reading bad device info from LLDP packets
60 return type == OFType.PACKET_IN && "linkdiscovery".equals(name);
Jonathan Hartd857ad62013-12-14 18:08:17 -080061 }
62
63 @Override
64 public boolean isCallbackOrderingPostreq(OFType type, String name) {
65 return type == OFType.PACKET_IN &&
66 ("proxyarpmanager".equals(name) || "onosforwarding".equals(name));
67 }
68
69 @Override
70 public Command receive(IOFSwitch sw, OFMessage msg, FloodlightContext cntx) {
71 if (msg.getType().equals(OFType.PACKET_IN)) {
72 OFPacketIn pi = (OFPacketIn) msg;
73
74 Ethernet eth = IFloodlightProviderService.bcStore.
75 get(cntx, IFloodlightProviderService.CONTEXT_PI_PAYLOAD);
76
77 return processPacketIn(sw, pi, eth);
78 }
79
80 return Command.CONTINUE;
81 }
82
83 private Command processPacketIn(IOFSwitch sw, OFPacketIn pi, Ethernet eth) {
84
85 // Extract source entity information
86 OnosDevice srcDevice =
87 getSourceDeviceFromPacket(eth, sw.getId(), pi.getInPort());
88 if (srcDevice == null)
89 return Command.STOP;
90
91 floodlightProvider.publishUpdate(new OnosDeviceUpdate(srcDevice));
92
93 return Command.CONTINUE;
94 }
95
96 /**
97 * Get IP address from packet if the packet is either an ARP
98 * or a DHCP packet
99 * @param eth
100 * @param dlAddr
101 * @return
102 */
103 private int getSrcNwAddr(Ethernet eth, long dlAddr) {
104 if (eth.getPayload() instanceof ARP) {
105 ARP arp = (ARP) eth.getPayload();
106 if ((arp.getProtocolType() == ARP.PROTO_TYPE_IP) &&
107 (Ethernet.toLong(arp.getSenderHardwareAddress()) == dlAddr)) {
108 return IPv4.toIPv4Address(arp.getSenderProtocolAddress());
109 }
110 } else if (eth.getPayload() instanceof IPv4) {
111 IPv4 ipv4 = (IPv4) eth.getPayload();
112 if (ipv4.getPayload() instanceof UDP) {
113 UDP udp = (UDP)ipv4.getPayload();
114 if (udp.getPayload() instanceof DHCP) {
115 DHCP dhcp = (DHCP)udp.getPayload();
116 if (dhcp.getOpCode() == DHCP.OPCODE_REPLY) {
117 return ipv4.getSourceAddress();
118 }
119 }
120 }
121 }
122 return 0;
123 }
124
125 /**
126 * Parse an entity from an {@link Ethernet} packet.
127 * @param eth the packet to parse
128 * @param sw the switch on which the packet arrived
129 * @param pi the original packetin
130 * @return the entity from the packet
131 */
132 private OnosDevice getSourceDeviceFromPacket(Ethernet eth,
133 long swdpid,
134 short port) {
135 byte[] dlAddrArr = eth.getSourceMACAddress();
136 long dlAddr = Ethernet.toLong(dlAddrArr);
137
138 // Ignore broadcast/multicast source
139 if ((dlAddrArr[0] & 0x1) != 0)
140 return null;
141
142 short vlan = eth.getVlanID();
143 int nwSrc = getSrcNwAddr(eth, dlAddr);
144 return new OnosDevice(MACAddress.valueOf(dlAddr),
145 ((vlan >= 0) ? vlan : null),
146 ((nwSrc != 0) ? nwSrc : null),
147 swdpid,
148 port,
149 new Date());
150 }
151
152 @Override
153 public Collection<Class<? extends IFloodlightService>> getModuleServices() {
154 List<Class<? extends IFloodlightService>> services =
155 new ArrayList<Class<? extends IFloodlightService>>();
156 services.add(IOnosDeviceService.class);
157 return services;
158 }
159
160 @Override
161 public Map<Class<? extends IFloodlightService>, IFloodlightService> getServiceImpls() {
162 Map<Class<? extends IFloodlightService>, IFloodlightService> impls =
163 new HashMap<Class<? extends IFloodlightService>, IFloodlightService>();
164 impls.put(IOnosDeviceService.class, this);
165 return impls;
166 }
167
168 @Override
169 public Collection<Class<? extends IFloodlightService>> getModuleDependencies() {
170 List<Class<? extends IFloodlightService>> dependencies =
171 new ArrayList<Class<? extends IFloodlightService>>();
172 dependencies.add(IFloodlightProviderService.class);
173 return dependencies;
174 }
175
176 @Override
177 public void init(FloodlightModuleContext context)
178 throws FloodlightModuleException {
179 floodlightProvider = context.getServiceImpl(IFloodlightProviderService.class);
180
181 deviceStorage = new DeviceStorageImpl();
182 deviceStorage.init("");
183 }
184
185 @Override
186 public void startUp(FloodlightModuleContext context) {
187 floodlightProvider.addOFMessageListener(OFType.PACKET_IN, this);
188 }
189
190}