Changed configuration file format to separate 'interfaces' from BGP peers. Also implemented procative paths for BGP traffic within the SDN domain
diff --git a/src/main/java/net/onrc/onos/ofcontroller/bgproute/BgpRoute.java b/src/main/java/net/onrc/onos/ofcontroller/bgproute/BgpRoute.java
index 4b6e328..d3bb598 100644
--- a/src/main/java/net/onrc/onos/ofcontroller/bgproute/BgpRoute.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/bgproute/BgpRoute.java
@@ -7,10 +7,8 @@
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
-import java.util.HashSet;
import java.util.List;
import java.util.Map;
-import java.util.Set;
import net.floodlightcontroller.core.IFloodlightProviderService;
import net.floodlightcontroller.core.IOFSwitch;
@@ -21,6 +19,7 @@
import net.floodlightcontroller.core.module.IFloodlightService;
import net.floodlightcontroller.devicemanager.IDeviceService;
import net.floodlightcontroller.packet.Ethernet;
+import net.floodlightcontroller.packet.IPv4;
import net.floodlightcontroller.restserver.IRestApiService;
import net.floodlightcontroller.topology.ITopologyListener;
import net.floodlightcontroller.topology.ITopologyService;
@@ -28,6 +27,7 @@
import net.onrc.onos.ofcontroller.linkdiscovery.ILinkDiscovery;
import net.onrc.onos.ofcontroller.linkdiscovery.ILinkDiscovery.LDUpdate;
import net.onrc.onos.ofcontroller.util.DataPath;
+import net.onrc.onos.ofcontroller.util.Dpid;
import net.onrc.onos.ofcontroller.util.FlowEntry;
import net.onrc.onos.ofcontroller.util.Port;
import net.onrc.onos.ofcontroller.util.SwitchPort;
@@ -66,9 +66,7 @@
protected static Ptree ptree;
protected String bgpdRestIp;
protected String routerId;
- protected String gatewaysFilename = "gateways.json";
-
- protected Set<InetAddress> routerIpAddresses;
+ protected String gatewaysFilename = "config.json";
//We need to identify our flows somehow. But like it says in LearningSwitch.java,
//the controller/OS should hand out cookie IDs to prevent conflicts.
@@ -77,12 +75,22 @@
protected final long L2_FWD_COOKIE = APP_COOKIE + 1;
//Cookie for flows in ingress switches that rewrite the MAC address
protected final long MAC_RW_COOKIE = APP_COOKIE + 2;
+ //Cookie for flows that setup BGP paths
+ protected final long BGP_COOKIE = APP_COOKIE + 3;
//Forwarding uses priority 0, and the mac rewrite entries in ingress switches
//need to be higher priority than this otherwise the rewrite may not get done
protected final short SDNIP_PRIORITY = 10;
+ protected final short BGP_PORT = 179;
+
+ //Configuration stuff
protected Map<String, GatewayRouter> gatewayRouters;
protected List<String> switches;
+ protected Map<String, Interface> interfaces;
+ protected List<BgpPeer> bgpPeers;
+ //protected long bgpdAttachmentDpid;
+ //protected short bgpdAttachmentPort;
+ protected SwitchPort bgpdAttachmentPoint;
//True when all switches have connected
protected volatile boolean switchesConnected = false;
@@ -98,10 +106,14 @@
gatewayRouters = config.getGateways();
switches = config.getSwitches();
+ interfaces = config.getInterfaces();
+ bgpPeers = config.getPeers();
- for (String sw : switches){
- log.debug("Switchjoin {}", sw);
- }
+ bgpdAttachmentPoint = new SwitchPort(
+ new Dpid(config.getBgpdAttachmentDpid()),
+ new Port(config.getBgpdAttachmentPort()));
+ //bgpdAttachmentDpid = config.getBgpdAttachmentDpid();
+ //bgpdAttachmentPort = config.getBgpdAttachmentPort();
} catch (JsonParseException e) {
log.error("Error in JSON file", e);
@@ -149,7 +161,7 @@
ptree = new Ptree(32);
- routerIpAddresses = new HashSet<InetAddress>();
+ //routerIpAddresses = new HashSet<InetAddress>();
// Register floodlight provider and REST handler.
floodlightProvider = context.getServiceImpl(IFloodlightProviderService.class);
@@ -407,9 +419,6 @@
match.setDataLayerSource(ingressRouter.getRouterMac().toBytes());
match.setWildcards(match.getWildcards() & ~OFMatch.OFPFW_DL_SRC);
-
- //match.setDataLayerDestination(ingressRouter.getSdnRouterMac().toBytes());
- //match.setWildcards(match.getWildcards() & ~OFMatch.OFPFW_DL_DST);
InetAddress address = null;
try {
@@ -429,7 +438,7 @@
//Set up output action
OFActionOutput outputAction = new OFActionOutput();
- outputAction.setMaxLength((short)0xffff); //TODO check what this is (and if needed for mac rewrite)
+ outputAction.setMaxLength((short)0xffff);
Port outputPort = shortestPath.flowEntries().get(0).outPort();
outputAction.setPort(outputPort.value());
@@ -502,9 +511,6 @@
match.setDataLayerSource(ingressRouter.getRouterMac().toBytes());
match.setWildcards(match.getWildcards() & ~OFMatch.OFPFW_DL_SRC);
- //match.setDataLayerDestination(ingressRouter.getSdnRouterMac().toBytes());
- //match.setWildcards(match.getWildcards() & ~OFMatch.OFPFW_DL_DST);
-
InetAddress address = null;
try {
address = InetAddress.getByAddress(node.key);
@@ -651,11 +657,137 @@
}
}
+ private void setupBgpPaths(){
+ for (BgpPeer bgpPeer : bgpPeers){
+ Interface peerInterface = interfaces.get(bgpPeer.getInterfaceName());
+
+ DataPath path = topoRouteService.getShortestPath(
+ peerInterface.getSwitchPort(), bgpdAttachmentPoint);
+
+ if (path == null){
+ log.debug("Unable to compute path for BGP traffic for {}",
+ bgpPeer.getIpAddress());
+ continue;
+ }
+
+ //Set up the flow mod
+ OFFlowMod fm =
+ (OFFlowMod) floodlightProvider.getOFMessageFactory()
+ .getMessage(OFType.FLOW_MOD);
+
+ OFActionOutput action = new OFActionOutput();
+ action.setMaxLength((short)0xffff);
+ List<OFAction> actions = new ArrayList<OFAction>();
+ actions.add(action);
+
+ fm.setIdleTimeout((short)0)
+ .setHardTimeout((short)0)
+ .setBufferId(OFPacketOut.BUFFER_ID_NONE)
+ .setCookie(BGP_COOKIE)
+ .setCommand(OFFlowMod.OFPFC_ADD)
+ .setPriority(SDNIP_PRIORITY)
+ .setActions(actions)
+ .setLengthU(OFFlowMod.MINIMUM_LENGTH+OFActionOutput.MINIMUM_LENGTH);
+
+ //Forward = gateway -> bgpd, reverse = bgpd -> gateway
+ OFMatch forwardMatchSrc = new OFMatch();
+
+
+ String interfaceCidrAddress = peerInterface.getIpAddress().getHostAddress()
+ + "/32";
+ String peerCidrAddress = bgpPeer.getIpAddress().getHostAddress()
+ + "/32";
+
+ //Common match fields
+ forwardMatchSrc.setDataLayerType(Ethernet.TYPE_IPv4);
+ //forwardMatch.setWildcards(forwardMatch.getWildcards() & ~OFMatch.OFPFW_DL_TYPE);
+ forwardMatchSrc.setNetworkProtocol(IPv4.PROTOCOL_TCP);
+ forwardMatchSrc.setTransportDestination(BGP_PORT);
+ forwardMatchSrc.setWildcards(forwardMatchSrc.getWildcards() & ~OFMatch.OFPFW_IN_PORT
+ & ~OFMatch.OFPFW_DL_TYPE & ~OFMatch.OFPFW_NW_PROTO);
+
+
+ OFMatch reverseMatchSrc = forwardMatchSrc.clone();
+
+ forwardMatchSrc.setFromCIDR(peerCidrAddress, OFMatch.STR_NW_SRC);
+ forwardMatchSrc.setFromCIDR(interfaceCidrAddress, OFMatch.STR_NW_DST);
+
+ OFMatch forwardMatchDst = forwardMatchSrc.clone();
+
+ forwardMatchSrc.setTransportSource(BGP_PORT);
+ forwardMatchSrc.setWildcards(forwardMatchSrc.getWildcards() & ~OFMatch.OFPFW_TP_SRC);
+ forwardMatchDst.setTransportDestination(BGP_PORT);
+ forwardMatchDst.setWildcards(forwardMatchDst.getWildcards() & ~OFMatch.OFPFW_TP_DST);
+
+ reverseMatchSrc.setFromCIDR(interfaceCidrAddress, OFMatch.STR_NW_SRC);
+ reverseMatchSrc.setFromCIDR(peerCidrAddress, OFMatch.STR_NW_DST);
+
+ OFMatch reverseMatchDst = reverseMatchSrc.clone();
+
+ reverseMatchSrc.setTransportSource(BGP_PORT);
+ reverseMatchSrc.setWildcards(forwardMatchSrc.getWildcards() & ~OFMatch.OFPFW_TP_SRC);
+ reverseMatchDst.setTransportDestination(BGP_PORT);
+ reverseMatchDst.setWildcards(forwardMatchDst.getWildcards() & ~OFMatch.OFPFW_TP_DST);
+
+ fm.setMatch(forwardMatchSrc);
+
+ for (FlowEntry flowEntry : path.flowEntries()){
+ OFFlowMod forwardFlowModSrc, forwardFlowModDst;
+ OFFlowMod reverseFlowModSrc, reverseFlowModDst;
+ try {
+ forwardFlowModSrc = fm.clone();
+ forwardFlowModDst = fm.clone();
+ reverseFlowModSrc = fm.clone();
+ reverseFlowModDst = fm.clone();
+ } catch (CloneNotSupportedException e) {
+ log.warn("Clone failed", e);
+ continue;
+ }
+
+ forwardMatchSrc.setInputPort(flowEntry.inPort().value());
+ forwardFlowModSrc.setMatch(forwardMatchSrc);
+ ((OFActionOutput)forwardFlowModSrc.getActions().get(0))
+ .setPort(flowEntry.outPort().value());
+
+ forwardMatchDst.setInputPort(flowEntry.inPort().value());
+ forwardFlowModDst.setMatch(forwardMatchDst);
+ ((OFActionOutput)forwardFlowModDst.getActions().get(0))
+ .setPort(flowEntry.outPort().value());
+
+ reverseMatchSrc.setInputPort(flowEntry.outPort().value());
+ reverseFlowModSrc.setMatch(reverseMatchSrc);
+ ((OFActionOutput)reverseFlowModSrc.getActions().get(0))
+ .setPort(flowEntry.inPort().value());
+
+ reverseMatchDst.setInputPort(flowEntry.outPort().value());
+ reverseFlowModDst.setMatch(reverseMatchDst);
+ ((OFActionOutput)reverseFlowModDst.getActions().get(0))
+ .setPort(flowEntry.inPort().value());
+
+ IOFSwitch sw = floodlightProvider.getSwitches().get(flowEntry.dpid().value());
+
+ //Hopefully the switch is there
+ List<OFMessage> msgList = new ArrayList<OFMessage>(2);
+ msgList.add(forwardFlowModSrc);
+ msgList.add(forwardFlowModDst);
+ msgList.add(reverseFlowModSrc);
+ msgList.add(reverseFlowModDst);
+
+ try {
+ sw.write(msgList, null);
+ sw.flush();
+ } catch (IOException e) {
+ log.error("Failure writing flow mod", e);
+ }
+ }
+ }
+ }
private void beginRouting(){
log.debug("Topology is now ready, beginning routing function");
+ setupBgpPaths();
- //traverse ptree and create flows for all routes
+ //Traverse ptree and create flows for all routes
for (PtreeNode node = ptree.begin(); node != null; node = ptree.next(node)){
if (node.rib != null){
prefixAdded(node);