blob: 5126958198e5021fceff2e8cc50fbf12769a5c74 [file] [log] [blame]
Sangho Shin2f263692014-09-15 14:09:41 -07001package net.onrc.onos.apps.segmentrouting;
2
3import java.util.ArrayList;
4import java.util.List;
5
6import net.floodlightcontroller.core.IFloodlightProviderService;
7import net.floodlightcontroller.core.IOFSwitch;
8import net.floodlightcontroller.core.module.FloodlightModuleContext;
9import net.floodlightcontroller.util.MACAddress;
10import net.onrc.onos.api.packet.IPacketListener;
11import net.onrc.onos.api.packet.IPacketService;
12import net.onrc.onos.core.flowprogrammer.IFlowPusherService;
13import net.onrc.onos.core.packet.Ethernet;
14import net.onrc.onos.core.packet.IPv4;
15import net.onrc.onos.core.topology.ITopologyService;
16import net.onrc.onos.core.topology.MutableTopology;
17import net.onrc.onos.core.topology.Port;
18import net.onrc.onos.core.topology.Switch;
19
20import org.projectfloodlight.openflow.protocol.OFFactory;
21import org.projectfloodlight.openflow.protocol.OFMatchV3;
22import org.projectfloodlight.openflow.protocol.OFMessage;
23import org.projectfloodlight.openflow.protocol.OFOxmList;
24import org.projectfloodlight.openflow.protocol.action.OFAction;
25import org.projectfloodlight.openflow.protocol.instruction.OFInstruction;
26import org.projectfloodlight.openflow.protocol.oxm.OFOxmEthDst;
27import org.projectfloodlight.openflow.protocol.oxm.OFOxmEthSrc;
28import org.projectfloodlight.openflow.protocol.oxm.OFOxmEthType;
29import org.projectfloodlight.openflow.protocol.oxm.OFOxmIpv4DstMasked;
30import org.projectfloodlight.openflow.types.EthType;
31import org.projectfloodlight.openflow.types.IPv4Address;
32import org.projectfloodlight.openflow.types.MacAddress;
33import org.projectfloodlight.openflow.types.OFBufferId;
34import org.projectfloodlight.openflow.types.OFPort;
35import org.projectfloodlight.openflow.types.TableId;
36import org.slf4j.Logger;
37import org.slf4j.LoggerFactory;
38
39public class IcmpHandler implements IPacketListener {
40
41 private SegmentRoutingManager srManager;
42 private IFloodlightProviderService floodlightProvider;
43 private MutableTopology mutableTopology;
44 private IPacketService packetService;
45 private ITopologyService topologyService;
46 private static final Logger log = LoggerFactory
47 .getLogger(ArpHandler.class);
48
49 private IFlowPusherService flowPusher;
50
51 private static final int TABLE_VLAN = 0;
52 private static final int TABLE_TMAC = 1;
53 private static final int TABLE_IPv4_UNICAST = 2;
54 private static final int TABLE_MPLS = 3;
55 private static final int TABLE_META = 4;
56 private static final int TABLE_ACL = 5;
57
58 private static final short MAX_PRIORITY = (short) 0xffff;
59 private static final short SLASH_24_PRIORITY = (short) 0xfff0;
60 private static final short SLASH_16_PRIORITY = (short) 0xff00;
61 private static final short SLASH_8_PRIORITY = (short) 0xf000;
62 private static final short MIN_PRIORITY = 0x0;
63
64
65 public IcmpHandler(FloodlightModuleContext context, SegmentRoutingManager manager) {
66
67 this.floodlightProvider = context.getServiceImpl(IFloodlightProviderService.class);
68 this.flowPusher = context.getServiceImpl(IFlowPusherService.class);
69 this.packetService = context.getServiceImpl(IPacketService.class);
70 this.topologyService = context.getServiceImpl(ITopologyService.class);
71 this.mutableTopology = topologyService.getTopology();
72
73 this.srManager = manager;
74
75 packetService.registerPacketListener(this);
76
77 }
78
79 @Override
80 public void receive(Switch sw, Port inPort, Ethernet payload) {
81
82 if (payload.getEtherType() == Ethernet.TYPE_IPV4) {
83
84 IPv4 ipv4 = (IPv4)payload.getPayload();
85 if (ipv4.getProtocol() == IPv4.PROTOCOL_ICMP) {
86
87 addRouteToHost(sw, ipv4);
88
89 }
90
91 }
92
93 }
94
95 /**
96 * Add routing rules to forward packets to known hosts
97 *
98 * @param sw Switch
99 * @param hostIp Host IP address to forwards packets to
100 */
101 private void addRouteToHost(Switch sw, IPv4 hostIp) {
102
103 IOFSwitch ofSwitch = floodlightProvider.getMasterSwitch(sw.getDpid().value());
104 OFFactory factory = ofSwitch.getFactory();
105 int destinationAddress = hostIp.getDestinationAddress();
106 // Check APR entries
107 byte[] destinationMacAddress = null;;
108
109 // srManager.getMacAddressFromIpAddress(destinationAddress);
110
111 // Check TopologyService
112
113 for (net.onrc.onos.core.topology.Host host: mutableTopology.getHosts()) {
114 IPv4Address hostIpAddress = IPv4Address.of(host.getIpAddress());
115 if (hostIpAddress != null && hostIpAddress.getInt() == destinationAddress) {
116 destinationMacAddress = host.getMacAddress().toBytes();
117 }
118 }
119
120
121 // If MAC address is not known to the host, just return
122 if (destinationMacAddress == null)
123 return;
124
125 OFOxmEthType ethTypeIp = factory.oxms()
126 .ethType(EthType.IPv4);
127 OFOxmIpv4DstMasked ipPrefix = factory.oxms()
128 .ipv4DstMasked(
129 IPv4Address.of(destinationAddress),
130 IPv4Address.NO_MASK); // host addr should be /32
131 OFOxmList oxmListSlash32 = OFOxmList.of(ethTypeIp, ipPrefix);
132 OFMatchV3 match = factory.buildMatchV3()
133 .setOxmList(oxmListSlash32).build();
134 OFAction setDmac = null;
135 OFOxmEthDst dmac = factory.oxms()
136 .ethDst(MacAddress.of(destinationMacAddress));
137 setDmac = factory.actions().buildSetField()
138 .setField(dmac).build();
139
140 OFAction decTtl = factory.actions().decNwTtl();
141
142 // Set the source MAC address with the switch MAC address
143 String switchMacAddress = sw.getStringAttribute("routerMac");
144 OFOxmEthSrc srcAddr = factory.oxms().ethSrc(MacAddress.of(switchMacAddress));
145 OFAction setSA = factory.actions().buildSetField()
146 .setField(srcAddr).build();
147
148 List<OFAction> actionList = new ArrayList<OFAction>();
149 actionList.add(setDmac);
150 actionList.add(decTtl);
151 actionList.add(setSA);
152
153
154 /* TODO : need to check the config file for all packets
155 String subnets = sw.getStringAttribute("subnets");
156 try {
157 JSONArray arry = new JSONArray(subnets);
158 for (int i = 0; i < arry.length(); i++) {
159 String subnetIp = (String) arry.getJSONObject(i).get("subnetIp");
160 int portNo = (int) arry.getJSONObject(i).get("portNo");
161
162 if (netMatch(subnetIp, IPv4Address.of(hostIp.getDestinationAddress()).toString())) {
163 OFAction out = factory.actions().buildOutput()
164 .setPort(OFPort.of(portNo)).build();
165 actionList.add(out);
166 }
167 }
168 } catch (JSONException e) {
169 // TODO Auto-generated catch block
170 e.printStackTrace();
171 }
172 */
173
174 // Set output port
175 net.onrc.onos.core.topology.Host host = mutableTopology.getHostByMac(MACAddress.valueOf(destinationMacAddress));
176 if (host != null) {
177 for (Port port: host.getAttachmentPoints()) {
178 OFAction out = factory.actions().buildOutput()
179 .setPort(OFPort.of(port.getPortNumber().shortValue())).build();
180 actionList.add(out);
181 }
182 }
183
184 OFInstruction writeInstr = factory.instructions().buildWriteActions()
185 .setActions(actionList).build();
186
187 List<OFInstruction> instructions = new ArrayList<OFInstruction>();
188 instructions.add(writeInstr);
189
190 OFMessage myIpEntry = factory.buildFlowAdd()
191 .setTableId(TableId.of(TABLE_IPv4_UNICAST))
192 .setMatch(match)
193 .setInstructions(instructions)
194 .setPriority(MAX_PRIORITY)
195 .setBufferId(OFBufferId.NO_BUFFER)
196 .setIdleTimeout(0)
197 .setHardTimeout(0)
198 //.setXid(getNextTransactionId())
199 .build();
200
201 log.debug("Sending 'Routing information' OF message to the switch {}.", sw.getDpid().toString());
202
203 flowPusher.add(sw.getDpid(), myIpEntry);
204
205
206 }
207
208}