blob: d710b1082c17ea9cf6f2e68459ceefdc8a502ee7 [file] [log] [blame]
package net.onrc.onos.apps.segmentrouting;
import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import net.floodlightcontroller.core.IFloodlightProviderService;
import net.floodlightcontroller.core.module.FloodlightModuleContext;
import net.floodlightcontroller.core.module.FloodlightModuleException;
import net.floodlightcontroller.core.module.IFloodlightModule;
import net.floodlightcontroller.core.module.IFloodlightService;
import net.onrc.onos.api.packet.IPacketService;
import net.onrc.onos.core.flowprogrammer.IFlowPusherService;
import net.onrc.onos.core.intent.Path;
import net.onrc.onos.core.main.config.IConfigInfoService;
import net.onrc.onos.core.packet.ARP;
import net.onrc.onos.core.topology.ITopologyListener;
import net.onrc.onos.core.topology.ITopologyService;
import net.onrc.onos.core.topology.LinkData;
import net.onrc.onos.core.topology.MutableTopology;
import net.onrc.onos.core.topology.Switch;
import net.onrc.onos.core.topology.TopologyEvents;
import org.projectfloodlight.openflow.types.IPv4Address;
import org.projectfloodlight.openflow.util.HexString;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class SegmentRoutingManager implements IFloodlightModule, ITopologyListener {
private static final Logger log = LoggerFactory
.getLogger(SegmentRoutingManager.class);
private ITopologyService topologyService;
private MutableTopology mutableTopology;
private List<ArpEntry> arpEntries;
@Override
public Collection<Class<? extends IFloodlightService>> getModuleServices() {
// TODO Auto-generated method stub
return null;
}
@Override
public Map<Class<? extends IFloodlightService>, IFloodlightService> getServiceImpls() {
// TODO Auto-generated method stub
return null;
}
@Override
public Collection<Class<? extends IFloodlightService>> getModuleDependencies() {
Collection<Class<? extends IFloodlightService>> l = new ArrayList<Class<? extends IFloodlightService>>();
l.add(IFloodlightProviderService.class);
l.add(IConfigInfoService.class);
l.add(ITopologyService.class);
l.add(IPacketService.class);
l.add(IFlowPusherService.class);
l.add(ITopologyService.class);
return l;
}
@Override
public void init(FloodlightModuleContext context) throws FloodlightModuleException {
ArpHandler aprHandler = new ArpHandler(context, this);
IcmpHandler icmpHandler = new IcmpHandler(context, this);
arpEntries = new ArrayList<ArpEntry>();
topologyService = context.getServiceImpl(ITopologyService.class);
mutableTopology = topologyService.getTopology();
topologyService.addListener(this, false);
}
@Override
public void startUp(FloodlightModuleContext context) throws FloodlightModuleException {
// TODO Auto-generated method stub
}
/**
* Update ARP Cache using ARP packets
* It is used to set destination MAC address to forward packets to known hosts.
* But, it will be replace with Host information of Topology service later.
*
* @param arp APR packets to use for updating ARP entries
*/
public void updateArpCache(ARP arp) {
ArpEntry arpEntry = new ArpEntry(arp.getSenderHardwareAddress(), arp.getSenderProtocolAddress());
// TODO: Need to check the duplication
arpEntries.add(arpEntry);
}
/**
* Get MAC address to known hosts
*
* @param destinationAddress IP address to get MAC address
* @return MAC Address to given IP address
*/
public byte[] getMacAddressFromIpAddress(int destinationAddress) {
// Can't we get the host IP address from the TopologyService ??
Iterator<ArpEntry> iterator = arpEntries.iterator();
IPv4Address ipAddress = IPv4Address.of(destinationAddress);
byte[] ipAddressInByte = ipAddress.getBytes();
while (iterator.hasNext() ) {
ArpEntry arpEntry = iterator.next();
byte[] address = arpEntry.targetIpAddress;
IPv4Address a = IPv4Address.of(address);
IPv4Address b = IPv4Address.of(ipAddressInByte);
if ( a.equals(b)) {
log.debug("Found an arp entry");
return arpEntry.targetMacAddress;
}
}
return null;
}
/**
* Temporary class to to keep ARP entry
*
*/
private class ArpEntry {
byte[] targetMacAddress;
byte[] targetIpAddress;
private ArpEntry(byte[] macAddress, byte[] ipAddress) {
this.targetMacAddress = macAddress;
this.targetIpAddress = ipAddress;
}
}
/**
* Topology events that have been generated.
*
* @param topologyEvents the generated Topology Events
* @see TopologyEvents
*/
public void topologyEvents(TopologyEvents topologyEvents)
{
/**
* Any Link update events, compute the ECMP path graph for all switch nodes
*/
if ((topologyEvents.getAddedLinkDataEntries() != null) ||
(topologyEvents.getRemovedLinkDataEntries() != null))
{
Iterable<Switch> switches= mutableTopology.getSwitches();
for (Switch sw : switches) {
ECMPShortestPathGraph ecmpSPG = new ECMPShortestPathGraph(sw);
log.debug("ECMPShortestPathGraph is computed for switch {}",
HexString.toHexString(sw.getDpid().value()));
for (Switch dstSw: mutableTopology.getSwitches()){
if (sw.getDpid().equals(dstSw.getDpid())){
continue;
}
ArrayList<Path> paths = ecmpSPG.getPath(dstSw);
log.debug("ECMPShortestPathGraph:Paths from switch {} to switch {} is {}",
HexString.toHexString(sw.getDpid().value()),
HexString.toHexString(dstSw.getDpid().value()), paths);
setSegmentRoutingRule(sw, paths);
}
}
}
}
/**
* Set segment routing rule to switches in the ECMP shortest path to the switch
*
* @param sw source switch
* @param paths ECMP path
*/
private void setSegmentRoutingRule(Switch sw, ArrayList<Path> paths) {
log.debug("Set routing infor for {} to .. ", sw.getDpid());
for (Path path: paths) {
for (Object obj : path.toArray()) {
LinkData link = (LinkData)obj;
log.debug(" ---- Set a rule in {} [Forward to {}] " , link.getSrc(), link.getDst().getDpid());
}
}
}
/**
* The function checks if given IP matches to the given subnet mask
*
* @param addr - subnet address to match
* @param addr1 - IP address to check
* @return true if the IP address matches to the subnet, otherwise false
*/
public 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)
String[] parts = addr.split("/");
String ip = parts[0];
int prefix;
if (parts.length < 2) {
prefix = 0;
} else {
prefix = Integer.parseInt(parts[1]);
}
Inet4Address a =null;
Inet4Address a1 =null;
try {
a = (Inet4Address) InetAddress.getByName(ip);
a1 = (Inet4Address) InetAddress.getByName(addr1);
} catch (UnknownHostException e){}
byte[] b = a.getAddress();
int ipInt = ((b[0] & 0xFF) << 24) |
((b[1] & 0xFF) << 16) |
((b[2] & 0xFF) << 8) |
((b[3] & 0xFF) << 0);
byte[] b1 = a1.getAddress();
int ipInt1 = ((b1[0] & 0xFF) << 24) |
((b1[1] & 0xFF) << 16) |
((b1[2] & 0xFF) << 8) |
((b1[3] & 0xFF) << 0);
int mask = ~((1 << (32 - prefix)) - 1);
if ((ipInt & mask) == (ipInt1 & mask)) {
return true;
}
else {
return false;
}
}
}