blob: 7e6d2ac1faa7422535fa1ad6aba80a98e21f6c7f [file] [log] [blame]
Sangho Shineb083032014-09-22 16:11:34 -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 GenericIpHandler implements IPacketListener {
40
41 private MutableTopology mutableTopology;
42 private ITopologyService topologyService;
43 private IFloodlightProviderService floodlightProvider;
44 private IFlowPusherService flowPusher;
45 private IPacketService packetService;
46 private SegmentRoutingManager srManager;
47
48 private static final Logger log = LoggerFactory
49 .getLogger(GenericIpHandler.class);
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 public GenericIpHandler(FloodlightModuleContext context, SegmentRoutingManager sr) {
65 this.floodlightProvider = context.getServiceImpl(IFloodlightProviderService.class);
66 this.topologyService = context.getServiceImpl(ITopologyService.class);
67 this.mutableTopology = topologyService.getTopology();
68 this.flowPusher = context.getServiceImpl(IFlowPusherService.class);
69 this.packetService = context.getServiceImpl(IPacketService.class);
70 this.srManager = sr;
71
72 packetService.registerPacketListener(this);
73
74 }
75
76 @Override
77 public void receive(Switch sw, Port inPort, Ethernet payload) {
78 // TODO Auto-generated method stub
79 if (payload.getEtherType() == Ethernet.TYPE_IPV4) {
80
81 IPv4 ipv4 = (IPv4)payload.getPayload();
82 int destinationAddress = ipv4.getDestinationAddress();
83
84 // Check if the destination is any host known to TopologyService
85 for (net.onrc.onos.core.topology.Host host: mutableTopology.getHosts()) {
86 IPv4Address hostIpAddress = IPv4Address.of(host.getIpAddress());
87 if (hostIpAddress != null && hostIpAddress.getInt() == destinationAddress) {
88 byte[] destinationMacAddress = host.getMacAddress().toBytes();
89 addRouteToHost(sw, destinationAddress, destinationMacAddress);
90 return;
91 }
92 }
93
94 // Check if the destination is within subnets of the swtich
95 if (isWithinSubnets(sw, IPv4Address.of(destinationAddress).toString())) {
96 srManager.sendArpRequest(sw, destinationAddress, inPort);
97 }
98 }
99 }
100
101 private boolean isWithinSubnets(Switch sw, String ipAddress) {
102
103 return true;
104 }
105
106
107 /**
108 * Add routing rules to forward packets to known hosts
109 *
110 * @param sw Switch
111 * @param hostIp Host IP address to forwards packets to
112 */
113 public void addRouteToHost(Switch sw, int destinationAddress, byte[] destinationMacAddress) {
114
115 IOFSwitch ofSwitch = floodlightProvider.getMasterSwitch(sw.getDpid().value());
116 OFFactory factory = ofSwitch.getFactory();
117
118
119 OFOxmEthType ethTypeIp = factory.oxms()
120 .ethType(EthType.IPv4);
121 OFOxmIpv4DstMasked ipPrefix = factory.oxms()
122 .ipv4DstMasked(
123 IPv4Address.of(destinationAddress),
124 IPv4Address.NO_MASK); // host addr should be /32
125 OFOxmList oxmListSlash32 = OFOxmList.of(ethTypeIp, ipPrefix);
126 OFMatchV3 match = factory.buildMatchV3()
127 .setOxmList(oxmListSlash32).build();
128 OFAction setDmac = null;
129 OFOxmEthDst dmac = factory.oxms()
130 .ethDst(MacAddress.of(destinationMacAddress));
131 setDmac = factory.actions().buildSetField()
132 .setField(dmac).build();
133
134 OFAction decTtl = factory.actions().decNwTtl();
135
136 // Set the source MAC address with the switch MAC address
137 String switchMacAddress = sw.getStringAttribute("routerMac");
138 OFOxmEthSrc srcAddr = factory.oxms().ethSrc(MacAddress.of(switchMacAddress));
139 OFAction setSA = factory.actions().buildSetField()
140 .setField(srcAddr).build();
141
142 List<OFAction> actionList = new ArrayList<OFAction>();
143 actionList.add(setDmac);
144 actionList.add(decTtl);
145 actionList.add(setSA);
146
147
148 /* TODO : need to check the config file for all packets
149 String subnets = sw.getStringAttribute("subnets");
150 try {
151 JSONArray arry = new JSONArray(subnets);
152 for (int i = 0; i < arry.length(); i++) {
153 String subnetIp = (String) arry.getJSONObject(i).get("subnetIp");
154 int portNo = (int) arry.getJSONObject(i).get("portNo");
155
156 if (netMatch(subnetIp, IPv4Address.of(hostIp.getDestinationAddress()).toString())) {
157 OFAction out = factory.actions().buildOutput()
158 .setPort(OFPort.of(portNo)).build();
159 actionList.add(out);
160 }
161 }
162 } catch (JSONException e) {
163 // TODO Auto-generated catch block
164 e.printStackTrace();
165 }
166 */
167
168 // Set output port
169 net.onrc.onos.core.topology.Host host = mutableTopology.getHostByMac(MACAddress.valueOf(destinationMacAddress));
170 if (host != null) {
171 for (Port port: host.getAttachmentPoints()) {
172 OFAction out = factory.actions().buildOutput()
173 .setPort(OFPort.of(port.getPortNumber().shortValue())).build();
174 actionList.add(out);
175 }
176 }
177
178 OFInstruction writeInstr = factory.instructions().buildWriteActions()
179 .setActions(actionList).build();
180
181 List<OFInstruction> instructions = new ArrayList<OFInstruction>();
182 instructions.add(writeInstr);
183
184 OFMessage myIpEntry = factory.buildFlowAdd()
185 .setTableId(TableId.of(TABLE_IPv4_UNICAST))
186 .setMatch(match)
187 .setInstructions(instructions)
188 .setPriority(MAX_PRIORITY)
189 .setBufferId(OFBufferId.NO_BUFFER)
190 .setIdleTimeout(0)
191 .setHardTimeout(0)
192 //.setXid(getNextTransactionId())
193 .build();
194
195 log.debug("Sending 'Routing information' OF message to the switch {}.", sw.getDpid().toString());
196
197 flowPusher.add(sw.getDpid(), myIpEntry);
198
199 }
200
201
202}