Jonathan Hart

Create a formal interface between the RIB and FIB.

 * IntentSynchronizer implements a more generalized FibListener interface
 * Updates to the FIB are signalled with FibUpdate to any FibListeners
 * generateRouteIntent logic has been pushed down into the IntentSynchronizer

Change-Id: I6f0ccfd52ee4e16ce9974af5ee549d4ede6c2d0e
/*
* Copyright 2015 Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.sdnip;
import org.onlab.packet.IpAddress;
import org.onlab.packet.IpPrefix;
import org.onlab.packet.MacAddress;
/**
* An entry in the Forwarding Information Base (FIB).
*/
public class FibEntry {
private final IpPrefix prefix;
private final IpAddress nextHopIp;
private final MacAddress nextHopMac;
/**
* Creates a new FIB entry.
*
* @param prefix IP prefix of the FIB entry
* @param nextHopIp IP address of the next hop
* @param nextHopMac MAC address of the next hop
*/
public FibEntry(IpPrefix prefix, IpAddress nextHopIp, MacAddress nextHopMac) {
this.prefix = prefix;
this.nextHopIp = nextHopIp;
this.nextHopMac = nextHopMac;
}
/**
* Returns the IP prefix of the FIB entry.
*
* @return the IP prefix
*/
public IpPrefix prefix() {
return prefix;
}
/**
* Returns the IP address of the next hop.
*
* @return the IP address
*/
public IpAddress nextHopIp() {
return nextHopIp;
}
/**
* Returns the MAC address of the next hop.
*
* @return the MAC address
*/
public MacAddress nextHopMac() {
return nextHopMac;
}
}
/*
* Copyright 2015 Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.sdnip;
import java.util.Collection;
/**
* A component that is able to process Forwarding Information Base (FIB) updates.
*/
public interface FibListener {
/**
* Signals the FIB component of changes to the FIB.
*
* @param updates FIB updates of the UDPATE type
* @param withdraws FIB updates of the WITHDRAW type
*/
// TODO this interface should use only one collection when we have the new
// intent key API
void update(Collection<FibUpdate> updates, Collection<FibUpdate> withdraws);
}
/*
* Copyright 2015 Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.sdnip;
/**
* Represents a change to the Forwarding Information Base (FIB).
*/
public class FibUpdate {
/**
* Specifies the type of the FIB update.
*/
public enum Type {
/**
* The update contains a new or updated FIB entry for a prefix.
*/
UPDATE,
/**
* The update signals that a prefix should be removed from the FIB.
*/
DELETE
}
private final Type type;
private final FibEntry entry;
/**
* Creates a new FIB update.
*
* @param type type of the update
* @param entry FIB entry describing the update
*/
public FibUpdate(Type type, FibEntry entry) {
this.type = type;
this.entry = entry;
}
/**
* Returns the type of the update.
*
* @return update type
*/
public Type type() {
return type;
}
/**
* Returns the FIB entry which contains update information.
*
* @return the FIB entry
*/
public FibEntry entry() {
return entry;
}
}
......@@ -15,22 +15,19 @@
*/
package org.onosproject.sdnip;
import static com.google.common.base.Preconditions.checkArgument;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
import org.apache.commons.lang3.tuple.Pair;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import org.onlab.packet.Ethernet;
import org.onlab.packet.Ip4Address;
import org.onlab.packet.IpAddress;
import org.onlab.packet.IpPrefix;
import org.onlab.packet.MacAddress;
import org.onlab.packet.VlanId;
import org.onosproject.core.ApplicationId;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.flow.DefaultTrafficSelector;
import org.onosproject.net.flow.DefaultTrafficTreatment;
import org.onosproject.net.flow.TrafficSelector;
import org.onosproject.net.flow.TrafficTreatment;
import org.onosproject.net.flow.criteria.Criteria.IPCriterion;
import org.onosproject.net.flow.criteria.Criterion;
import org.onosproject.net.intent.Intent;
......@@ -39,16 +36,32 @@ import org.onosproject.net.intent.IntentService;
import org.onosproject.net.intent.IntentState;
import org.onosproject.net.intent.MultiPointToSinglePointIntent;
import org.onosproject.net.intent.PointToPointIntent;
import org.onosproject.sdnip.config.BgpPeer;
import org.onosproject.sdnip.config.Interface;
import org.onosproject.sdnip.config.SdnIpConfigurationService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
import static com.google.common.base.Preconditions.checkArgument;
/**
* Synchronizes intents between the in-memory intent store and the
* IntentService.
*/
public class IntentSynchronizer {
public class IntentSynchronizer implements FibListener {
private static final Logger log =
LoggerFactory.getLogger(IntentSynchronizer.class);
......@@ -65,18 +78,28 @@ public class IntentSynchronizer {
private volatile boolean isElectedLeader = false;
private volatile boolean isActivatedLeader = false;
private final SdnIpConfigurationService configService;
private final InterfaceService interfaceService;
/**
* Class constructor.
*
* @param appId the Application ID
* @param intentService the intent service
* @param configService the SDN-IP configuration service
* @param interfaceService the interface service
*/
IntentSynchronizer(ApplicationId appId, IntentService intentService) {
IntentSynchronizer(ApplicationId appId, IntentService intentService,
SdnIpConfigurationService configService,
InterfaceService interfaceService) {
this.appId = appId;
this.intentService = intentService;
peerIntents = new ConcurrentHashMap<>();
routeIntents = new ConcurrentHashMap<>();
this.configService = configService;
this.interfaceService = interfaceService;
bgpIntentsSynchronizerExecutor = Executors.newSingleThreadExecutor(
new ThreadFactoryBuilder()
.setNameFormat("sdnip-intents-synchronizer-%d").build());
......@@ -244,16 +267,85 @@ public class IntentSynchronizer {
}
/**
* Updates multi-point-to-single-point route intents.
* Generates a route intent for a prefix, the next hop IP address, and
* the next hop MAC address.
* <p/>
* This method will find the egress interface for the intent.
* Intent will match dst IP prefix and rewrite dst MAC address at all other
* border switches, then forward packets according to dst MAC address.
*
* @param submitIntents the intents to submit
* @param withdrawPrefixes the IPv4 or IPv6 matching prefixes for the
* intents to withdraw
* @param prefix IP prefix of the route to add
* @param nextHopIpAddress IP address of the next hop
* @param nextHopMacAddress MAC address of the next hop
* @return the generated intent, or null if no intent should be submitted
*/
void updateRouteIntents(
Collection<Pair<IpPrefix, MultiPointToSinglePointIntent>> submitIntents,
Collection<IpPrefix> withdrawPrefixes) {
private MultiPointToSinglePointIntent generateRouteIntent(
IpPrefix prefix,
IpAddress nextHopIpAddress,
MacAddress nextHopMacAddress) {
// Find the attachment point (egress interface) of the next hop
Interface egressInterface;
if (configService.getBgpPeers().containsKey(nextHopIpAddress)) {
// Route to a peer
log.debug("Route to peer {}", nextHopIpAddress);
BgpPeer peer =
configService.getBgpPeers().get(nextHopIpAddress);
egressInterface =
interfaceService.getInterface(peer.connectPoint());
} else {
// Route to non-peer
log.debug("Route to non-peer {}", nextHopIpAddress);
egressInterface =
interfaceService.getMatchingInterface(nextHopIpAddress);
if (egressInterface == null) {
log.warn("No outgoing interface found for {}",
nextHopIpAddress);
return null;
}
}
//
// Generate the intent itself
//
Set<ConnectPoint> ingressPorts = new HashSet<>();
ConnectPoint egressPort = egressInterface.connectPoint();
log.debug("Generating intent for prefix {}, next hop mac {}",
prefix, nextHopMacAddress);
for (Interface intf : interfaceService.getInterfaces()) {
if (!intf.connectPoint().equals(egressInterface.connectPoint())) {
ConnectPoint srcPort = intf.connectPoint();
ingressPorts.add(srcPort);
}
}
// Match the destination IP prefix at the first hop
TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
if (prefix.version() == Ip4Address.VERSION) {
selector.matchEthType(Ethernet.TYPE_IPV4);
} else {
selector.matchEthType(Ethernet.TYPE_IPV6);
}
selector.matchIPDst(prefix);
// Rewrite the destination MAC address
TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder()
.setEthDst(nextHopMacAddress);
if (!egressInterface.vlan().equals(VlanId.NONE)) {
treatment.setVlanId(egressInterface.vlan());
// If we set VLAN ID, we have to make sure a VLAN tag exists.
// TODO support no VLAN -> VLAN routing
selector.matchVlanId(VlanId.ANY);
}
return new MultiPointToSinglePointIntent(appId, selector.build(),
treatment.build(),
ingressPorts, egressPort);
}
@Override
public void update(Collection<FibUpdate> updates, Collection<FibUpdate> withdraws) {
//
// NOTE: Semantically, we MUST withdraw existing intents before
// submitting new intents.
......@@ -262,14 +354,19 @@ public class IntentSynchronizer {
MultiPointToSinglePointIntent intent;
log.debug("SDN-IP submitting intents = {} withdrawing = {}",
submitIntents.size(), withdrawPrefixes.size());
updates.size(), withdraws.size());
//
// Prepare the Intent batch operations for the intents to withdraw
//
IntentOperations.Builder withdrawBuilder =
IntentOperations.builder(appId);
for (IpPrefix prefix : withdrawPrefixes) {
for (FibUpdate withdraw : withdraws) {
checkArgument(withdraw.type() == FibUpdate.Type.DELETE,
"FibUpdate with wrong type in withdraws list");
IpPrefix prefix = withdraw.entry().prefix();
intent = routeIntents.remove(prefix);
if (intent == null) {
log.trace("SDN-IP No intent in routeIntents to delete " +
......@@ -287,10 +384,21 @@ public class IntentSynchronizer {
//
IntentOperations.Builder submitBuilder =
IntentOperations.builder(appId);
for (Pair<IpPrefix, MultiPointToSinglePointIntent> pair :
submitIntents) {
IpPrefix prefix = pair.getLeft();
intent = pair.getRight();
for (FibUpdate update : updates) {
checkArgument(update.type() == FibUpdate.Type.UPDATE,
"FibUpdate with wrong type in updates list");
IpPrefix prefix = update.entry().prefix();
intent = generateRouteIntent(prefix, update.entry().nextHopIp(),
update.entry().nextHopMac());
if (intent == null) {
// This preserves the old semantics - if an intent can't be
// generated, we don't do anything with that prefix. But
// perhaps we should withdraw the old intent anyway?
continue;
}
MultiPointToSinglePointIntent oldIntent =
routeIntents.put(prefix, intent);
if (isElectedLeader && isActivatedLeader) {
......
......@@ -15,11 +15,6 @@
*/
package org.onosproject.sdnip;
import static org.slf4j.LoggerFactory.getLogger;
import java.util.Collection;
import java.util.Dictionary;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Deactivate;
......@@ -44,6 +39,11 @@ import org.onosproject.sdnip.config.SdnIpConfigurationReader;
import org.osgi.service.component.ComponentContext;
import org.slf4j.Logger;
import java.util.Collection;
import java.util.Dictionary;
import static org.slf4j.LoggerFactory.getLogger;
/**
* Component for the SDN-IP peering application.
*/
......@@ -104,7 +104,8 @@ public class SdnIp implements SdnIpService {
InterfaceService interfaceService =
new HostToInterfaceAdaptor(hostService);
intentSynchronizer = new IntentSynchronizer(appId, intentService);
intentSynchronizer = new IntentSynchronizer(appId, intentService,
config, interfaceService);
intentSynchronizer.start();
peerConnectivity = new PeerConnectivityManager(appId,
......@@ -113,8 +114,7 @@ public class SdnIp implements SdnIpService {
interfaceService);
peerConnectivity.start();
router = new Router(appId, intentSynchronizer, config,
interfaceService, hostService);
router = new Router(intentSynchronizer, hostService);
router.start();
leadershipService.addListener(leadershipEventListener);
......
......@@ -15,23 +15,10 @@
*/
package org.onosproject.sdnip;
import static org.easymock.EasyMock.anyObject;
import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.expectLastCall;
import static org.easymock.EasyMock.replay;
import static org.easymock.EasyMock.reset;
import static org.easymock.EasyMock.verify;
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import com.google.common.collect.Sets;
import com.googlecode.concurrenttrees.radix.node.concrete.DefaultByteArrayNodeFactory;
import com.googlecode.concurrenttrees.radixinverted.ConcurrentInvertedRadixTree;
import com.googlecode.concurrenttrees.radixinverted.InvertedRadixTree;
import org.junit.Before;
import org.junit.Test;
import org.onlab.junit.TestUtils;
......@@ -67,10 +54,16 @@ import org.onosproject.net.intent.MultiPointToSinglePointIntent;
import org.onosproject.net.provider.ProviderId;
import org.onosproject.sdnip.config.Interface;
import com.google.common.collect.Sets;
import com.googlecode.concurrenttrees.radix.node.concrete.DefaultByteArrayNodeFactory;
import com.googlecode.concurrenttrees.radixinverted.ConcurrentInvertedRadixTree;
import com.googlecode.concurrenttrees.radixinverted.InvertedRadixTree;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import static org.easymock.EasyMock.*;
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
/**
* This class tests the intent synchronization function in the
......@@ -116,9 +109,9 @@ public class IntentSyncTest extends AbstractIntentTest {
setUpHostService();
intentService = createMock(IntentService.class);
intentSynchronizer = new IntentSynchronizer(APPID, intentService);
router = new Router(APPID, intentSynchronizer, null, interfaceService,
hostService);
intentSynchronizer = new IntentSynchronizer(APPID, intentService,
null, interfaceService);
router = new Router(intentSynchronizer, hostService);
}
/**
......
......@@ -15,19 +15,7 @@
*/
package org.onosproject.sdnip;
import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.replay;
import static org.easymock.EasyMock.reset;
import static org.easymock.EasyMock.verify;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import com.google.common.collect.Sets;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
......@@ -60,7 +48,14 @@ import org.onosproject.sdnip.config.Interface;
import org.onosproject.sdnip.config.InterfaceAddress;
import org.onosproject.sdnip.config.SdnIpConfigurationService;
import com.google.common.collect.Sets;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import static org.easymock.EasyMock.*;
/**
* Unit tests for PeerConnectivityManager.
......@@ -552,7 +547,9 @@ public class PeerConnectivityManagerTest extends AbstractIntentTest {
intentService = createMock(IntentService.class);
replay(intentService);
intentSynchronizer = new IntentSynchronizer(APPID, intentService);
intentSynchronizer = new IntentSynchronizer(APPID, intentService,
configInfoService,
interfaceService);
intentSynchronizer.leaderChanged(true);
TestUtils.setField(intentSynchronizer, "isActivatedLeader", true);
......
......@@ -15,22 +15,10 @@
*/
package org.onosproject.sdnip;
import static org.easymock.EasyMock.anyObject;
import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.replay;
import static org.easymock.EasyMock.reset;
import static org.easymock.EasyMock.verify;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import com.google.common.collect.Sets;
import com.googlecode.concurrenttrees.radix.node.concrete.DefaultByteArrayNodeFactory;
import com.googlecode.concurrenttrees.radixinverted.ConcurrentInvertedRadixTree;
import com.googlecode.concurrenttrees.radixinverted.InvertedRadixTree;
import org.junit.Before;
import org.junit.Test;
import org.onlab.junit.TestUtils;
......@@ -69,10 +57,16 @@ import org.onosproject.sdnip.config.BgpPeer;
import org.onosproject.sdnip.config.Interface;
import org.onosproject.sdnip.config.SdnIpConfigurationService;
import com.google.common.collect.Sets;
import com.googlecode.concurrenttrees.radix.node.concrete.DefaultByteArrayNodeFactory;
import com.googlecode.concurrenttrees.radixinverted.ConcurrentInvertedRadixTree;
import com.googlecode.concurrenttrees.radixinverted.InvertedRadixTree;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import static org.easymock.EasyMock.*;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
/**
* This class tests adding a route, updating a route, deleting a route, and
......@@ -122,9 +116,10 @@ public class RouterAsyncArpTest extends AbstractIntentTest {
hostService = createMock(HostService.class);
intentService = createMock(IntentService.class);
intentSynchronizer = new IntentSynchronizer(APPID, intentService);
router = new Router(APPID, intentSynchronizer,
sdnIpConfigService, interfaceService, hostService);
intentSynchronizer = new IntentSynchronizer(APPID, intentService,
sdnIpConfigService,
interfaceService);
router = new Router(intentSynchronizer, hostService);
internalHostListener = router.new InternalHostListener();
}
......
......@@ -15,22 +15,7 @@
*/
package org.onosproject.sdnip;
import static org.easymock.EasyMock.anyObject;
import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.expectLastCall;
import static org.easymock.EasyMock.replay;
import static org.easymock.EasyMock.reset;
import static org.easymock.EasyMock.verify;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import com.google.common.collect.Sets;
import org.junit.Before;
import org.junit.Test;
import org.onlab.junit.TestUtils;
......@@ -68,7 +53,15 @@ import org.onosproject.sdnip.config.BgpPeer;
import org.onosproject.sdnip.config.Interface;
import org.onosproject.sdnip.config.SdnIpConfigurationService;
import com.google.common.collect.Sets;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import static org.easymock.EasyMock.*;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
/**
* This class tests adding a route, updating a route, deleting a route,
......@@ -125,9 +118,10 @@ public class RouterTest extends AbstractIntentTest {
intentService = createMock(IntentService.class);
intentSynchronizer = new IntentSynchronizer(APPID, intentService);
router = new Router(APPID, intentSynchronizer, sdnIpConfigService,
interfaceService, hostService);
intentSynchronizer = new IntentSynchronizer(APPID, intentService,
sdnIpConfigService,
interfaceService);
router = new Router(intentSynchronizer, hostService);
}
/**
......
......@@ -15,26 +15,7 @@
*/
package org.onosproject.sdnip;
import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.expectLastCall;
import static org.easymock.EasyMock.replay;
import static org.easymock.EasyMock.reset;
import static org.easymock.EasyMock.verify;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.Set;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import com.google.common.collect.Sets;
import org.easymock.IAnswer;
import org.junit.Before;
import org.junit.Test;
......@@ -66,7 +47,20 @@ import org.onosproject.sdnip.config.BgpPeer;
import org.onosproject.sdnip.config.Interface;
import org.onosproject.sdnip.config.SdnIpConfigurationService;
import com.google.common.collect.Sets;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.Set;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import static org.easymock.EasyMock.*;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
/**
* Integration tests for the SDN-IP application.
......@@ -130,9 +124,10 @@ public class SdnIpTest extends AbstractIntentTest {
intentService = createMock(IntentService.class);
random = new Random();
intentSynchronizer = new IntentSynchronizer(APPID, intentService);
router = new Router(APPID, intentSynchronizer, sdnIpConfigService,
interfaceService, hostService);
intentSynchronizer = new IntentSynchronizer(APPID, intentService,
sdnIpConfigService,
interfaceService);
router = new Router(intentSynchronizer, hostService);
}
/**
......