blob: fc6c02e67bb64407e5efa60f85eefd6afa7ef1bd [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2014 Open Networking Laboratory.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Apache License v2.0
* which accompanies this distribution, and is available at
* http://www.apache.org/licenses/LICENSE-2.0
******************************************************************************/
package net.onrc.onos.apps.segmentrouting;
import net.floodlightcontroller.core.IFloodlightProviderService;
import net.floodlightcontroller.core.module.FloodlightModuleContext;
import net.floodlightcontroller.util.MACAddress;
import net.onrc.onos.api.packet.IPacketListener;
import net.onrc.onos.api.packet.IPacketService;
import net.onrc.onos.core.flowprogrammer.IFlowPusherService;
import net.onrc.onos.core.packet.ARP;
import net.onrc.onos.core.packet.Ethernet;
import net.onrc.onos.core.packet.IPv4;
import net.onrc.onos.core.topology.ITopologyService;
import net.onrc.onos.core.topology.MutableTopology;
import net.onrc.onos.core.topology.Port;
import net.onrc.onos.core.topology.Switch;
import net.onrc.onos.core.util.SwitchPort;
import org.projectfloodlight.openflow.types.IPv4Address;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.esotericsoftware.minlog.Log;
/**
* Handling ARP requests to switches for Segment Routing.
* <p/>
* The module is for handling ARP requests to switches. It sends ARP response for any known
* hosts to the controllers.
* TODO: need to check the network config file for all hosts and packets
*/
public class ArpHandler implements IPacketListener {
private static final Logger log = LoggerFactory
.getLogger(ArpHandler.class);
private IFloodlightProviderService floodlightProvider;
private IPacketService packetService;
private IFlowPusherService flowPusher;
private ITopologyService topologyService;
private MutableTopology mutableTopology;
//private List<ArpEntry> arpEntries;
private SegmentRoutingManager srManager;
private static final short IDLE_TIMEOUT = 0;
private static final short HARD_TIMEOUT = 0;
private static final int TABLE_VLAN = 0;
private static final int TABLE_TMAC = 1;
private static final int TABLE_IPv4_UNICAST = 2;
private static final int TABLE_MPLS = 3;
private static final int TABLE_META = 4;
private static final int TABLE_ACL = 5;
private static final short MAX_PRIORITY = (short) 0xffff;
private static final short SLASH_24_PRIORITY = (short) 0xfff0;
private static final short SLASH_16_PRIORITY = (short) 0xff00;
private static final short SLASH_8_PRIORITY = (short) 0xf000;
private static final short MIN_PRIORITY = 0x0;
/*
* Default Constructor
*/
public ArpHandler(FloodlightModuleContext context, SegmentRoutingManager segmentRoutingManager) {
this.floodlightProvider = context.getServiceImpl(IFloodlightProviderService.class);
this.packetService = context.getServiceImpl(IPacketService.class);
this.flowPusher = context.getServiceImpl(IFlowPusherService.class);
this.topologyService = context.getServiceImpl(ITopologyService.class);
this.srManager = segmentRoutingManager;
this.mutableTopology = topologyService.getTopology();
packetService.registerPacketListener(this);
//arpEntries = new ArrayList<ArpEntry>();
Log.debug("Arp Handler is initialized");
}
@Override
public void receive(Switch sw, Port inPort, Ethernet payload) {
log.debug("Received a packet {} from sw {} ", payload.toString(), sw.getDpid());
if (payload.getEtherType() == Ethernet.TYPE_ARP) {
ARP arp = (ARP)payload.getPayload();
srManager.updateArpCache(arp);
if (arp.getOpCode() == ARP.OP_REQUEST) {
handleArpRequest(sw, inPort, arp);
}
}
}
/**
* Send an ARP response for the ARP request to the known switches
*
* @param sw Switch
* @param inPort port to send ARP response to
* @param arpRequest ARP request packet to handle
*/
private void handleArpRequest(Switch sw, Port inPort, ARP arpRequest) {
String switchIpAddressSlash = sw.getStringAttribute("routerIp");
String switchMacAddressStr = sw.getStringAttribute("routerMac");
if (switchIpAddressSlash != null && switchMacAddressStr != null) {
String switchIpAddressStr = switchIpAddressSlash.substring(0, switchIpAddressSlash.indexOf('/'));
IPv4Address switchIpAddress = IPv4Address.of(switchIpAddressStr);
IPv4Address targetProtocolAddress = IPv4Address.of(arpRequest.getTargetProtocolAddress());
if (targetProtocolAddress.equals(switchIpAddress)) {
MACAddress targetMac = MACAddress.valueOf(switchMacAddressStr);
ARP arpReply = new ARP();
arpReply.setHardwareType(ARP.HW_TYPE_ETHERNET)
.setProtocolType(ARP.PROTO_TYPE_IP)
.setHardwareAddressLength(
(byte) Ethernet.DATALAYER_ADDRESS_LENGTH)
.setProtocolAddressLength((byte) IPv4.ADDRESS_LENGTH)
.setOpCode(ARP.OP_REPLY)
.setSenderHardwareAddress(targetMac.toBytes())
.setSenderProtocolAddress(arpRequest.getTargetProtocolAddress())
.setTargetHardwareAddress(arpRequest.getSenderHardwareAddress())
.setTargetProtocolAddress(arpRequest.getSenderProtocolAddress());
Ethernet eth = new Ethernet();
eth.setDestinationMACAddress(arpRequest.getSenderHardwareAddress())
.setSourceMACAddress(targetMac.toBytes())
.setEtherType(Ethernet.TYPE_ARP).setPayload(arpReply);
packetService.sendPacket(eth, new SwitchPort(sw.getDpid(), inPort.getPortNumber()));
}
}
}
}