Saurav Das
Committed by Gerrit Code Review

Adding more filtering objectives from the router application and handling them

in the corsa-pipeline driver

Change-Id: I3598b84ce25df97c10b33c6f1fdfc76421499046
......@@ -20,6 +20,7 @@ import com.google.common.collect.HashMultimap;
import com.google.common.collect.Maps;
import com.google.common.collect.Multimap;
import com.google.common.collect.Multiset;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Deactivate;
......@@ -30,14 +31,11 @@ import org.onlab.packet.Ip4Address;
import org.onlab.packet.Ip6Address;
import org.onlab.packet.IpAddress;
import org.onlab.packet.IpPrefix;
import org.onlab.packet.MacAddress;
import org.onlab.packet.VlanId;
import org.onlab.util.KryoNamespace;
import org.onosproject.config.NetworkConfigService;
import org.onosproject.core.ApplicationId;
import org.onosproject.core.CoreService;
import org.onosproject.net.DeviceId;
import org.onosproject.net.PortNumber;
import org.onosproject.net.flow.DefaultFlowRule;
import org.onosproject.net.flow.DefaultTrafficSelector;
import org.onosproject.net.flow.DefaultTrafficTreatment;
......@@ -60,7 +58,6 @@ import org.onosproject.net.group.GroupDescription;
import org.onosproject.net.group.GroupEvent;
import org.onosproject.net.group.GroupListener;
import org.onosproject.net.group.GroupService;
import org.onosproject.net.host.InterfaceIpAddress;
import org.onosproject.net.packet.PacketService;
import org.onosproject.routing.FibEntry;
import org.onosproject.routing.FibListener;
......@@ -75,7 +72,6 @@ import org.slf4j.LoggerFactory;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
......@@ -146,8 +142,6 @@ public class BgpRouter {
private IcmpHandler icmpHandler;
private InternalTableHandler provisionStaticTables = new InternalTableHandler();
private KryoNamespace appKryo = new KryoNamespace.Builder()
.register(IpAddress.Version.class)
.register(IpAddress.class)
......@@ -168,7 +162,7 @@ public class BgpRouter {
groupService.addListener(groupListener);
provisionStaticTables.provision(true, configService.getInterfaces());
processIntfFilters(true, configService.getInterfaces());
connectivityManager = new TunnellingConnectivityManager(appId,
configService,
......@@ -192,7 +186,7 @@ public class BgpRouter {
routingService.stop();
connectivityManager.stop();
icmpHandler.stop();
provisionStaticTables.provision(false, configService.getInterfaces());
processIntfFilters(false, configService.getInterfaces());
groupService.removeListener(groupListener);
......@@ -380,30 +374,20 @@ public class BgpRouter {
}
}
private class InternalTableHandler {
private Set<InterfaceIpAddress> intfIps = new HashSet<InterfaceIpAddress>();
private Set<MacAddress> intfMacs = new HashSet<MacAddress>();
private Map<PortNumber, VlanId> portVlanPair = Maps.newHashMap();
public void provision(boolean install, Set<Interface> intfs) {
getInterfaceConfig(intfs);
}
private void getInterfaceConfig(Set<Interface> intfs) {
private void processIntfFilters(boolean install, Set<Interface> intfs) {
log.info("Processing {} router interfaces", intfs.size());
for (Interface intf : intfs) {
FilteringObjective.Builder fob = DefaultFilteringObjective.builder();
flowObjectiveService.filter(deviceId, Collections.singletonList(
fob.addCondition(Criteria.matchEthDst(intf.mac()))
.fromApp(appId).permit().add()));
intfIps.addAll(intf.ipAddresses());
intfMacs.add(intf.mac());
portVlanPair.put(intf.connectPoint().port(), intf.vlan());
}
fob.withKey(Criteria.matchInPort(intf.connectPoint().port()))
.addCondition(Criteria.matchEthDst(intf.mac()))
.addCondition(Criteria.matchVlanId(intf.vlan()));
intf.ipAddresses().stream()
.forEach(ipaddr -> fob.addCondition(
Criteria.matchIPDst(ipaddr.subnetAddress())));
fob.permit().fromApp(appId);
flowObjectiveService.filter(deviceId,
Collections.singletonList(fob.add()));
}
}
private class InternalGroupListener implements GroupListener {
......
......@@ -83,39 +83,80 @@ public class OVSCorsaPipeline extends AbstractHandlerBehaviour implements Pipeli
@Override
public Future<Boolean> filter(Collection<FilteringObjective> filteringObjectives) {
Collection<Future<Boolean>> results =
Sets.newHashSet();
Collection<Future<Boolean>> results = Sets.newHashSet();
filteringObjectives.stream()
.filter(obj -> obj.type() == FilteringObjective.Type.PERMIT)
.forEach(obj -> obj.conditions()
.forEach(condition ->
results.add(processCondition(condition,
obj.op() == Objective.Operation.ADD,
obj.appId()))
));
.forEach(filtobj -> results.add(processFilter(filtobj,
filtobj.op() == Objective.Operation.ADD,
filtobj.appId()
)));
//TODO: return something more helpful/sensible in the future (no pun intended)
return results.iterator().next();
}
private Future<Boolean> processCondition(Criterion c, boolean install,
private Future<Boolean> processFilter(FilteringObjective filt, boolean install,
ApplicationId applicationId) {
SettableFuture<Boolean> result = SettableFuture.create();
// This driver only processes filtering criteria defined with switch
// ports as the key
Criteria.PortCriterion p = null;
if (!filt.key().equals(Criteria.dummy()) &&
filt.key().type() == Criterion.Type.IN_PORT) {
p = (Criteria.PortCriterion) filt.key();
} else {
log.warn("No key defined in filtering objective from app: {}. Not"
+ "processing filtering objective", applicationId);
return null;
}
// convert filtering conditions for switch-intfs into flowrules
FlowRuleOperations.Builder ops = FlowRuleOperations.builder();
for (Criterion c : filt.conditions()) {
if (c.type() == Criterion.Type.ETH_DST) {
Criteria.EthCriterion e = (Criteria.EthCriterion) c;
log.debug("adding rule for MAC: {}", e.mac());
TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
selector.matchEthDst(e.mac());
treatment.transition(FlowRule.Type.VLAN_MPLS);
FlowRule rule = new DefaultFlowRule(deviceId, selector.build(),
treatment.build(),
CONTROLLER_PRIORITY, applicationId, 0,
true, FlowRule.Type.FIRST);
FlowRuleOperations.Builder ops = FlowRuleOperations.builder();
CONTROLLER_PRIORITY, applicationId,
0, true, FlowRule.Type.FIRST);
ops = install ? ops.add(rule) : ops.remove(rule);
} else if (c.type() == Criterion.Type.VLAN_VID) {
Criteria.VlanIdCriterion v = (Criteria.VlanIdCriterion) c;
log.debug("adding rule for VLAN: {}", v.vlanId());
TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
selector.matchVlanId(v.vlanId());
selector.matchInPort(p.port());
treatment.transition(FlowRule.Type.ETHER);
treatment.deferred().popVlan();
FlowRule rule = new DefaultFlowRule(deviceId, selector.build(),
treatment.build(),
CONTROLLER_PRIORITY, applicationId,
0, true, FlowRule.Type.VLAN);
ops = install ? ops.add(rule) : ops.remove(rule);
} else if (c.type() == Criterion.Type.IPV4_DST) {
Criteria.IPCriterion ip = (Criteria.IPCriterion) c;
log.debug("adding rule for IP: {}", ip.ip());
TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
selector.matchEthType(Ethernet.TYPE_IPV4);
selector.matchIPDst(ip.ip());
treatment.transition(FlowRule.Type.ACL);
FlowRule rule = new DefaultFlowRule(deviceId, selector.build(),
treatment.build(), HIGHEST_PRIORITY, appId,
0, true, FlowRule.Type.IP);
ops = install ? ops.add(rule) : ops.remove(rule);
} else {
log.warn("Driver does not currently process filtering condition"
+ " of type: {}", c.type());
}
}
// apply filtering flow rules
flowRuleService.apply(ops.build(new FlowRuleOperationsContext() {
@Override
public void onSuccess(FlowRuleOperations ops) {
......@@ -129,7 +170,7 @@ public class OVSCorsaPipeline extends AbstractHandlerBehaviour implements Pipeli
log.info("Failed to provision default table for bgp router");
}
}));
}
return result;
}
......