blob: 1b8a69e0a9a1a4dc1725a60d8b66fc8bd9aa9df5 [file] [log] [blame]
Brian Stanke9a108972016-04-11 15:25:17 -04001/*
2 * Copyright 2016-present Open Networking Laboratory
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package org.onosproject.incubator.net.virtual.impl;
18
19
20import org.apache.felix.scr.annotations.Activate;
21import org.apache.felix.scr.annotations.Component;
22import org.apache.felix.scr.annotations.Deactivate;
23import org.apache.felix.scr.annotations.Reference;
24import org.apache.felix.scr.annotations.ReferenceCardinality;
25import org.apache.felix.scr.annotations.Service;
26import org.onosproject.core.ApplicationId;
27import org.onosproject.core.CoreService;
28import org.onosproject.incubator.net.tunnel.TunnelId;
29import org.onosproject.incubator.net.virtual.DefaultVirtualLink;
30import org.onosproject.incubator.net.virtual.NetworkId;
31import org.onosproject.incubator.net.virtual.VirtualNetworkProvider;
32import org.onosproject.incubator.net.virtual.VirtualNetworkProviderRegistry;
33import org.onosproject.incubator.net.virtual.VirtualNetworkProviderService;
34import org.onosproject.net.ConnectPoint;
35import org.onosproject.net.EncapsulationType;
36import org.onosproject.net.intent.Constraint;
37import org.onosproject.net.intent.Intent;
Brian Stanke612cebf2016-05-02 10:21:33 -040038import org.onosproject.net.intent.IntentEvent;
39import org.onosproject.net.intent.IntentListener;
Brian Stanke9a108972016-04-11 15:25:17 -040040import org.onosproject.net.intent.IntentService;
Brian Stanke9a108972016-04-11 15:25:17 -040041import org.onosproject.net.intent.Key;
42import org.onosproject.net.intent.PointToPointIntent;
43import org.onosproject.net.intent.constraint.EncapsulationConstraint;
44import org.onosproject.net.provider.AbstractProvider;
45import org.slf4j.Logger;
46
47import java.util.ArrayList;
48import java.util.List;
Brian Stanke612cebf2016-05-02 10:21:33 -040049import java.util.StringTokenizer;
Brian Stanke9a108972016-04-11 15:25:17 -040050
51import static com.google.common.base.Preconditions.checkNotNull;
Brian Stanke9a108972016-04-11 15:25:17 -040052import static org.slf4j.LoggerFactory.getLogger;
53
54/**
55 * Point to point intent VirtualNetworkProvider implementation.
56 */
57@Component(immediate = true)
58@Service
Brian Stanke612cebf2016-05-02 10:21:33 -040059public class PtToPtIntentVirtualNetworkProvider extends AbstractProvider
60 implements VirtualNetworkProvider {
Brian Stanke9a108972016-04-11 15:25:17 -040061
62 private final Logger log = getLogger(PtToPtIntentVirtualNetworkProvider.class);
63 private static final String NETWORK_ID_NULL = "Network ID cannot be null";
64 private static final String CONNECT_POINT_NULL = "Connect Point cannot be null";
65 private static final String INTENT_NULL = "Intent cannot be null";
Brian Stanke612cebf2016-05-02 10:21:33 -040066 private static final String NETWORK_ID = "networkId=";
67 protected static final String KEY_FORMAT = NETWORK_ID + "%s, src=%s, dst=%s";
Brian Stanke9a108972016-04-11 15:25:17 -040068 private static final int MAX_WAIT_COUNT = 30;
69
70 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
71 protected VirtualNetworkProviderRegistry providerRegistry;
72
73 private VirtualNetworkProviderService providerService;
74
75 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
76 protected IntentService intentService;
77
Brian Stanke612cebf2016-05-02 10:21:33 -040078 private final InternalPtPtIntentListener intentListener = new InternalPtPtIntentListener();
79
Brian Stanke9a108972016-04-11 15:25:17 -040080 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
81 protected CoreService coreService;
82
83 protected static final String PTPT_INTENT_APPID = "org.onosproject.vnet.intent";
84 private ApplicationId appId;
85
86 /**
87 * Default constructor.
88 */
89 public PtToPtIntentVirtualNetworkProvider() {
90 super(DefaultVirtualLink.PID);
91 }
92
93 @Activate
94 public void activate() {
95 providerService = providerRegistry.register(this);
96 appId = coreService.registerApplication(PTPT_INTENT_APPID);
97
Brian Stanke612cebf2016-05-02 10:21:33 -040098 intentService.addListener(intentListener);
Brian Stanke9a108972016-04-11 15:25:17 -040099 log.info("Started");
100 }
101
102 @Deactivate
103 public void deactivate() {
Brian Stanke612cebf2016-05-02 10:21:33 -0400104 intentService.removeListener(intentListener);
Brian Stanke9a108972016-04-11 15:25:17 -0400105 providerRegistry.unregister(this);
106 providerService = null;
107 log.info("Stopped");
108 }
109
110 @Override
111 public TunnelId createTunnel(NetworkId networkId, ConnectPoint src, ConnectPoint dst) {
Shashikanth VHeb495492016-05-02 13:55:23 +0530112 checkNotNull(networkId, NETWORK_ID_NULL);
113 checkNotNull(src, CONNECT_POINT_NULL);
114 checkNotNull(dst, CONNECT_POINT_NULL);
Brian Stanke612cebf2016-05-02 10:21:33 -0400115 Key intentKey = encodeKey(networkId, src, dst);
Brian Stanke9a108972016-04-11 15:25:17 -0400116
117 List<Constraint> constraints = new ArrayList<>();
118 constraints.add(new EncapsulationConstraint(EncapsulationType.VLAN));
119
120 // TODO Currently there can only be one tunnel/intent between the src and dst across
121 // all virtual networks. We may want to support multiple intents between the same src/dst pairs.
122 PointToPointIntent intent = PointToPointIntent.builder()
123 .key(intentKey)
124 .appId(appId)
125 .ingressPoint(src)
126 .egressPoint(dst)
127 .constraints(constraints)
128 .build();
129 intentService.submit(intent);
130
131 // construct tunnelId from the key
Brian Stanke612cebf2016-05-02 10:21:33 -0400132 return TunnelId.valueOf(intentKey.toString());
Brian Stanke9a108972016-04-11 15:25:17 -0400133 }
134
135 @Override
136 public void destroyTunnel(NetworkId networkId, TunnelId tunnelId) {
137 String key = tunnelId.id();
138 Key intentKey = Key.of(key, appId);
139 Intent intent = intentService.getIntent(intentKey);
140 checkNotNull(intent, INTENT_NULL);
141 intentService.withdraw(intent);
Brian Stanke612cebf2016-05-02 10:21:33 -0400142 }
143
144 private NetworkId decodeNetworkIdFromKey(Key intentKey) {
145 // Extract the network identifier from the intent key
146 StringTokenizer tokenizer = new StringTokenizer(intentKey.toString(), ",");
147 String networkIdString = tokenizer.nextToken().substring(NETWORK_ID.length());
148 return NetworkId.networkId(Integer.valueOf(networkIdString));
149 }
150
151 private Key encodeKey(NetworkId networkId, ConnectPoint src, ConnectPoint dst) {
152 String key = String.format(KEY_FORMAT, networkId, src, dst);
153 return Key.of(key, appId);
154 }
155
156 private class InternalPtPtIntentListener implements IntentListener {
157 @Override
158 public void event(IntentEvent event) {
159 PointToPointIntent intent = (PointToPointIntent) event.subject();
160 Key intentKey = intent.key();
161
162 // Ignore intent events that are not relevant.
163 if (!isRelevant(event)) {
164 return;
Brian Stanke9a108972016-04-11 15:25:17 -0400165 }
Brian Stanke612cebf2016-05-02 10:21:33 -0400166
167 NetworkId networkId = decodeNetworkIdFromKey(intentKey);
168 ConnectPoint src = intent.ingressPoint();
169 ConnectPoint dst = intent.egressPoint();
170
171 switch (event.type()) {
172 case INSTALLED:
173 providerService.tunnelUp(networkId, src, dst, TunnelId.valueOf(intentKey.toString()));
174 break;
175 case WITHDRAWN:
176 intentService.purge(intent);
177 // Fall through and notify the provider service that the tunnel is down
178 // for both WITHDRAWN and FAILED intent event types.
179 case FAILED:
180 providerService.tunnelDown(networkId, src, dst, TunnelId.valueOf(intentKey.toString()));
181 break;
182 case INSTALL_REQ:
183 case CORRUPT:
184 case PURGED:
185 break; // Not sure what do with these events, ignore for now.
186 default:
187 break;
188 }
189 }
190
191 @Override
192 public boolean isRelevant(IntentEvent event) {
Ray Milkey801121b2016-05-20 16:08:34 -0700193 if (event.subject() instanceof PointToPointIntent) {
194 PointToPointIntent intent = (PointToPointIntent) event.subject();
Brian Stanke612cebf2016-05-02 10:21:33 -0400195
Ray Milkey801121b2016-05-20 16:08:34 -0700196 // Only events that are for this appId are relevent.
197 return intent.appId().equals(appId);
Brian Stanke612cebf2016-05-02 10:21:33 -0400198 }
199 return false;
Brian Stanke9a108972016-04-11 15:25:17 -0400200 }
201 }
202}
203