blob: d5b049c784a55b82b796c28ecae1c918201a4040 [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
Brian Stankefb61df42016-07-25 11:47:51 -0400111 public boolean isTraversable(ConnectPoint src, ConnectPoint dst) {
112 return false;
113 }
114
115 @Override
Brian Stanke9a108972016-04-11 15:25:17 -0400116 public TunnelId createTunnel(NetworkId networkId, ConnectPoint src, ConnectPoint dst) {
Shashikanth VHeb495492016-05-02 13:55:23 +0530117 checkNotNull(networkId, NETWORK_ID_NULL);
118 checkNotNull(src, CONNECT_POINT_NULL);
119 checkNotNull(dst, CONNECT_POINT_NULL);
Brian Stanke612cebf2016-05-02 10:21:33 -0400120 Key intentKey = encodeKey(networkId, src, dst);
Brian Stanke9a108972016-04-11 15:25:17 -0400121
122 List<Constraint> constraints = new ArrayList<>();
123 constraints.add(new EncapsulationConstraint(EncapsulationType.VLAN));
124
125 // TODO Currently there can only be one tunnel/intent between the src and dst across
126 // all virtual networks. We may want to support multiple intents between the same src/dst pairs.
127 PointToPointIntent intent = PointToPointIntent.builder()
128 .key(intentKey)
129 .appId(appId)
130 .ingressPoint(src)
131 .egressPoint(dst)
132 .constraints(constraints)
133 .build();
134 intentService.submit(intent);
135
136 // construct tunnelId from the key
Brian Stanke612cebf2016-05-02 10:21:33 -0400137 return TunnelId.valueOf(intentKey.toString());
Brian Stanke9a108972016-04-11 15:25:17 -0400138 }
139
140 @Override
141 public void destroyTunnel(NetworkId networkId, TunnelId tunnelId) {
142 String key = tunnelId.id();
143 Key intentKey = Key.of(key, appId);
144 Intent intent = intentService.getIntent(intentKey);
145 checkNotNull(intent, INTENT_NULL);
146 intentService.withdraw(intent);
Brian Stanke612cebf2016-05-02 10:21:33 -0400147 }
148
149 private NetworkId decodeNetworkIdFromKey(Key intentKey) {
150 // Extract the network identifier from the intent key
151 StringTokenizer tokenizer = new StringTokenizer(intentKey.toString(), ",");
152 String networkIdString = tokenizer.nextToken().substring(NETWORK_ID.length());
153 return NetworkId.networkId(Integer.valueOf(networkIdString));
154 }
155
156 private Key encodeKey(NetworkId networkId, ConnectPoint src, ConnectPoint dst) {
157 String key = String.format(KEY_FORMAT, networkId, src, dst);
158 return Key.of(key, appId);
159 }
160
161 private class InternalPtPtIntentListener implements IntentListener {
162 @Override
163 public void event(IntentEvent event) {
164 PointToPointIntent intent = (PointToPointIntent) event.subject();
165 Key intentKey = intent.key();
166
167 // Ignore intent events that are not relevant.
168 if (!isRelevant(event)) {
169 return;
Brian Stanke9a108972016-04-11 15:25:17 -0400170 }
Brian Stanke612cebf2016-05-02 10:21:33 -0400171
172 NetworkId networkId = decodeNetworkIdFromKey(intentKey);
173 ConnectPoint src = intent.ingressPoint();
174 ConnectPoint dst = intent.egressPoint();
175
176 switch (event.type()) {
177 case INSTALLED:
178 providerService.tunnelUp(networkId, src, dst, TunnelId.valueOf(intentKey.toString()));
179 break;
180 case WITHDRAWN:
181 intentService.purge(intent);
182 // Fall through and notify the provider service that the tunnel is down
183 // for both WITHDRAWN and FAILED intent event types.
184 case FAILED:
185 providerService.tunnelDown(networkId, src, dst, TunnelId.valueOf(intentKey.toString()));
186 break;
187 case INSTALL_REQ:
188 case CORRUPT:
189 case PURGED:
190 break; // Not sure what do with these events, ignore for now.
191 default:
192 break;
193 }
194 }
195
196 @Override
197 public boolean isRelevant(IntentEvent event) {
Ray Milkey801121b2016-05-20 16:08:34 -0700198 if (event.subject() instanceof PointToPointIntent) {
199 PointToPointIntent intent = (PointToPointIntent) event.subject();
Brian Stanke612cebf2016-05-02 10:21:33 -0400200
Ray Milkey801121b2016-05-20 16:08:34 -0700201 // Only events that are for this appId are relevent.
202 return intent.appId().equals(appId);
Brian Stanke612cebf2016-05-02 10:21:33 -0400203 }
204 return false;
Brian Stanke9a108972016-04-11 15:25:17 -0400205 }
206 }
207}
208