blob: 9f0fa86428de262034f28f8994ee4698aa4e640c [file] [log] [blame]
Sangho Shin01bca862014-09-12 11:18:59 -07001/*******************************************************************************
2 * Copyright (c) 2014 Open Networking Laboratory.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Apache License v2.0
5 * which accompanies this distribution, and is available at
6 * http://www.apache.org/licenses/LICENSE-2.0
7 ******************************************************************************/
8
9package net.onrc.onos.apps.segmentrouting;
10
11import java.net.Inet4Address;
12import java.net.InetAddress;
13import java.net.UnknownHostException;
Sangho Shin01bca862014-09-12 11:18:59 -070014
Sangho Shin01bca862014-09-12 11:18:59 -070015import net.floodlightcontroller.core.IFloodlightProviderService;
Sangho Shin01bca862014-09-12 11:18:59 -070016import net.floodlightcontroller.core.module.FloodlightModuleContext;
Sangho Shin01bca862014-09-12 11:18:59 -070017import net.floodlightcontroller.util.MACAddress;
18import net.onrc.onos.api.packet.IPacketListener;
19import net.onrc.onos.api.packet.IPacketService;
20import net.onrc.onos.core.flowprogrammer.IFlowPusherService;
Sangho Shin01bca862014-09-12 11:18:59 -070021import net.onrc.onos.core.packet.ARP;
22import net.onrc.onos.core.packet.Ethernet;
23import net.onrc.onos.core.packet.IPv4;
Sangho Shin01bca862014-09-12 11:18:59 -070024import net.onrc.onos.core.topology.ITopologyService;
25import net.onrc.onos.core.topology.MutableTopology;
26import net.onrc.onos.core.topology.Port;
27import net.onrc.onos.core.topology.Switch;
28import net.onrc.onos.core.util.SwitchPort;
29
Sangho Shin01bca862014-09-12 11:18:59 -070030import org.projectfloodlight.openflow.types.IPv4Address;
Sangho Shin01bca862014-09-12 11:18:59 -070031import org.slf4j.Logger;
32import org.slf4j.LoggerFactory;
33
34import com.esotericsoftware.minlog.Log;
35
36/**
37 * Handling ARP requests to switches for Segment Routing.
38 * <p/>
39 * The module is for handling ARP requests to switches. It sends ARP response for any known
40 * hosts to the controllers.
41 * TODO: need to check the network config file for all hosts and packets
42 */
Sangho Shin2f263692014-09-15 14:09:41 -070043public class ArpHandler implements IPacketListener {
Sangho Shin01bca862014-09-12 11:18:59 -070044
45 private static final Logger log = LoggerFactory
46 .getLogger(ArpHandler.class);
47
48 private IFloodlightProviderService floodlightProvider;
49 private IPacketService packetService;
50 private IFlowPusherService flowPusher;
51 private ITopologyService topologyService;
52 private MutableTopology mutableTopology;
Sangho Shin2f263692014-09-15 14:09:41 -070053 //private List<ArpEntry> arpEntries;
54 private SegmentRoutingManager srManager;
Sangho Shin01bca862014-09-12 11:18:59 -070055
56 private static final short IDLE_TIMEOUT = 0;
57 private static final short HARD_TIMEOUT = 0;
58
59 private static final int TABLE_VLAN = 0;
60 private static final int TABLE_TMAC = 1;
61 private static final int TABLE_IPv4_UNICAST = 2;
62 private static final int TABLE_MPLS = 3;
63 private static final int TABLE_META = 4;
64 private static final int TABLE_ACL = 5;
65
66 private static final short MAX_PRIORITY = (short) 0xffff;
67 private static final short SLASH_24_PRIORITY = (short) 0xfff0;
68 private static final short SLASH_16_PRIORITY = (short) 0xff00;
69 private static final short SLASH_8_PRIORITY = (short) 0xf000;
70 private static final short MIN_PRIORITY = 0x0;
71
72
Sangho Shin2f263692014-09-15 14:09:41 -070073 /*
74 * Default Constructor
75 */
76 public ArpHandler(FloodlightModuleContext context, SegmentRoutingManager segmentRoutingManager) {
Sangho Shin01bca862014-09-12 11:18:59 -070077
Sangho Shin01bca862014-09-12 11:18:59 -070078 this.floodlightProvider = context.getServiceImpl(IFloodlightProviderService.class);
79 this.packetService = context.getServiceImpl(IPacketService.class);
80 this.flowPusher = context.getServiceImpl(IFlowPusherService.class);
81 this.topologyService = context.getServiceImpl(ITopologyService.class);
Sangho Shin2f263692014-09-15 14:09:41 -070082 this.srManager = segmentRoutingManager;
83 this.mutableTopology = topologyService.getTopology();
84
85 packetService.registerPacketListener(this);
86 //arpEntries = new ArrayList<ArpEntry>();
Sangho Shin01bca862014-09-12 11:18:59 -070087
88 Log.debug("Arp Handler is initialized");
89
90 }
91
92 @Override
Sangho Shin01bca862014-09-12 11:18:59 -070093 public void receive(Switch sw, Port inPort, Ethernet payload) {
94 log.debug("Received a packet {} from sw {} ", payload.toString(), sw.getDpid());
95
96 if (payload.getEtherType() == Ethernet.TYPE_ARP) {
97
98 ARP arp = (ARP)payload.getPayload();
Sangho Shin2f263692014-09-15 14:09:41 -070099 srManager.updateArpCache(arp);
Sangho Shin01bca862014-09-12 11:18:59 -0700100
101 if (arp.getOpCode() == ARP.OP_REQUEST) {
102
103 handleArpRequest(sw, inPort, arp);
104 }
105
106 }
Sangho Shin01bca862014-09-12 11:18:59 -0700107
108 }
109
Sangho Shin01bca862014-09-12 11:18:59 -0700110
111 /**
112 * Send an ARP response for the ARP request to the known switches
113 *
114 * @param sw Switch
115 * @param inPort port to send ARP response to
116 * @param arpRequest ARP request packet to handle
117 */
118 private void handleArpRequest(Switch sw, Port inPort, ARP arpRequest) {
119
120 String switchIpAddressSlash = sw.getStringAttribute("routerIp");
121 String switchMacAddressStr = sw.getStringAttribute("routerMac");
122 if (switchIpAddressSlash != null && switchMacAddressStr != null) {
123
124 String switchIpAddressStr = switchIpAddressSlash.substring(0, switchIpAddressSlash.indexOf('/'));
125 IPv4Address switchIpAddress = IPv4Address.of(switchIpAddressStr);
126 IPv4Address targetProtocolAddress = IPv4Address.of(arpRequest.getTargetProtocolAddress());
127 if (targetProtocolAddress.equals(switchIpAddress)) {
128 MACAddress targetMac = MACAddress.valueOf(switchMacAddressStr);
129
130 ARP arpReply = new ARP();
131 arpReply.setHardwareType(ARP.HW_TYPE_ETHERNET)
132 .setProtocolType(ARP.PROTO_TYPE_IP)
133 .setHardwareAddressLength(
134 (byte) Ethernet.DATALAYER_ADDRESS_LENGTH)
135 .setProtocolAddressLength((byte) IPv4.ADDRESS_LENGTH)
136 .setOpCode(ARP.OP_REPLY)
137 .setSenderHardwareAddress(targetMac.toBytes())
138 .setSenderProtocolAddress(arpRequest.getTargetProtocolAddress())
139 .setTargetHardwareAddress(arpRequest.getSenderHardwareAddress())
140 .setTargetProtocolAddress(arpRequest.getSenderProtocolAddress());
141
142 Ethernet eth = new Ethernet();
143 eth.setDestinationMACAddress(arpRequest.getSenderHardwareAddress())
144 .setSourceMACAddress(targetMac.toBytes())
145 .setEtherType(Ethernet.TYPE_ARP).setPayload(arpReply);
146
147 packetService.sendPacket(eth, new SwitchPort(sw.getDpid(), inPort.getPortNumber()));
148 }
149 }
150 }
151
152 /**
Sangho Shin01bca862014-09-12 11:18:59 -0700153 * The function checks if given IP matches to the given subnet mask
154 *
155 * @param addr - subnet address to match
156 * @param addr1 - IP address to check
157 * @return true if the IP address matches to the subnet, otherwise false
158 */
159
160 public static boolean netMatch(String addr, String addr1){ //addr is subnet address and addr1 is ip address. Function will return true, if addr1 is within addr(subnet)
161
162 String[] parts = addr.split("/");
163 String ip = parts[0];
164 int prefix;
165
166 if (parts.length < 2) {
167 prefix = 0;
168 } else {
169 prefix = Integer.parseInt(parts[1]);
170 }
171
172 Inet4Address a =null;
173 Inet4Address a1 =null;
174 try {
175 a = (Inet4Address) InetAddress.getByName(ip);
176 a1 = (Inet4Address) InetAddress.getByName(addr1);
177 } catch (UnknownHostException e){}
178
179 byte[] b = a.getAddress();
180 int ipInt = ((b[0] & 0xFF) << 24) |
181 ((b[1] & 0xFF) << 16) |
182 ((b[2] & 0xFF) << 8) |
183 ((b[3] & 0xFF) << 0);
184
185 byte[] b1 = a1.getAddress();
186 int ipInt1 = ((b1[0] & 0xFF) << 24) |
187 ((b1[1] & 0xFF) << 16) |
188 ((b1[2] & 0xFF) << 8) |
189 ((b1[3] & 0xFF) << 0);
190
191 int mask = ~((1 << (32 - prefix)) - 1);
192
193 if ((ipInt & mask) == (ipInt1 & mask)) {
194 return true;
195 }
196 else {
197 return false;
198 }
199}
200
201
202
203
204}