WIP: Started implementing static flows for corsa vanderweken pipeline.
Modified to not use Corsa driver by default.
Change-Id: If8df5769cf084346121d34bf4490f578e6b6f2d0
diff --git a/apps/bgprouter/src/main/java/org/onosproject/bgprouter/BgpRouter.java b/apps/bgprouter/src/main/java/org/onosproject/bgprouter/BgpRouter.java
index 317bf0d..62098b4 100644
--- a/apps/bgprouter/src/main/java/org/onosproject/bgprouter/BgpRouter.java
+++ b/apps/bgprouter/src/main/java/org/onosproject/bgprouter/BgpRouter.java
@@ -23,6 +23,7 @@
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.ReferenceCardinality;
import org.onlab.packet.Ethernet;
+import org.onlab.packet.MacAddress;
import org.onosproject.core.ApplicationId;
import org.onosproject.core.CoreService;
import org.onosproject.net.DeviceId;
@@ -30,6 +31,8 @@
import org.onosproject.net.flow.DefaultTrafficSelector;
import org.onosproject.net.flow.DefaultTrafficTreatment;
import org.onosproject.net.flow.FlowRule;
+import org.onosproject.net.flow.FlowRuleOperations;
+import org.onosproject.net.flow.FlowRuleOperationsContext;
import org.onosproject.net.flow.FlowRuleService;
import org.onosproject.net.flow.TrafficSelector;
import org.onosproject.net.flow.TrafficTreatment;
@@ -90,15 +93,19 @@
private final Multiset<NextHop> nextHops = ConcurrentHashMultiset.create();
private final Map<NextHop, NextHopGroupKey> groups = new HashMap<>();
- private DeviceId deviceId = DeviceId.deviceId("of:00000000000000a1"); // TODO config
+ private DeviceId deviceId = DeviceId.deviceId("of:0000000000000001"); // TODO config
private TunnellingConnectivityManager connectivityManager;
+ private InternalTableHandler provisionStaticTables = new InternalTableHandler();
+
@Activate
protected void activate() {
log.info("Bgp1Router started");
appId = coreService.registerApplication(BGP_ROUTER_APP);
+ provisionStaticTables.provision(true);
+
connectivityManager = new TunnellingConnectivityManager(appId,
configService,
packetService);
@@ -114,6 +121,7 @@
protected void deactivate() {
routingService.stop();
connectivityManager.stop();
+ provisionStaticTables.provision(false);
log.info("BgpRouter stopped");
}
@@ -224,4 +232,303 @@
BgpRouter.this.updateFibEntry(updates);
}
}
+
+ private class InternalTableHandler {
+
+ private static final int CONTROLLER_PRIORITY = 255;
+ private static final int DROP_PRIORITY = 0;
+
+
+ public void provision(boolean install) {
+
+ processTableZero(install);
+ processTableOne(install);
+ processTableTwo(install);
+ processTableThree(install);
+ processTableFive(install);
+ processTableSix(install);
+ processTableNine(install);
+
+ }
+
+ private void processTableZero(boolean install) {
+ TrafficSelector.Builder selector;
+ TrafficTreatment.Builder treatment;
+
+ selector = DefaultTrafficSelector.builder();
+ treatment = DefaultTrafficTreatment.builder();
+
+ selector.matchEthDst(MacAddress.BROADCAST);
+ treatment.transition(FlowRule.Type.VLAN_MPLS);
+
+ FlowRule rule = new DefaultFlowRule(deviceId, selector.build(),
+ treatment.build(), CONTROLLER_PRIORITY,
+ appId, 0, true);
+
+ FlowRuleOperations.Builder ops = FlowRuleOperations.builder();
+
+ ops = install ? ops.add(rule) : ops.remove(rule);
+
+
+ //Drop rule
+ selector = DefaultTrafficSelector.builder();
+ treatment = DefaultTrafficTreatment.builder();
+
+ treatment.drop();
+
+ rule = new DefaultFlowRule(deviceId, selector.build(),
+ treatment.build(), DROP_PRIORITY,
+ appId, 0, true, FlowRule.Type.VLAN_MPLS);
+
+ ops = install ? ops.add(rule) : ops.remove(rule);
+
+ flowService.apply(ops.build(new FlowRuleOperationsContext() {
+ @Override
+ public void onSuccess(FlowRuleOperations ops) {
+ log.info("Provisioned default table for bgp router");
+ }
+
+ @Override
+ public void onError(FlowRuleOperations ops) {
+ log.info("Failed to provision default table for bgp router");
+ }
+ }));
+
+ }
+
+ private void processTableOne(boolean install) {
+ TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
+ TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
+ FlowRuleOperations.Builder ops = FlowRuleOperations.builder();
+ FlowRule rule;
+
+ selector.matchEthType(Ethernet.TYPE_IPV4);
+ treatment.transition(FlowRule.Type.VLAN);
+
+ rule = new DefaultFlowRule(deviceId, selector.build(),
+ treatment.build(), CONTROLLER_PRIORITY,
+ appId, 0, true, FlowRule.Type.VLAN_MPLS);
+
+ ops = install ? ops.add(rule) : ops.remove(rule);
+
+ selector = DefaultTrafficSelector.builder();
+ treatment = DefaultTrafficTreatment.builder();
+
+ selector.matchEthType(Ethernet.TYPE_ARP);
+ treatment.transition(FlowRule.Type.VLAN);
+
+ rule = new DefaultFlowRule(deviceId, selector.build(),
+ treatment.build(), CONTROLLER_PRIORITY,
+ appId, 0, true, FlowRule.Type.VLAN_MPLS);
+
+ ops = install ? ops.add(rule) : ops.remove(rule);
+
+ selector = DefaultTrafficSelector.builder();
+ treatment = DefaultTrafficTreatment.builder();
+
+ selector.matchEthType(Ethernet.TYPE_VLAN);
+ treatment.transition(FlowRule.Type.VLAN);
+
+ rule = new DefaultFlowRule(deviceId, selector.build(),
+ treatment.build(), CONTROLLER_PRIORITY,
+ appId, 0, true, FlowRule.Type.VLAN_MPLS);
+
+ ops = install ? ops.add(rule) : ops.remove(rule);
+
+ //Drop rule
+ selector = DefaultTrafficSelector.builder();
+ treatment = DefaultTrafficTreatment.builder();
+
+ treatment.drop();
+
+ rule = new DefaultFlowRule(deviceId, selector.build(),
+ treatment.build(), DROP_PRIORITY,
+ appId, 0, true, FlowRule.Type.VLAN_MPLS);
+
+ ops = install ? ops.add(rule) : ops.remove(rule);
+
+ flowService.apply(ops.build(new FlowRuleOperationsContext() {
+ @Override
+ public void onSuccess(FlowRuleOperations ops) {
+ log.info("Provisioned vlan/mpls table for bgp router");
+ }
+
+ @Override
+ public void onError(FlowRuleOperations ops) {
+ log.info("Failed to provision vlan/mpls table for bgp router");
+ }
+ }));
+
+ }
+
+ private void processTableTwo(boolean install) {
+ TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
+ TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
+ FlowRuleOperations.Builder ops = FlowRuleOperations.builder();
+ FlowRule rule;
+
+ //Drop rule
+
+ treatment.drop();
+
+ rule = new DefaultFlowRule(deviceId, selector.build(),
+ treatment.build(), DROP_PRIORITY,
+ appId, 0, true, FlowRule.Type.VLAN);
+
+ ops = install ? ops.add(rule) : ops.remove(rule);
+
+ flowService.apply(ops.build(new FlowRuleOperationsContext() {
+ @Override
+ public void onSuccess(FlowRuleOperations ops) {
+ log.info("Provisioned vlan table for bgp router");
+ }
+
+ @Override
+ public void onError(FlowRuleOperations ops) {
+ log.info("Failed to provision vlan table for bgp router");
+ }
+ }));
+ }
+
+
+
+ private void processTableThree(boolean install) {
+ TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
+ TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
+ FlowRuleOperations.Builder ops = FlowRuleOperations.builder();
+ FlowRule rule;
+
+ selector.matchEthType(Ethernet.TYPE_ARP);
+ treatment.punt();
+
+ rule = new DefaultFlowRule(deviceId, selector.build(),
+ treatment.build(), CONTROLLER_PRIORITY,
+ appId, 0, true, FlowRule.Type.ETHER);
+
+ ops = install ? ops.add(rule) : ops.remove(rule);
+
+ selector = DefaultTrafficSelector.builder();
+ treatment = DefaultTrafficTreatment.builder();
+
+ selector.matchEthType(Ethernet.TYPE_IPV4);
+ treatment.transition(FlowRule.Type.COS);
+
+ rule = new DefaultFlowRule(deviceId, selector.build(),
+ treatment.build(), CONTROLLER_PRIORITY,
+ appId, 0, true, FlowRule.Type.ETHER);
+
+ ops = install ? ops.add(rule) : ops.remove(rule);
+
+ //Drop rule
+ selector = DefaultTrafficSelector.builder();
+ treatment = DefaultTrafficTreatment.builder();
+
+ treatment.drop();
+
+ rule = new DefaultFlowRule(deviceId, selector.build(),
+ treatment.build(), DROP_PRIORITY,
+ appId, 0, true, FlowRule.Type.VLAN_MPLS);
+
+ ops = install ? ops.add(rule) : ops.remove(rule);
+
+ flowService.apply(ops.build(new FlowRuleOperationsContext() {
+ @Override
+ public void onSuccess(FlowRuleOperations ops) {
+ log.info("Provisioned ether table for bgp router");
+ }
+
+ @Override
+ public void onError(FlowRuleOperations ops) {
+ log.info("Failed to provision ether table for bgp router");
+ }
+ }));
+
+
+ }
+
+ private void processTableFive(boolean install) {
+ TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
+ TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
+ FlowRuleOperations.Builder ops = FlowRuleOperations.builder();
+ FlowRule rule;
+
+ treatment.transition(FlowRule.Type.IP);
+
+ rule = new DefaultFlowRule(deviceId, selector.build(),
+ treatment.build(), DROP_PRIORITY,
+ appId, 0, true, FlowRule.Type.COS);
+
+ ops = install ? ops.add(rule) : ops.remove(rule);
+
+ flowService.apply(ops.build(new FlowRuleOperationsContext() {
+ @Override
+ public void onSuccess(FlowRuleOperations ops) {
+ log.info("Provisioned cos table for bgp router");
+ }
+
+ @Override
+ public void onError(FlowRuleOperations ops) {
+ log.info("Failed to provision cos table for bgp router");
+ }
+ }));
+
+ }
+
+ private void processTableSix(boolean install) {
+ TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
+ TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
+ FlowRuleOperations.Builder ops = FlowRuleOperations.builder();
+ FlowRule rule;
+
+ //Drop rule
+
+ treatment.drop();
+
+ rule = new DefaultFlowRule(deviceId, selector.build(),
+ treatment.build(), DROP_PRIORITY,
+ appId, 0, true, FlowRule.Type.IP);
+
+ ops = install ? ops.add(rule) : ops.remove(rule);
+
+ flowService.apply(ops.build(new FlowRuleOperationsContext() {
+ @Override
+ public void onSuccess(FlowRuleOperations ops) {
+ log.info("Provisioned FIB table for bgp router");
+ }
+
+ @Override
+ public void onError(FlowRuleOperations ops) {
+ log.info("Failed to provision FIB table for bgp router");
+ }
+ }));
+ }
+
+ private void processTableNine(boolean install) {
+ TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
+ TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
+ FlowRuleOperations.Builder ops = FlowRuleOperations.builder();
+ FlowRule rule;
+
+ treatment.punt();
+
+ rule = new DefaultFlowRule(deviceId, selector.build(),
+ treatment.build(), CONTROLLER_PRIORITY,
+ appId, 0, true, FlowRule.Type.ACL);
+
+ ops = install ? ops.add(rule) : ops.remove(rule);
+
+ flowService.apply(ops.build(new FlowRuleOperationsContext() {
+ @Override
+ public void onSuccess(FlowRuleOperations ops) {
+ log.info("Provisioned Local table for bgp router");
+ }
+
+ @Override
+ public void onError(FlowRuleOperations ops) {
+ log.info("Failed to provision Local table for bgp router");
+ }
+ }));
+ }
+
+ }
}
diff --git a/core/api/src/main/java/org/onosproject/net/flow/DefaultTrafficTreatment.java b/core/api/src/main/java/org/onosproject/net/flow/DefaultTrafficTreatment.java
index de5c328..a8880b0 100644
--- a/core/api/src/main/java/org/onosproject/net/flow/DefaultTrafficTreatment.java
+++ b/core/api/src/main/java/org/onosproject/net/flow/DefaultTrafficTreatment.java
@@ -134,6 +134,7 @@
case DROP:
drop = true;
break;
+ case TABLE:
case OUTPUT:
outputs.add(instruction);
break;
diff --git a/core/store/dist/src/main/java/org/onosproject/store/group/impl/DistributedGroupStore.java b/core/store/dist/src/main/java/org/onosproject/store/group/impl/DistributedGroupStore.java
new file mode 100644
index 0000000..c914784
--- /dev/null
+++ b/core/store/dist/src/main/java/org/onosproject/store/group/impl/DistributedGroupStore.java
@@ -0,0 +1,555 @@
+/*
+ * 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.store.group.impl;
+
+import static org.apache.commons.lang3.concurrent.ConcurrentUtils.createIfAbsentUnchecked;
+import static org.slf4j.LoggerFactory.getLogger;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.apache.felix.scr.annotations.Activate;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Deactivate;
+import org.apache.felix.scr.annotations.Service;
+import org.onlab.util.NewConcurrentHashMap;
+import org.onosproject.core.DefaultGroupId;
+import org.onosproject.core.GroupId;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.group.DefaultGroup;
+import org.onosproject.net.group.DefaultGroupDescription;
+import org.onosproject.net.group.Group;
+import org.onosproject.net.group.Group.GroupState;
+import org.onosproject.net.group.GroupBucket;
+import org.onosproject.net.group.GroupBuckets;
+import org.onosproject.net.group.GroupDescription;
+import org.onosproject.net.group.GroupEvent;
+import org.onosproject.net.group.GroupEvent.Type;
+import org.onosproject.net.group.GroupKey;
+import org.onosproject.net.group.GroupOperation;
+import org.onosproject.net.group.GroupStore;
+import org.onosproject.net.group.GroupStoreDelegate;
+import org.onosproject.net.group.StoredGroupEntry;
+import org.onosproject.store.AbstractStore;
+import org.slf4j.Logger;
+
+import com.google.common.base.Function;
+import com.google.common.collect.FluentIterable;
+
+/**
+ * Manages inventory of group entries using trivial in-memory implementation.
+ */
+@Component(immediate = true)
+@Service
+public class DistributedGroupStore
+ extends AbstractStore<GroupEvent, GroupStoreDelegate>
+ implements GroupStore {
+
+ private final Logger log = getLogger(getClass());
+
+ private final int dummyId = 0xffffffff;
+ private final GroupId dummyGroupId = new DefaultGroupId(dummyId);
+
+ // inner Map is per device group table
+ private final ConcurrentMap<DeviceId, ConcurrentMap<GroupKey, StoredGroupEntry>>
+ groupEntriesByKey = new ConcurrentHashMap<>();
+ private final ConcurrentMap<DeviceId, ConcurrentMap<GroupId, StoredGroupEntry>>
+ groupEntriesById = new ConcurrentHashMap<>();
+ private final ConcurrentMap<DeviceId, ConcurrentMap<GroupKey, StoredGroupEntry>>
+ pendingGroupEntriesByKey = new ConcurrentHashMap<>();
+ private final ConcurrentMap<DeviceId, ConcurrentMap<GroupId, Group>>
+ extraneousGroupEntriesById = new ConcurrentHashMap<>();
+
+ private final HashMap<DeviceId, Boolean> deviceAuditStatus =
+ new HashMap<DeviceId, Boolean>();
+
+ private final AtomicInteger groupIdGen = new AtomicInteger();
+
+ @Activate
+ public void activate() {
+ log.info("Started");
+ }
+
+ @Deactivate
+ public void deactivate() {
+ groupEntriesByKey.clear();
+ groupEntriesById.clear();
+ log.info("Stopped");
+ }
+
+ private static NewConcurrentHashMap<GroupKey, StoredGroupEntry>
+ lazyEmptyGroupKeyTable() {
+ return NewConcurrentHashMap.<GroupKey, StoredGroupEntry>ifNeeded();
+ }
+
+ private static NewConcurrentHashMap<GroupId, StoredGroupEntry>
+ lazyEmptyGroupIdTable() {
+ return NewConcurrentHashMap.<GroupId, StoredGroupEntry>ifNeeded();
+ }
+
+ private static NewConcurrentHashMap<GroupKey, StoredGroupEntry>
+ lazyEmptyPendingGroupKeyTable() {
+ return NewConcurrentHashMap.<GroupKey, StoredGroupEntry>ifNeeded();
+ }
+
+ private static NewConcurrentHashMap<GroupId, Group>
+ lazyEmptyExtraneousGroupIdTable() {
+ return NewConcurrentHashMap.<GroupId, Group>ifNeeded();
+ }
+
+ /**
+ * Returns the group key table for specified device.
+ *
+ * @param deviceId identifier of the device
+ * @return Map representing group key table of given device.
+ */
+ private ConcurrentMap<GroupKey, StoredGroupEntry> getGroupKeyTable(DeviceId deviceId) {
+ return createIfAbsentUnchecked(groupEntriesByKey,
+ deviceId, lazyEmptyGroupKeyTable());
+ }
+
+ /**
+ * Returns the group id table for specified device.
+ *
+ * @param deviceId identifier of the device
+ * @return Map representing group key table of given device.
+ */
+ private ConcurrentMap<GroupId, StoredGroupEntry> getGroupIdTable(DeviceId deviceId) {
+ return createIfAbsentUnchecked(groupEntriesById,
+ deviceId, lazyEmptyGroupIdTable());
+ }
+
+ /**
+ * Returns the pending group key table for specified device.
+ *
+ * @param deviceId identifier of the device
+ * @return Map representing group key table of given device.
+ */
+ private ConcurrentMap<GroupKey, StoredGroupEntry>
+ getPendingGroupKeyTable(DeviceId deviceId) {
+ return createIfAbsentUnchecked(pendingGroupEntriesByKey,
+ deviceId, lazyEmptyPendingGroupKeyTable());
+ }
+
+ /**
+ * Returns the extraneous group id table for specified device.
+ *
+ * @param deviceId identifier of the device
+ * @return Map representing group key table of given device.
+ */
+ private ConcurrentMap<GroupId, Group>
+ getExtraneousGroupIdTable(DeviceId deviceId) {
+ return createIfAbsentUnchecked(extraneousGroupEntriesById,
+ deviceId,
+ lazyEmptyExtraneousGroupIdTable());
+ }
+
+ /**
+ * Returns the number of groups for the specified device in the store.
+ *
+ * @return number of groups for the specified device
+ */
+ @Override
+ public int getGroupCount(DeviceId deviceId) {
+ return (groupEntriesByKey.get(deviceId) != null) ?
+ groupEntriesByKey.get(deviceId).size() : 0;
+ }
+
+ /**
+ * Returns the groups associated with a device.
+ *
+ * @param deviceId the device ID
+ *
+ * @return the group entries
+ */
+ @Override
+ public Iterable<Group> getGroups(DeviceId deviceId) {
+ // flatten and make iterator unmodifiable
+ return FluentIterable.from(getGroupKeyTable(deviceId).values())
+ .transform(
+ new Function<StoredGroupEntry, Group>() {
+
+ @Override
+ public Group apply(
+ StoredGroupEntry input) {
+ return input;
+ }
+ });
+ }
+
+ /**
+ * Returns the stored group entry.
+ *
+ * @param deviceId the device ID
+ * @param appCookie the group key
+ *
+ * @return a group associated with the key
+ */
+ @Override
+ public Group getGroup(DeviceId deviceId, GroupKey appCookie) {
+ return (groupEntriesByKey.get(deviceId) != null) ?
+ groupEntriesByKey.get(deviceId).get(appCookie) :
+ null;
+ }
+
+ private int getFreeGroupIdValue(DeviceId deviceId) {
+ int freeId = groupIdGen.incrementAndGet();
+
+ while (true) {
+ Group existing = (
+ groupEntriesById.get(deviceId) != null) ?
+ groupEntriesById.get(deviceId).get(new DefaultGroupId(freeId)) :
+ null;
+ if (existing == null) {
+ existing = (
+ extraneousGroupEntriesById.get(deviceId) != null) ?
+ extraneousGroupEntriesById.get(deviceId).
+ get(new DefaultGroupId(freeId)) :
+ null;
+ }
+ if (existing != null) {
+ freeId = groupIdGen.incrementAndGet();
+ } else {
+ break;
+ }
+ }
+ return freeId;
+ }
+
+ /**
+ * Stores a new group entry using the information from group description.
+ *
+ * @param groupDesc group description to be used to create group entry
+ */
+ @Override
+ public void storeGroupDescription(GroupDescription groupDesc) {
+ // Check if a group is existing with the same key
+ if (getGroup(groupDesc.deviceId(), groupDesc.appCookie()) != null) {
+ return;
+ }
+
+ if (deviceAuditStatus.get(groupDesc.deviceId()) == null) {
+ // Device group audit has not completed yet
+ // Add this group description to pending group key table
+ // Create a group entry object with Dummy Group ID
+ StoredGroupEntry group = new DefaultGroup(dummyGroupId, groupDesc);
+ group.setState(GroupState.WAITING_AUDIT_COMPLETE);
+ ConcurrentMap<GroupKey, StoredGroupEntry> pendingKeyTable =
+ getPendingGroupKeyTable(groupDesc.deviceId());
+ pendingKeyTable.put(groupDesc.appCookie(), group);
+ return;
+ }
+
+ storeGroupDescriptionInternal(groupDesc);
+ }
+
+ private void storeGroupDescriptionInternal(GroupDescription groupDesc) {
+ // Check if a group is existing with the same key
+ if (getGroup(groupDesc.deviceId(), groupDesc.appCookie()) != null) {
+ return;
+ }
+
+ // Get a new group identifier
+ GroupId id = new DefaultGroupId(getFreeGroupIdValue(groupDesc.deviceId()));
+ // Create a group entry object
+ StoredGroupEntry group = new DefaultGroup(id, groupDesc);
+ // Insert the newly created group entry into concurrent key and id maps
+ ConcurrentMap<GroupKey, StoredGroupEntry> keyTable =
+ getGroupKeyTable(groupDesc.deviceId());
+ keyTable.put(groupDesc.appCookie(), group);
+ ConcurrentMap<GroupId, StoredGroupEntry> idTable =
+ getGroupIdTable(groupDesc.deviceId());
+ idTable.put(id, group);
+ notifyDelegate(new GroupEvent(GroupEvent.Type.GROUP_ADD_REQUESTED,
+ group));
+ }
+
+ /**
+ * Updates the existing group entry with the information
+ * from group description.
+ *
+ * @param deviceId the device ID
+ * @param oldAppCookie the current group key
+ * @param type update type
+ * @param newBuckets group buckets for updates
+ * @param newAppCookie optional new group key
+ */
+ @Override
+ public void updateGroupDescription(DeviceId deviceId,
+ GroupKey oldAppCookie,
+ UpdateType type,
+ GroupBuckets newBuckets,
+ GroupKey newAppCookie) {
+ // Check if a group is existing with the provided key
+ Group oldGroup = getGroup(deviceId, oldAppCookie);
+ if (oldGroup == null) {
+ return;
+ }
+
+ List<GroupBucket> newBucketList = getUpdatedBucketList(oldGroup,
+ type,
+ newBuckets);
+ if (newBucketList != null) {
+ // Create a new group object from the old group
+ GroupBuckets updatedBuckets = new GroupBuckets(newBucketList);
+ GroupKey newCookie = (newAppCookie != null) ? newAppCookie : oldAppCookie;
+ GroupDescription updatedGroupDesc = new DefaultGroupDescription(
+ oldGroup.deviceId(),
+ oldGroup.type(),
+ updatedBuckets,
+ newCookie,
+ oldGroup.appId());
+ StoredGroupEntry newGroup = new DefaultGroup(oldGroup.id(),
+ updatedGroupDesc);
+ newGroup.setState(GroupState.PENDING_UPDATE);
+ newGroup.setLife(oldGroup.life());
+ newGroup.setPackets(oldGroup.packets());
+ newGroup.setBytes(oldGroup.bytes());
+ // Remove the old entry from maps and add new entry using new key
+ ConcurrentMap<GroupKey, StoredGroupEntry> keyTable =
+ getGroupKeyTable(oldGroup.deviceId());
+ ConcurrentMap<GroupId, StoredGroupEntry> idTable =
+ getGroupIdTable(oldGroup.deviceId());
+ keyTable.remove(oldGroup.appCookie());
+ idTable.remove(oldGroup.id());
+ keyTable.put(newGroup.appCookie(), newGroup);
+ idTable.put(newGroup.id(), newGroup);
+ notifyDelegate(new GroupEvent(Type.GROUP_UPDATE_REQUESTED, newGroup));
+ }
+ }
+
+ private List<GroupBucket> getUpdatedBucketList(Group oldGroup,
+ UpdateType type,
+ GroupBuckets buckets) {
+ GroupBuckets oldBuckets = oldGroup.buckets();
+ List<GroupBucket> newBucketList = new ArrayList<GroupBucket>(
+ oldBuckets.buckets());
+ boolean groupDescUpdated = false;
+
+ if (type == UpdateType.ADD) {
+ // Check if the any of the new buckets are part of
+ // the old bucket list
+ for (GroupBucket addBucket:buckets.buckets()) {
+ if (!newBucketList.contains(addBucket)) {
+ newBucketList.add(addBucket);
+ groupDescUpdated = true;
+ }
+ }
+ } else if (type == UpdateType.REMOVE) {
+ // Check if the to be removed buckets are part of the
+ // old bucket list
+ for (GroupBucket removeBucket:buckets.buckets()) {
+ if (newBucketList.contains(removeBucket)) {
+ newBucketList.remove(removeBucket);
+ groupDescUpdated = true;
+ }
+ }
+ }
+
+ if (groupDescUpdated) {
+ return newBucketList;
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Triggers deleting the existing group entry.
+ *
+ * @param deviceId the device ID
+ * @param appCookie the group key
+ */
+ @Override
+ public void deleteGroupDescription(DeviceId deviceId,
+ GroupKey appCookie) {
+ // Check if a group is existing with the provided key
+ StoredGroupEntry existing = (groupEntriesByKey.get(deviceId) != null) ?
+ groupEntriesByKey.get(deviceId).get(appCookie) :
+ null;
+ if (existing == null) {
+ return;
+ }
+
+ synchronized (existing) {
+ existing.setState(GroupState.PENDING_DELETE);
+ }
+ notifyDelegate(new GroupEvent(Type.GROUP_REMOVE_REQUESTED, existing));
+ }
+
+ /**
+ * Stores a new group entry, or updates an existing entry.
+ *
+ * @param group group entry
+ */
+ @Override
+ public void addOrUpdateGroupEntry(Group group) {
+ // check if this new entry is an update to an existing entry
+ StoredGroupEntry existing = (groupEntriesById.get(
+ group.deviceId()) != null) ?
+ groupEntriesById.get(group.deviceId()).get(group.id()) :
+ null;
+ GroupEvent event = null;
+
+ if (existing != null) {
+ synchronized (existing) {
+ existing.setLife(group.life());
+ existing.setPackets(group.packets());
+ existing.setBytes(group.bytes());
+ if (existing.state() == GroupState.PENDING_ADD) {
+ existing.setState(GroupState.ADDED);
+ event = new GroupEvent(Type.GROUP_ADDED, existing);
+ } else {
+ if (existing.state() == GroupState.PENDING_UPDATE) {
+ existing.setState(GroupState.PENDING_UPDATE);
+ }
+ event = new GroupEvent(Type.GROUP_UPDATED, existing);
+ }
+ }
+ }
+
+ if (event != null) {
+ notifyDelegate(event);
+ }
+ }
+
+ /**
+ * Removes the group entry from store.
+ *
+ * @param group group entry
+ */
+ @Override
+ public void removeGroupEntry(Group group) {
+ StoredGroupEntry existing = (groupEntriesById.get(
+ group.deviceId()) != null) ?
+ groupEntriesById.get(group.deviceId()).get(group.id()) :
+ null;
+
+ if (existing != null) {
+ ConcurrentMap<GroupKey, StoredGroupEntry> keyTable =
+ getGroupKeyTable(existing.deviceId());
+ ConcurrentMap<GroupId, StoredGroupEntry> idTable =
+ getGroupIdTable(existing.deviceId());
+ idTable.remove(existing.id());
+ keyTable.remove(existing.appCookie());
+ notifyDelegate(new GroupEvent(Type.GROUP_REMOVED, existing));
+ }
+ }
+
+ @Override
+ public void deviceInitialAuditCompleted(DeviceId deviceId,
+ boolean completed) {
+ synchronized (deviceAuditStatus) {
+ if (completed) {
+ log.debug("deviceInitialAuditCompleted: AUDIT "
+ + "completed for device {}", deviceId);
+ deviceAuditStatus.put(deviceId, true);
+ // Execute all pending group requests
+ ConcurrentMap<GroupKey, StoredGroupEntry> pendingGroupRequests =
+ getPendingGroupKeyTable(deviceId);
+ for (Group group:pendingGroupRequests.values()) {
+ GroupDescription tmp = new DefaultGroupDescription(
+ group.deviceId(),
+ group.type(),
+ group.buckets(),
+ group.appCookie(),
+ group.appId());
+ storeGroupDescriptionInternal(tmp);
+ }
+ getPendingGroupKeyTable(deviceId).clear();
+ } else {
+ if (deviceAuditStatus.get(deviceId)) {
+ log.debug("deviceInitialAuditCompleted: Clearing AUDIT "
+ + "status for device {}", deviceId);
+ deviceAuditStatus.put(deviceId, false);
+ }
+ }
+ }
+ }
+
+ @Override
+ public boolean deviceInitialAuditStatus(DeviceId deviceId) {
+ synchronized (deviceAuditStatus) {
+ return (deviceAuditStatus.get(deviceId) != null)
+ ? deviceAuditStatus.get(deviceId) : false;
+ }
+ }
+
+ @Override
+ public void groupOperationFailed(DeviceId deviceId, GroupOperation operation) {
+
+ StoredGroupEntry existing = (groupEntriesById.get(
+ deviceId) != null) ?
+ groupEntriesById.get(deviceId).get(operation.groupId()) :
+ null;
+
+ if (existing == null) {
+ log.warn("No group entry with ID {} found ", operation.groupId());
+ return;
+ }
+
+ switch (operation.opType()) {
+ case ADD:
+ notifyDelegate(new GroupEvent(Type.GROUP_ADD_FAILED, existing));
+ break;
+ case MODIFY:
+ notifyDelegate(new GroupEvent(Type.GROUP_UPDATE_FAILED, existing));
+ break;
+ case DELETE:
+ notifyDelegate(new GroupEvent(Type.GROUP_REMOVE_FAILED, existing));
+ break;
+ default:
+ log.warn("Unknown group operation type {}", operation.opType());
+ }
+
+ ConcurrentMap<GroupKey, StoredGroupEntry> keyTable =
+ getGroupKeyTable(existing.deviceId());
+ ConcurrentMap<GroupId, StoredGroupEntry> idTable =
+ getGroupIdTable(existing.deviceId());
+ idTable.remove(existing.id());
+ keyTable.remove(existing.appCookie());
+ }
+
+ @Override
+ public void addOrUpdateExtraneousGroupEntry(Group group) {
+ ConcurrentMap<GroupId, Group> extraneousIdTable =
+ getExtraneousGroupIdTable(group.deviceId());
+ extraneousIdTable.put(group.id(), group);
+ // Check the reference counter
+ if (group.referenceCount() == 0) {
+ notifyDelegate(new GroupEvent(Type.GROUP_REMOVE_REQUESTED, group));
+ }
+ }
+
+ @Override
+ public void removeExtraneousGroupEntry(Group group) {
+ ConcurrentMap<GroupId, Group> extraneousIdTable =
+ getExtraneousGroupIdTable(group.deviceId());
+ extraneousIdTable.remove(group.id());
+ }
+
+ @Override
+ public Iterable<Group> getExtraneousGroups(DeviceId deviceId) {
+ // flatten and make iterator unmodifiable
+ return FluentIterable.from(
+ getExtraneousGroupIdTable(deviceId).values());
+ }
+
+
+}
diff --git a/openflow/drivers/src/main/java/org/onosproject/openflow/drivers/OFCorsaSwitchDriver.java b/openflow/drivers/src/main/java/org/onosproject/openflow/drivers/OFCorsaSwitchDriver.java
index f07725f..62eceda 100644
--- a/openflow/drivers/src/main/java/org/onosproject/openflow/drivers/OFCorsaSwitchDriver.java
+++ b/openflow/drivers/src/main/java/org/onosproject/openflow/drivers/OFCorsaSwitchDriver.java
@@ -17,7 +17,6 @@
import com.google.common.collect.Lists;
import org.onosproject.openflow.controller.Dpid;
-import org.onosproject.openflow.controller.RoleState;
import org.onosproject.openflow.controller.driver.AbstractOpenFlowSwitch;
import org.projectfloodlight.openflow.protocol.OFDescStatsReply;
import org.projectfloodlight.openflow.protocol.OFFlowMod;
@@ -43,8 +42,6 @@
private static final int FIB_TABLE = 6;
private static final int LOCAL_TABLE = 9;
-
-
OFCorsaSwitchDriver(Dpid dpid, OFDescStatsReply desc) {
super(dpid);
@@ -58,10 +55,7 @@
@Override
public void write(List<OFMessage> msgs) {
- if (role == RoleState.MASTER) {
channel.write(msgs);
- }
-
}
@Override
@@ -152,7 +146,9 @@
default:
log.warn("Unknown table type: {}", type);
}
+ builder.setInstructions(newInstructions);
this.write(builder.build());
+ log.info("Installed {}", builder.build());
} else {
this.write(msg);
}
diff --git a/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/FlowModBuilderVer10.java b/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/FlowModBuilderVer10.java
index 3e9bdfc..584f448 100644
--- a/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/FlowModBuilderVer10.java
+++ b/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/FlowModBuilderVer10.java
@@ -55,7 +55,7 @@
*/
public class FlowModBuilderVer10 extends FlowModBuilder {
- private static final Logger log = LoggerFactory.getLogger(FlowModBuilderVer10.class);
+ private final Logger log = LoggerFactory.getLogger(getClass());
private static final int OFPCML_NO_BUFFER = 0xffff;
private final TrafficTreatment treatment;
diff --git a/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/FlowModBuilderVer13.java b/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/FlowModBuilderVer13.java
index d87103d..b1848f2 100644
--- a/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/FlowModBuilderVer13.java
+++ b/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/FlowModBuilderVer13.java
@@ -74,7 +74,7 @@
*/
public class FlowModBuilderVer13 extends FlowModBuilder {
- private static final Logger log = LoggerFactory.getLogger(FlowModBuilderVer10.class);
+ private final Logger log = LoggerFactory.getLogger(getClass());
private static final int OFPCML_NO_BUFFER = 0xffff;
private final TrafficTreatment treatment;
@@ -118,6 +118,7 @@
.setMatch(match)
.setFlags(Collections.singleton(OFFlowModFlags.SEND_FLOW_REM))
.setPriority(flowRule().priority())
+ .setTableId(TableId.of(flowRule().type().ordinal()))
.build();
return fm;
@@ -144,6 +145,7 @@
.setMatch(match)
.setFlags(Collections.singleton(OFFlowModFlags.SEND_FLOW_REM))
.setPriority(flowRule().priority())
+ .setTableId(TableId.of(flowRule().type().ordinal()))
.build();
return fm;
@@ -219,6 +221,9 @@
.setGroup(OFGroup.of(group.groupId().id()));
actions.add(groupBuilder.build());
break;
+ case TABLE:
+ //FIXME: should not occur here.
+ break;
default:
log.warn("Instruction type {} not yet implemented.", i.type());
}
diff --git a/utils/misc/src/main/java/org/onlab/packet/Ethernet.java b/utils/misc/src/main/java/org/onlab/packet/Ethernet.java
index 2a69ffa..b2a01b9 100644
--- a/utils/misc/src/main/java/org/onlab/packet/Ethernet.java
+++ b/utils/misc/src/main/java/org/onlab/packet/Ethernet.java
@@ -36,6 +36,7 @@
public static final short TYPE_IPV4 = (short) 0x0800;
public static final short TYPE_IPV6 = (short) 0x86dd;
public static final short TYPE_LLDP = (short) 0x88cc;
+ public static final short TYPE_VLAN = (short) 0x8100;
public static final short TYPE_BSN = (short) 0x8942;
public static final short VLAN_UNTAGGED = (short) 0xffff;
public static final short MPLS_UNICAST = (short) 0x8847;
@@ -284,7 +285,7 @@
bb.put(this.destinationMACAddress.toBytes());
bb.put(this.sourceMACAddress.toBytes());
if (this.vlanID != Ethernet.VLAN_UNTAGGED) {
- bb.putShort((short) 0x8100);
+ bb.putShort(TYPE_VLAN);
bb.putShort((short) (this.priorityCode << 13 | this.vlanID & 0x0fff));
}
bb.putShort(this.etherType);
@@ -319,7 +320,7 @@
this.sourceMACAddress = MacAddress.valueOf(srcAddr);
short ethType = bb.getShort();
- if (ethType == (short) 0x8100) {
+ if (ethType == TYPE_VLAN) {
final short tci = bb.getShort();
this.priorityCode = (byte) (tci >> 13 & 0x07);
this.vlanID = (short) (tci & 0x0fff);