Called from Northbound API classes and implemented within nfchain agent.
Signed-off-by: Suchi Raman <suchi.raman@plexxi.com>
/* Methods to add and enable network service chains. */
public Status addNfchain(AffinityLink al);
public Status enableRedirect(AffinityLink al) throws Exception;
+ public Status disableRedirect(AffinityLink al) throws Exception;
// public Status addFlowRulesForRedirect(AffinityLink al) throws Exception;
// public Status pushFlowRule(InetAddress from, InetAddress to, byte [] mac);
/**
* Function called after registering the service in OSGi service registry.
*/
- void started(){
+ void started() {
// Retrieve current statistics so we don't have to wait for next refresh
IAffinityManager affinityManager = (IAffinityManager) ServiceHelper.getInstance(
IAffinityManager.class, this.getContainerName(), this);
String nfccname = al.getName();
return nfchainagent.enable(nfccname);
}
+
+ public Status disableRedirect(AffinityLink al) throws Exception {
+ String nfccname = al.getName();
+ return nfchainagent.disable(nfccname);
+ }
+
+ public Status removeNfchain(AffinityLink al) throws Exception {
+ String nfccname = al.getName();
+ return nfchainagent.removeNfchain(nfccname);
+ }
+
}
al1.setWaypoint(waypointIP);
try {
affinityManager.addNfchain(al1);
+ } catch (Exception e) {
+ String message = "An error occurred during flow programming.";
+ log.error(message, e);
+ }
+ return Response.status(Response.Status.CREATED).build();
+ }
+
+
+ @Path("/{containerName}/link/{affinityLinkName}/enable")
+ @PUT
+ @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
+ @TypeHint(Response.class)
+ @StatusCodes({
+ @ResponseCode(code = 200, condition = "Operation successful"),
+ @ResponseCode(code = 404, condition = "The Container Name or nodeId or configuration name is not found"),
+ @ResponseCode(code = 503, condition = "One or more of Controller services are unavailable") })
+ public Response enableLink(
+ @PathParam("containerName") String containerName,
+ @PathParam("affinityLinkName") String affinityLinkName) {
+
+ if (!NorthboundUtils.isAuthorized(getUserName(), containerName, Privilege.WRITE, this)) {
+ throw new UnauthorizedException("User is not authorized to perform this operation on container "
+ + containerName);
+ }
+
+ IAffinityManager affinityManager = getIfAffinityManagerService(containerName);
+ if (affinityManager == null) {
+ throw new ServiceUnavailableException("Affinity Manager "
+ + RestMessages.SERVICEUNAVAILABLE.toString());
+ }
+ log.info("Enable (link) " + affinityLinkName);
+
+ AffinityLink al1 = affinityManager.getAffinityLink(affinityLinkName);
+ try {
affinityManager.enableRedirect(al1);
} catch (Exception e) {
String message = "An error occurred during flow programming.";
return Response.status(Response.Status.CREATED).build();
}
+ @Path("/{containerName}/link/{affinityLinkName}/disable")
+ @PUT
+ @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
+ @TypeHint(Response.class)
+ @StatusCodes({
+ @ResponseCode(code = 200, condition = "Operation successful"),
+ @ResponseCode(code = 404, condition = "The Container Name or nodeId or configuration name is not found"),
+ @ResponseCode(code = 503, condition = "One or more of Controller services are unavailable") })
+ public Response disableLink(
+ @PathParam("containerName") String containerName,
+ @PathParam("affinityLinkName") String affinityLinkName) {
+
+ if (!NorthboundUtils.isAuthorized(getUserName(), containerName, Privilege.WRITE, this)) {
+ throw new UnauthorizedException("User is not authorized to perform this operation on container "
+ + containerName);
+ }
+
+ IAffinityManager affinityManager = getIfAffinityManagerService(containerName);
+ if (affinityManager == null) {
+ throw new ServiceUnavailableException("Affinity Manager "
+ + RestMessages.SERVICEUNAVAILABLE.toString());
+ }
+ log.info("Disable (link) " + affinityLinkName);
+
+ AffinityLink al1 = affinityManager.getAffinityLink(affinityLinkName);
+ try {
+ affinityManager.disableRedirect(al1);
+ } catch (Exception e) {
+ String message = "An error occurred during flow programming.";
+ log.error(message, e);
+ }
+ return Response.status(Response.Status.CREATED).build();
+ }
/**
* Add IP addresses to a group.
+++ /dev/null
-module affinity-config-all {
- namespace "urn:opendaylight:affinity";
- prefix affinity;
-
- import ietf-inet-types { prefix inet; }
- import ietf-yang-types { prefix yang; }
- import yang-ext { prefix ext; }
- import opendaylight-inventory {prefix inv;}
- import opendaylight-l2-types { prefix l2types; }
-
- revision "2013-09-25" {
- description "Initial revision of affinity model to be reviewed";
- }
-
-
- //**************************************************
- // Stationary location within the network -- switch + port, including physical switch port
- // or virtual switch port within a hypervisor virtual switch.
- //**************************************************
- grouping affinity-endpoint {
- leaf switch-port {
- type inv:node-connector-id;
- }
- }
-
- //**************************************************
- // Affinity address domain: This represents a domain (i.e, set) of one or
- // more addresses. An affinity address may not always have a corresponding
- // endpoint on the network, for example, an address domain representing
- // external addresses, or north-south traffic in a data center). Here the
- // IP address domain representing such external addresses does not map to
- // endpoints or node connectors on the network.
- // Whenever possible, the affinity service must resolve the address domain
- // into a list of endpoints especially when the address is present on the network.
- //
- // Affinity address domains specify one or more of the following:
- // layer 2 address (vlan + mac range)
- // layer 3 address (IP prefix)
- // layer 4 address (tcp or udp port number)
- //**************************************************
-
- grouping affinity-address-domain {
- // l2-domain-address is vlan + MAC address range
- container l2-address {
- leaf vlan-id {
- type l2types:vlan-id;
- }
- container mac-address-range {
- uses mac-address-range;
- }
- }
-
- // l3-domain-address is IPv4 prefix
- leaf l3-address {
- type inet:ipv4-prefix;
- }
-
- // l4 port number
- container l4-address {
- leaf proto {
- type string; // "tcp" or "udp"
- }
- leaf port-number {
- type inet:port-number;
- }
- }
- }
-
- grouping mac-address-range {
- leaf start-address {
- type yang:mac-address;
- }
- leaf end-address {
- type yang:mac-address;
- }
- }
-
- typedef affinity-group-ref {
- type instance-identifier;
- }
-
- typedef affinity-link-ref {
- type instance-identifier;
- }
-
- grouping affinity-element {
- leaf id {
- type string;
- }
- choice element {
- description "affinity element";
- case affinity-endpoint {
- uses affinity-endpoint;
- }
-
- case affinity-address-domain {
- uses affinity-address-domain;
- }
- }
- }
- //**************************************************
- // Affinity group
- //**************************************************
- grouping affinity-group {
- leaf id {
- type string;
- }
- list affinity-element {
- key id;
- uses affinity-element;
- }
- }
-
- //**************************************************
- // Affinity link connects one group (from group) to another (to
- // group). It represents a set of flows that start from the source group
- // and end in the destination group. An affinity link has attributes
- // (policies) attached to it that represent how these flows must be
- // handled. An affinity link also has directionality associated with
- // it. A bidirectional affinity link is equivalent to two unidirectional
- // affinity links, one in each direction.
- //**************************************************
- grouping affinity-link {
- leaf id {
- type string;
- }
- leaf from-affinity-group {
- type affinity-group-ref;
- }
- leaf to-affinity-group {
- type affinity-group-ref;
- }
- container attribute {
- uses affinity-attribute;
- }
- }
-
- typedef affinity-access-control-type {
- type enumeration {
- enum permit;
- enum deny;
- }
- }
-
- //**************************************************
- // Affinity attribute. Each is expanded in their own grouping construct below.
- //**************************************************
- grouping affinity-attribute {
- leaf id {
- type string;
- }
- choice attribute-type {
- description "affinity attribute";
- // Apply access control to selected flows.
- case affinity-access-control {
- leaf affinity-access-control {
- type affinity-access-control-type;
- }
- }
-
- // Apply waypoint routing to the selected flows and send it through service chain.
- case network-service-chain {
- leaf network-service-chain {
- type network-service-chain-ref;
- }
- }
- }
- }
-
- //**************************************************
- // Network service chain configuration.
- //**************************************************
- typedef network-service-chain-ref {
- type instance-identifier;
- }
-
- grouping network-service-chain {
- leaf id {
- type string;
- }
- list service-chain {
- key id;
- uses network-service-function;
- }
- }
-
- //**************************************************
- // Network-service-function represented by one of the following
- // types of addresses.
- //**************************************************
- grouping network-service-function {
- leaf id {
- type string;
- }
- // Address is either an IP address, MAC address, or switch/port.
- leaf location {
- description "Mac or Inet address";
- type union {
- type inv:node-connector-id;
- type yang:mac-address;
- type inet:ip-address;
- }
- }
- }
-
- // Main container that represents the complete set of affinity
- // groups and links. Each set is represented as a YANG list with 'id'
- // as the key. List contains affinity group and affinity link objects
- // defined above.
- container affinity-config {
- list affinity-group {
- key id;
- ext:context-instance "affinity-group-context";
- uses affinity-group;
- }
- list affinity-link {
- key id;
- ext:context-instance "affinity-link-context";
- uses affinity-link;
- }
- }
-
- //******************************
- // RPCs to create affinity groups, add endpoints and address domains.
- //******************************
- rpc create-affinity-group {
- input {
- uses affinity-group;
- }
- output {
- leaf status {
- type string;
- }
- }
- }
-
- rpc add-affinity-endpoint {
- input {
- leaf affinity-endpoint {
- type inv:node-connector-id;
- }
- }
- output {
- leaf status {
- type string;
- }
- }
- }
-
- rpc add-affinity-domain {
- input {
- container affinity-domain {
- uses affinity-address-domain;
- }
- }
- output {
- leaf status {
- type string;
- }
- }
- }
-
- rpc get-affinity-groups {
- output {
- list affinity-group {
- key id;
- uses affinity-group;
- }
- }
- }
- rpc get-affinity-links;
- rpc get-affinity-group;
- rpc get-affinity-link;
-
- rpc get-stats-per-affinity-link;
-
- //**************************************************
- // Notifications
- //**************************************************
- notification new-affinity-endpoint;
- notification new-affinity-domain;
- notification modify-affinity-attribute;
-
-}
-
-
/* Look up the output port leading to the waypoint. */
NodeConnector dst_connector = l2agent.lookup_output_port(node, wphost.getDataLayerAddressBytes());
- log.debug("Waypoint direction: node {} and connector {}", node, dst_connector);
+ log.debug("Waypoint direction added: node {} and connector {}", node, dst_connector);
if (dst_connector != null) {
f.setActions(actions);
f.addAction(new Output(dst_connector));
- log.debug("flow push flow = {} to node = {} ", f, node);
+ log.debug("flow push add flow = {} to node = {} ", f, node);
Status status = programmer.addFlow(node, f);
if (!status.isSuccess()) {
log.debug("Error during addFlow: {} on {}. The failure is: {}",
}
+
+ /**
+ * remove flow rules for set of flows in nfchainconfig. Do this for
+ * each node connector in the network proactively.
+ */
+ public Status removerules(Node node, NFchainconfig nfcc) throws Exception {
+ List<Flow> flowlist = nfcc.getFlowList();
+ for (Flow f: flowlist) {
+ HostNodeConnector wphost = (HostNodeConnector) hostTracker.hostFind(nfcc.getWaypointIP());
+ List<Action> actions = new ArrayList<Action>();
+ /* Look up the output port leading to the waypoint. */
+ NodeConnector dst_connector = l2agent.lookup_output_port(node, wphost.getDataLayerAddressBytes());
+
+ log.debug("Waypoint settings removed: node {} and connector {}", node, dst_connector);
+ if (dst_connector != null) {
+ f.setActions(actions);
+ f.addAction(new Output(dst_connector));
+ log.debug("flow push remove flow = {} to node = {} ", f, node);
+ Status status = programmer.removeFlow(node, f);
+ if (!status.isSuccess()) {
+ log.debug("Error during removeFlow: {} on {}. The failure is: {}",
+ f, node, status.getDescription());
+ }
+ }
+ }
+ return new Status(StatusCode.SUCCESS);
+ }
+
+
+ public Status removeNfchain(String key) {
+ if (allconfigs != null) {
+ allconfigs.remove(key);
+ }
+ return new Status(StatusCode.SUCCESS);
+ }
+
/**
* Enable the nfchain by programming flow rules on its behalf.
*/
}
return new Status(StatusCode.SUCCESS);
}
+
+ /**
+ * Remove openflow rules added earlier. Restore default routing via standard L2 learning methods.
+ */
+ public Status disable(String cfgname) throws Exception {
+ /* Get all node connectors. */
+ Set<Node> nodes = switchManager.getNodes();
+ NFchainconfig cfg = allconfigs.get(cfgname).get(0);
+
+ Status success = new Status(StatusCode.SUCCESS);
+ Status notfound = new Status(StatusCode.NOTFOUND);
+ Status ret;
+
+ if (nodes == null) {
+ log.debug("No nodes in network.");
+ return success;
+ }
+
+ /* Send this flow rule to all nodes in the network. */
+ for (Node node: nodes) {
+ ret = removerules(node, cfg);
+ }
+ return new Status(StatusCode.SUCCESS);
+ }
}
put_url = 'http://localhost:8080/affinity/nb/v2/affinity/default/link/inflows/setwaypoint/' + wp
rest_method(put_url, "PUT")
+def enable_waypoint():
+ put_url = 'http://localhost:8080/affinity/nb/v2/affinity/default/link/inflows/enable/'
+ rest_method(put_url, "PUT")
+
+def disable_waypoint():
+ put_url = 'http://localhost:8080/affinity/nb/v2/affinity/default/link/inflows/disable/'
+ rest_method(put_url, "PUT")
+
# Add waypoint IP to an affinity link.
def main():
global h
list_all_hosts()
set_waypoint_address()
+ enable_waypoint()
+ disable_waypoint()
#if __name__ == "__main__":
# main()