/**
* Copyright 2011, Big Switch Networks, Inc.
* Originally created by David Erickson, Stanford University
*
* 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 net.floodlightcontroller.core.util;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import org.projectfloodlight.openflow.types.U64;
/***
* A static utility class to register flow cookiue AppIds and generating
* flow cookies for a particular App`
*
* An "app" is a module or piece of code that can install flows in a switch.
* E.g., Forwarding and StaticFlowPusher are apps. An App is identified by a
* 12 bit integer, the id. Furthermore, an App has a name. The id value must
* be unique but the same name can be registered for multiple numeric ids.
* TODO: should we enforce unique names
*
* This class is thread-safe.
*
* The 64 bit OpenFlow cookie field used in the following way
* <li> Bit 63 -- 52 (12 bit): the AppId
* <li> Bit 51 -- 0 (52 bit): user data
*
* FIXME: The class should be a singleton. The registration method should
* return an instance of class. This instance should then be used to generate
* flow cookies. Ideally, we would also represent a flow cookie as a class
* instance.
*
* @author capveg
*/
public class AppCookie {
private static final int APP_ID_BITS = 12;
private static final long APP_ID_MASK = (1L << APP_ID_BITS) - 1;
private static final int APP_ID_SHIFT = 64 - APP_ID_BITS;
private static final long USER_MASK = 0x000FFFFFFFFFFFFFL;
private static ConcurrentMap<Long, String> appIdMap =
new ConcurrentHashMap<Long, String>();
/**
* Returns a mask suitable for matching the app ID within a cookie.
* @return a mask representing the bits used for the app ID in the cookie
*/
static public U64 getAppFieldMask() {
return U64.of(APP_ID_MASK << APP_ID_SHIFT);
}
/**
* Returns a mask suitable for matching the user field within a cookie.
* @return a mask representing the bits used for user data in the cookie
*/
static public U64 getUserFieldMask() {
return U64.of(USER_MASK);
}
/**
* Encapsulate an application ID and a user block of stuff into a cookie
*
* @param application An ID to identify the application
* @param user Some application specific data
* @return a cookie for use in OFFlowMod.setCookie()
* @throws IllegalStateException if the application has not been registered
*/
static public U64 makeCookie(long application, long user) {
if (!appIdMap.containsKey(application)) {
throw new AppIDNotRegisteredException(application);
}
user = user & USER_MASK; // mask to prevent sign extend
return U64.of((application << APP_ID_SHIFT) | user);
}
/**
* Extract the application id from a flow cookie. Does <em>not</em>
* check whether the application id is registered. The app ID is
* defined by the {@link #getAppFieldMask()} bits
* @param cookie
* @return
*/
static public long extractApp(U64 cookie) {
return (cookie.getValue() >>> APP_ID_SHIFT) & APP_ID_MASK;
}
/**
* Extract the user portion from a flow cookie, defined
* by the {@link #getUserFieldMask()} bits
* @param cookie
* @return
*/
static public long extractUser(U64 cookie) {
return cookie.getValue() & USER_MASK;
}
/**
* A lame attempt to prevent duplicate application ID.
*
* @param application
* @param appName
* @throws AppIDInUseException
*/
public static void registerApp(long application, String appName)
throws AppIDException
{
if ((application & APP_ID_MASK) != application) {
throw new InvalidAppIDValueException(application);
}
String oldApp = appIdMap.putIfAbsent(application, appName);
if (oldApp != null && !oldApp.equals(appName)) {
throw new AppIDInUseException(application, oldApp, appName);
}
}
/**
* Retrieves the application name registered for the given application id
* or null if the application has not been registered
* @param application
* @return
*/
public static String getAppName(long application) {
return appIdMap.get(application);
}
}