alshabib
Committed by Jonathan Hart

WIP: Started implementing static flows for corsa vanderweken pipeline.

Modified to not use Corsa driver by default.

Change-Id: If8df5769cf084346121d34bf4490f578e6b6f2d0
......@@ -23,6 +23,7 @@ import org.apache.felix.scr.annotations.Deactivate;
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.DefaultFlowRule;
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 @@ public class BgpRouter {
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 @@ public class BgpRouter {
protected void deactivate() {
routingService.stop();
connectivityManager.stop();
provisionStaticTables.provision(false);
log.info("BgpRouter stopped");
}
......@@ -224,4 +232,303 @@ public class BgpRouter {
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");
}
}));
}
}
}
......
......@@ -134,6 +134,7 @@ public final class DefaultTrafficTreatment implements TrafficTreatment {
case DROP:
drop = true;
break;
case TABLE:
case OUTPUT:
outputs.add(instruction);
break;
......
/*
* 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());
}
}
......@@ -17,7 +17,6 @@ package org.onosproject.openflow.drivers;
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 @@ public class OFCorsaSwitchDriver extends AbstractOpenFlowSwitch {
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 @@ public class OFCorsaSwitchDriver extends AbstractOpenFlowSwitch {
@Override
public void write(List<OFMessage> msgs) {
if (role == RoleState.MASTER) {
channel.write(msgs);
}
}
@Override
......@@ -152,7 +146,9 @@ public class OFCorsaSwitchDriver extends AbstractOpenFlowSwitch {
default:
log.warn("Unknown table type: {}", type);
}
builder.setInstructions(newInstructions);
this.write(builder.build());
log.info("Installed {}", builder.build());
} else {
this.write(msg);
}
......
......@@ -55,7 +55,7 @@ import java.util.Optional;
*/
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;
......
......@@ -74,7 +74,7 @@ import java.util.Optional;
*/
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 @@ public class FlowModBuilderVer13 extends FlowModBuilder {
.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 @@ public class FlowModBuilderVer13 extends FlowModBuilder {
.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 @@ public class FlowModBuilderVer13 extends FlowModBuilder {
.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());
}
......
......@@ -36,6 +36,7 @@ public class Ethernet extends BasePacket {
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 @@ public class Ethernet extends BasePacket {
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 @@ public class Ethernet extends BasePacket {
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);
......