blob: 3c593d688e65ff9848e1f52eb2e36978ac3faef8 [file] [log] [blame]
Sean Condonfae8e662016-12-15 10:25:13 +00001/*
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 */
16package org.onosproject.drivers.microsemi;
17
18import static com.google.common.base.Preconditions.checkNotNull;
19import static org.slf4j.LoggerFactory.getLogger;
20
21import java.math.BigInteger;
22import java.net.URI;
23import java.util.ArrayList;
24import java.util.Collection;
25import java.util.HashMap;
26import java.util.HashSet;
27import java.util.List;
28import java.util.Map;
29import java.util.concurrent.Semaphore;
30import java.util.stream.Collectors;
31
32import org.onlab.packet.EthType;
33import org.onlab.packet.EthType.EtherType;
34import org.onlab.packet.IpPrefix;
35import org.onlab.packet.VlanId;
36import org.onosproject.core.ApplicationId;
37import org.onosproject.core.CoreService;
38import org.onosproject.drivers.microsemi.yang.MseaSaFilteringNetconfService;
39import org.onosproject.drivers.microsemi.yang.MseaUniEvcServiceNetconfService;
40import org.onosproject.drivers.microsemi.yang.UniSide;
41import org.onosproject.drivers.microsemi.yang.utils.CeVlanMapUtils;
42import org.onosproject.net.PortNumber;
43import org.onosproject.net.driver.AbstractHandlerBehaviour;
44import org.onosproject.net.flow.DefaultFlowEntry;
45import org.onosproject.net.flow.DefaultFlowRule;
46import org.onosproject.net.flow.DefaultTrafficSelector;
47import org.onosproject.net.flow.DefaultTrafficTreatment;
48import org.onosproject.net.flow.FlowEntry;
49import org.onosproject.net.flow.FlowEntry.FlowEntryState;
50import org.onosproject.net.flow.FlowRule;
51import org.onosproject.net.flow.FlowRuleProgrammable;
52import org.onosproject.net.flow.TrafficSelector;
53import org.onosproject.net.flow.TrafficTreatment;
54import org.onosproject.net.flow.criteria.Criteria;
55import org.onosproject.net.flow.criteria.Criterion;
56import org.onosproject.net.flow.criteria.Criterion.Type;
57import org.onosproject.net.flow.criteria.PortCriterion;
58import org.onosproject.net.flow.criteria.VlanIdCriterion;
59import org.onosproject.net.flow.instructions.Instruction;
60import org.onosproject.net.flow.instructions.L2ModificationInstruction;
61import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModVlanHeaderInstruction;
62import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModVlanIdInstruction;
63import org.onosproject.net.meter.MeterId;
64import org.onosproject.netconf.NetconfController;
65import org.onosproject.netconf.NetconfException;
66import org.onosproject.netconf.NetconfSession;
67import org.onosproject.netconf.TargetConfig;
68import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.sa.filtering.rev20160412.MseaSaFiltering;
69import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.sa.filtering.rev20160412.MseaSaFilteringOpParam;
70import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.sa.filtering.rev20160412.mseasafiltering.DefaultSourceIpaddressFiltering;
71import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.sa.filtering.rev20160412.mseasafiltering.SourceIpaddressFiltering;
72import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.sa.filtering.rev20160412.mseasafiltering.sourceipaddressfiltering.DefaultInterfaceEth0;
73import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.sa.filtering.rev20160412.mseasafiltering.sourceipaddressfiltering.InterfaceEth0;
74import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.sa.filtering.rev20160412.mseasafiltering.sourceipaddressfiltering.interfaceeth0.DefaultSourceAddressRange;
75import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.sa.filtering.rev20160412.mseasafiltering.sourceipaddressfiltering.interfaceeth0.FilterAdminStateEnum;
76import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.sa.filtering.rev20160412.mseasafiltering.sourceipaddressfiltering.interfaceeth0.SourceAddressRange;
77import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.types.rev20160229.mseatypes.Identifier45;
78import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.types.rev20160229.mseatypes.ServiceListType;
79import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.types.rev20160229.mseatypes.VlanIdType;
80import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.uni.evc.service.rev20160317.MseaUniEvcService;
81import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.uni.evc.service.rev20160317.MseaUniEvcServiceOpParam;
82import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.uni.evc.service.rev20160317.mseaunievcservice.DefaultMefServices;
83import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.uni.evc.service.rev20160317.mseaunievcservice.MefServices;
84import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.uni.evc.service.rev20160317.mseaunievcservice.evcperuniextensionattributes.DefaultFlowMapping;
85import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.uni.evc.service.rev20160317.mseaunievcservice.evcperuniextensionattributes.FlowMapping;
86import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.uni.evc.service.rev20160317.mseaunievcservice.evcperuniextensionattributes.TagManipulation;
87import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.uni.evc.service.rev20160317.mseaunievcservice.evcperuniextensionattributes.tagmanipulation.DefaultTagOverwrite;
88import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.uni.evc.service.rev20160317.mseaunievcservice.evcperuniextensionattributes.tagmanipulation.DefaultTagPop;
89import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.uni.evc.service.rev20160317.mseaunievcservice.evcperuniextensionattributes.tagmanipulation.DefaultTagPush;
90import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.uni.evc.service.rev20160317.mseaunievcservice.evcperuniextensionattributes.tagmanipulation.TagOverwrite;
91import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.uni.evc.service.rev20160317.mseaunievcservice.evcperuniextensionattributes.tagmanipulation.TagPop;
92import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.uni.evc.service.rev20160317.mseaunievcservice.evcperuniextensionattributes.tagmanipulation.TagPush;
93import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.uni.evc.service.rev20160317.mseaunievcservice.evcperuniextensionattributes.tagmanipulation.tagpush.tagpush.PushTagTypeEnum;
94import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.uni.evc.service.rev20160317.mseaunievcservice.mefservices.DefaultProfiles;
95import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.uni.evc.service.rev20160317.mseaunievcservice.mefservices.DefaultUni;
96import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.uni.evc.service.rev20160317.mseaunievcservice.mefservices.Profiles;
97import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.uni.evc.service.rev20160317.mseaunievcservice.mefservices.Uni;
98import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.uni.evc.service.rev20160317.mseaunievcservice.mefservices.profiles.BwpGroup;
99import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.uni.evc.service.rev20160317.mseaunievcservice.mefservices.profiles.DefaultBwpGroup;
100import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.uni.evc.service.rev20160317.mseaunievcservice.mefservices.uni.CustomEvc;
101import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.uni.evc.service.rev20160317.mseaunievcservice.mefservices.uni.DefaultEvc;
102import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.uni.evc.service.rev20160317.mseaunievcservice.mefservices.uni.Evc;
103import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.uni.evc.service.rev20160317.mseaunievcservice.mefservices.uni.UniSideInterfaceAssignmentEnum;
104import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.uni.evc.service.rev20160317.mseaunievcservice.mefservices.uni.evc.DefaultEvcPerUni;
105import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.uni.evc.service.rev20160317.mseaunievcservice.mefservices.uni.evc.EvcPerUni;
106import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.uni.evc.service.rev20160317.mseaunievcservice.mefservices.uni.evc.evcperuni.CustomEvcPerUnic;
107import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.uni.evc.service.rev20160317.mseaunievcservice.mefservices.uni.evc.evcperuni.CustomEvcPerUnin;
108import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.uni.evc.service.rev20160317.mseaunievcservice.mefservices.uni.evc.evcperuni.DefaultEvcPerUnic.EvcPerUnicBuilder;
109import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.uni.evc.service.rev20160317.mseaunievcservice.mefservices.uni.evc.evcperuni.DefaultEvcPerUnin.EvcPerUninBuilder;
110import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.uni.evc.service.rev20160317.mseaunievcservice.mefservices.uni.evc.evcperuni.EvcPerUnic;
111import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.uni.evc.service.rev20160317.mseaunievcservice.mefservices.uni.evc.evcperuni.EvcPerUnin;
112import org.slf4j.Logger;
113
114/**
115 * An implementation of the FlowRuleProgrammable behaviour for the EA10000 device.
116 *
117 * This device is not a native Open Flow device. It has only a NETCONF interface for configuration
118 * status retrieval and notifications. It supports only a small subset of OpenFlow rules.<br>
119 *
120 * The device supports only:<br>
121 * 1) Open flow rules that blocks certain IP address ranges, but only those incoming on Port 0
122 * and has a limit of 10 such rules<br>
123 * 2) Open flow rules that PUSH, POP and OVERWRITE VLAN tags on both ports. This can push and overwrite
124 * both C-TAGs (0x8100) and S-TAGs (0x88a8).
125 */
126public class EA1000FlowRuleProgrammable extends AbstractHandlerBehaviour implements FlowRuleProgrammable {
127
128 protected final Logger log = getLogger(getClass());
129 public static final String MICROSEMI_DRIVERS = "com.microsemi.drivers";
130 public static final int PRIORITY_DEFAULT = 50000;
131 //To protect the NETCONF session from concurrent access across flow addition and removal
132 static Semaphore sessionMutex = new Semaphore(1);
133
134 /**
135 * Get the flow entries that are present on the EA1000.
136 * Since the EA1000 does not have any 'real' flow entries these are retrieved from 2 configuration
137 * areas on the EA1000 NETCONF model - from SA filtering YANG model and from EVC UNI YANG model.<br>
138 * The flow entries must match exactly the FlowRule entries in the ONOS store. If they are not an
139 * exact match the device will be requested to remove those flows and the FlowRule will stay in a
140 * PENDING_ADD state.
141 * @return A collection of Flow Entries
142 */
143 @Override
144 public Collection<FlowEntry> getFlowEntries() {
145 Collection<FlowEntry> flowEntryCollection = new HashSet<FlowEntry>();
146
147 UniSideInterfaceAssignmentEnum portAssignment = UniSideInterfaceAssignmentEnum.UNI_C_ON_HOST;
148 NetconfController controller = checkNotNull(handler().get(NetconfController.class));
149 NetconfSession session = controller.getDevicesMap().get(handler().data().deviceId()).getSession();
150 CoreService coreService = checkNotNull(handler().get(CoreService.class));
151 ApplicationId appId = coreService.getAppId(MICROSEMI_DRIVERS);
152 MseaSaFilteringNetconfService mseaSaFilteringService =
153 (MseaSaFilteringNetconfService) checkNotNull(handler().get(MseaSaFilteringNetconfService.class));
154 MseaUniEvcServiceNetconfService mseaUniEvcServiceSvc =
155 (MseaUniEvcServiceNetconfService) checkNotNull(handler().get(MseaUniEvcServiceNetconfService.class));
156 log.debug("getFlowEntries() called on EA1000FlowRuleProgrammable");
157
158 //First get the MseaSaFiltering rules
159 SourceIpaddressFiltering.SourceIpaddressFilteringBuilder sipBuilder =
160 new DefaultSourceIpaddressFiltering.SourceIpaddressFilteringBuilder();
161
162 MseaSaFilteringOpParam.MseaSaFilteringBuilder opBuilder =
163 new MseaSaFilteringOpParam.MseaSaFilteringBuilder();
164 MseaSaFilteringOpParam mseaSaFilteringFilter =
165 (MseaSaFilteringOpParam) opBuilder
166 .sourceIpaddressFiltering(sipBuilder.build())
167 .build();
168 try {
169 MseaSaFiltering saFilteringCurrent =
170 mseaSaFilteringService.getMseaSaFiltering(mseaSaFilteringFilter, session);
171 if (saFilteringCurrent != null) {
172 flowEntryCollection.addAll(
173 convertSaFilteringToFlowRules(saFilteringCurrent, appId));
174 }
175 } catch (NetconfException e) {
176 log.warn("Unexpected error on getFlowEntries", e);
177 }
178
179
180 //Then get the EVCs - there will be a flow entry per EVC
181 Uni.UniBuilder uniBuilder = new DefaultUni.UniBuilder();
182
183 MefServices.MefServicesBuilder mefBuilder = new DefaultMefServices.MefServicesBuilder();
184 MefServices mefServices = mefBuilder.uni(uniBuilder.build()).build();
185
186 MseaUniEvcService.MseaUniEvcServiceBuilder evcUniBuilder =
187 new MseaUniEvcServiceOpParam.MseaUniEvcServiceBuilder();
188
189 MseaUniEvcServiceOpParam mseaUniEvcServiceFilter =
190 (MseaUniEvcServiceOpParam) evcUniBuilder.mefServices(mefServices).build();
191 try {
192 MseaUniEvcService uniEvcCurrent =
193 mseaUniEvcServiceSvc.getConfigMseaUniEvcService(mseaUniEvcServiceFilter,
194 session, TargetConfig.RUNNING);
195
196 flowEntryCollection.addAll(
197 convertEvcUniToFlowRules(uniEvcCurrent, portAssignment));
198
199 } catch (NetconfException e) {
200 log.warn("Unexpected error on getFlowEntries", e);
201 }
202
203
204 return flowEntryCollection;
205 }
206
207 /**
208 * Apply the flow entries to the EA1000.
209 * Since the EA1000 does not have any 'real' flow entries these are converted 2 configuration
210 * areas on the EA1000 NETCONF model - to SA filtering YANG model and to EVC UNI YANG model.<br>
211 * Only a subset of the possible OpenFlow rules are supported. Any rule that's not handled
212 * will not be in the returned set.
213 *
214 * @param rules A collection of Flow Rules to be applied to the EA1000
215 * @return A collection of the Flow Rules that have been added.
216 */
217 @Override
218 public Collection<FlowRule> applyFlowRules(Collection<FlowRule> rules) {
219 Collection<FlowRule> frAdded = new HashSet<FlowRule>();
220 if (rules == null || rules.size() == 0) {
221 return rules;
222 }
223 NetconfController controller = checkNotNull(handler().get(NetconfController.class));
224 NetconfSession session = controller.getDevicesMap().get(handler().data().deviceId()).getSession();
225 MseaSaFilteringNetconfService mseaSaFilteringService =
226 (MseaSaFilteringNetconfService) checkNotNull(handler().get(MseaSaFilteringNetconfService.class));
227 MseaUniEvcServiceNetconfService mseaUniEvcServiceSvc =
228 (MseaUniEvcServiceNetconfService) checkNotNull(handler().get(MseaUniEvcServiceNetconfService.class));
229 log.debug("applyFlowRules() called on EA1000FlowRuleProgrammable with {} rules.", rules.size());
230 // FIXME: Change this so it's dynamically driven
231 UniSideInterfaceAssignmentEnum portAssignment = UniSideInterfaceAssignmentEnum.UNI_C_ON_HOST;
232
233 List<SourceAddressRange> saRangeList = new ArrayList<SourceAddressRange>();
234 Map<Integer, Evc> evcMap = new HashMap<>();
235
236 //Retrieve the list of actual EVCs and the CeVlanMaps from device
237 List<Evc> activeEvcs = new ArrayList<>();
238 try {
239 sessionMutex.acquire();
240 MseaUniEvcService evcResponse =
241 mseaUniEvcServiceSvc.getmseaUniEvcCeVlanMaps(session, TargetConfig.RUNNING);
242 //There could be zero or more EVCs
243 if (evcResponse != null && evcResponse.mefServices() != null && evcResponse.mefServices().uni() != null) {
244 activeEvcs.addAll(evcResponse.mefServices().uni().evc());
245 }
246 } catch (NetconfException | InterruptedException e1) {
247 log.warn("Unexpected error on applyFlowRules", e1);
248 }
249
250 for (FlowRule fr : rules) {
251
252 // IP SA Filtering can only apply to Port 0 optics
253 if (fr.selector().getCriterion(Type.IPV4_SRC) != null &&
254 fr.selector().getCriterion(Type.IN_PORT) != null &&
255 ((PortCriterion) fr.selector().getCriterion(Type.IN_PORT)).port().toLong() == 0) {
256 parseFrForSaRange(frAdded, saRangeList, fr);
257
258 // EVCs will be defined by Flow Rules relating to VIDs
259 } else if (fr.selector().getCriterion(Type.VLAN_VID) != null &&
260 fr.selector().getCriterion(Type.IN_PORT) != null) {
261 //There could be many Flow Rules for one EVC depending on the ceVlanMap
262 //Cannot build up the EVC until we know the details - the key is the tableID and port
263 parseFrForEvcs(frAdded, evcMap, activeEvcs, portAssignment, fr);
264 } else {
265 log.info("Unexpected Flow Rule type applied: " + fr);
266 }
267 }
268
269 //If there are IPv4 Flow Rules created commit them now through the
270 //MseaSaFiltering service
271 if (saRangeList.size() > 0) {
272 try {
273 mseaSaFilteringService.setMseaSaFiltering(
274 buildSaFilteringObject(saRangeList), session, TargetConfig.RUNNING);
275 } catch (NetconfException e) {
276 log.error("Error applying Flow Rules to SA Filtering - will try again: " + e.getMessage());
277 sessionMutex.release();
278 return frAdded;
279 }
280 }
281 //If there are EVC flow rules then populate the MseaUniEvc part of EA1000
282 if (evcMap.size() > 0) {
283 List<Evc> evcList = evcMap.entrySet().stream()
284 .map(x -> x.getValue())
285 .collect(Collectors.toList());
286 Uni.UniBuilder uniBuilder = new DefaultUni.UniBuilder();
287 URI deviceName = handler().data().deviceId().uri();
288 Uni uni = uniBuilder.name(new Identifier45("Uni-on-"
289 + deviceName.getSchemeSpecificPart())).evc(evcList).build();
290
291 List<BwpGroup> bwpGroupList = new ArrayList<BwpGroup>();
292 BwpGroup.BwpGroupBuilder bwpGrpBuilder = new DefaultBwpGroup.BwpGroupBuilder();
293 bwpGroupList.add(bwpGrpBuilder.groupIndex((short) 0).build());
294 Profiles profiles = (new DefaultProfiles.ProfilesBuilder()).bwpGroup(bwpGroupList).build();
295
296 MefServices.MefServicesBuilder mefBuilder = new DefaultMefServices.MefServicesBuilder();
297 MefServices mefServices = mefBuilder.uni(uni).profiles(profiles).build();
298
299 MseaUniEvcService.MseaUniEvcServiceBuilder evcUniBuilder =
300 new MseaUniEvcServiceOpParam.MseaUniEvcServiceBuilder();
301
302 MseaUniEvcServiceOpParam mseaUniEvcServiceFilter =
303 (MseaUniEvcServiceOpParam) evcUniBuilder.mefServices(mefServices).build();
304 try {
305 mseaUniEvcServiceSvc.setMseaUniEvcService(mseaUniEvcServiceFilter, session, TargetConfig.RUNNING);
306 } catch (NetconfException e) {
307 log.error("Error applying Flow Rules to EVC - will try again: " + e.getMessage());
308 sessionMutex.release();
309 return frAdded;
310 }
311 }
312 sessionMutex.release();
313 return frAdded;
314 }
315
316 /**
317 * Remove flow rules from the EA1000.
318 * Since the EA1000 does not have any 'real' flow entries these are converted 2 configuration
319 * areas on the EA1000 NETCONF model - to SA filtering YANG model and to EVC UNI YANG model.
320 *
321 * @param rulesToRemove A collection of Flow Rules to be removed to the EA1000
322 * @return A collection of the Flow Rules that have been removed.
323 */
324 @Override
325 public Collection<FlowRule> removeFlowRules(Collection<FlowRule> rulesToRemove) {
326 NetconfController controller = checkNotNull(handler().get(NetconfController.class));
327 NetconfSession session = controller.getDevicesMap().get(handler().data().deviceId()).getSession();
328 MseaSaFilteringNetconfService mseaSaFilteringService =
329 (MseaSaFilteringNetconfService) checkNotNull(handler().get(MseaSaFilteringNetconfService.class));
330 MseaUniEvcServiceNetconfService mseaUniEvcServiceSvc =
331 (MseaUniEvcServiceNetconfService) checkNotNull(handler().get(MseaUniEvcServiceNetconfService.class));
332 UniSideInterfaceAssignmentEnum portAssignment = UniSideInterfaceAssignmentEnum.UNI_C_ON_HOST;
333 log.debug("removeFlowRules() called on EA1000FlowRuleProgrammable with {} rules.", rulesToRemove.size());
334
335 if (rulesToRemove.size() == 0) {
336 return rulesToRemove;
337 }
338
339 //Retrieve the list of actual EVCs and the CeVlanMaps from device
340 List<Evc> activeEvcs = new ArrayList<>();
341 try {
342 sessionMutex.acquire();
343 MseaUniEvcService evcResponse =
344 mseaUniEvcServiceSvc.getmseaUniEvcCeVlanMaps(session, TargetConfig.RUNNING);
345 //There could be zero or more EVCs
346 if (evcResponse != null && evcResponse.mefServices() != null && evcResponse.mefServices().uni() != null) {
347 activeEvcs.addAll(evcResponse.mefServices().uni().evc());
348 }
349 } catch (NetconfException | InterruptedException e1) {
350 log.warn("Error on removeFlowRules.", e1);
351 }
352
353 List<SourceAddressRange> saRangeList = new ArrayList<SourceAddressRange>();
354 Map<Integer, String> ceVlanMapMap = new HashMap<>();
355 Map<Integer, List<Short>> flowIdMap = new HashMap<>();
356
357 Collection<FlowRule> rulesRemoved = new HashSet<FlowRule>();
358 for (FlowRule ruleToRemove : rulesToRemove) {
359 // IP SA Filtering can only apply to Port 0 optics
360 if (ruleToRemove.selector().getCriterion(Type.IPV4_SRC) != null &&
361 ruleToRemove.selector().getCriterion(Type.IN_PORT) != null &&
362 ((PortCriterion) ruleToRemove.selector().getCriterion(Type.IN_PORT)).port().toLong() == 0) {
363 SourceAddressRange.SourceAddressRangeBuilder saBuilder =
364 new DefaultSourceAddressRange.SourceAddressRangeBuilder();
365 SourceAddressRange sar = saBuilder
366 .rangeId((short) ruleToRemove.tableId())
367 .yangSourceAddressRangeOpType(org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.
368 edge.assure.msea.sa.filtering.rev20160412.MseaSaFiltering.OnosYangOpType.DELETE)
369 .build();
370
371 rulesRemoved.add(ruleToRemove);
372 saRangeList.add(sar);
373
374 } else if (ruleToRemove.selector().getCriterion(Type.VLAN_VID) != null &&
375 ruleToRemove.selector().getCriterion(Type.IN_PORT) != null) {
376 PortNumber portNumber = ((PortCriterion) ruleToRemove.selector().getCriterion(Type.IN_PORT)).port();
377 VlanId vlanId = ((VlanIdCriterion) ruleToRemove.selector().getCriterion(Type.VLAN_VID)).vlanId();
378 int evcId = ruleToRemove.tableId();
379 int evcKey = (evcId << 2) + (int) portNumber.toLong();
380 String activeCeVlanMap = "";
381 //If this is one of many VLANs belonging to an EVC then we should only remove this VLAN
382 // from the ceVlanMap and not the whole EVC
383 if (!ceVlanMapMap.containsKey(evcKey)) {
384 for (Evc activeEvc:activeEvcs) {
385 if (activeEvc.evcIndex() == evcId) {
386 if (Ea1000Port.fromNum(portNumber.toLong()).nOrC(portAssignment) ==
387 UniSide.CUSTOMER) {
388 activeCeVlanMap = activeEvc.evcPerUni().evcPerUnic().ceVlanMap().string();
389 } else if (Ea1000Port.fromNum(portNumber.toLong()).nOrC(portAssignment) ==
390 UniSide.NETWORK) {
391 activeCeVlanMap = activeEvc.evcPerUni().evcPerUnin().ceVlanMap().string();
392 }
393 }
394 }
395 }
396
397 ceVlanMapMap.put(evcKey, CeVlanMapUtils.removeFromCeVlanMap(activeCeVlanMap, vlanId.id()));
398 if (!flowIdMap.containsKey(evcKey)) {
399 flowIdMap.put(evcKey, new ArrayList<>());
400 }
401 flowIdMap.get(evcKey).add(vlanId.id());
402 rulesRemoved.add(ruleToRemove);
403
404 } else {
405 log.info("Unexpected Flow Rule type removal: " + ruleToRemove);
406 }
407 }
408
409 //If there are IPv4 Flow Rules created commit them now through the
410 //MseaSaFiltering service
411 if (saRangeList.size() > 0) {
412 try {
413 mseaSaFilteringService.setMseaSaFiltering(
414 buildSaFilteringObject(saRangeList), session, TargetConfig.RUNNING);
415 } catch (NetconfException e) {
416 log.warn("Remove FlowRule on MseaSaFilteringService could not delete SARule - "
417 + "it may already have been deleted: " + e.getMessage());
418 }
419 }
420
421 if (ceVlanMapMap.size() > 0) {
422 try {
423 mseaUniEvcServiceSvc.removeEvcUniFlowEntries(ceVlanMapMap, flowIdMap,
424 session, TargetConfig.RUNNING, portAssignment);
425 } catch (NetconfException e) {
426 log.warn("Remove FlowRule on MseaUniEvcService could not delete EVC - "
427 + "it may already have been deleted: " + e.getMessage());
428 }
429 }
430
431 sessionMutex.release();
432 return rulesRemoved;
433 }
434
435 /**
436 * An internal method for extracting one EVC from a list and returning its ceVlanMap.
437 *
438 * @param evcList - the list of known EVCs
439 * @param evcIndex - the index of the EVC we're looking for
440 * @param side - the side of the UNI
441 * @return - the CEVlanMap we're looking for
442 */
443 private String getCeVlanMapForIdxFromEvcList(List<Evc> evcList, long evcIndex, UniSide side) {
444 if (evcList != null && evcList.size() > 0) {
445 for (Evc evc:evcList) {
446 if (evc.evcIndex() == evcIndex && evc.evcPerUni() != null) {
447 if (side == UniSide.CUSTOMER &&
448 evc.evcPerUni().evcPerUnic() != null &&
449 evc.evcPerUni().evcPerUnic().ceVlanMap() != null) {
450 return evc.evcPerUni().evcPerUnic().ceVlanMap().string();
451 } else if (side == UniSide.NETWORK &&
452 evc.evcPerUni().evcPerUnin() != null &&
453 evc.evcPerUni().evcPerUnin().ceVlanMap() != null) {
454 return evc.evcPerUni().evcPerUnin().ceVlanMap().string();
455 }
456 }
457 }
458 }
459
460 return ""; //The EVC required was not in the list
461 }
462
463 /**
464 * An internal method to convert from a FlowRule to SARange.
465 *
466 * @param frList A collection of flow rules
467 * @param saRangeList A list of SARanges
468 * @param fr A flow rule
469 */
470 private void parseFrForSaRange(Collection<FlowRule> frList, List<SourceAddressRange> saRangeList, FlowRule fr) {
471 String ipAddrStr = fr.selector().getCriterion(Type.IPV4_SRC).toString().substring(9);
472 log.debug("Applying IP address to " + ipAddrStr
473 + " (on Port 0) to IP SA Filtering on EA1000 through NETCONF");
474
475 SourceAddressRange.SourceAddressRangeBuilder saBuilder =
476 new DefaultSourceAddressRange.SourceAddressRangeBuilder();
477
478 SourceAddressRange sar = saBuilder
479 .rangeId((short) fr.tableId())
480 .name("Flow:" + fr.id().toString())
481 .ipv4AddressPrefix(ipAddrStr)
482 .build();
483
484 frList.add(fr);
485 saRangeList.add(sar);
486 }
487
488 private void parseFrForEvcs(Collection<FlowRule> frList, Map<Integer, Evc> evcMap,
489 List<Evc> activeEvcs, UniSideInterfaceAssignmentEnum portAssignment, FlowRule fr) {
490 //There could be many Flow Rules for one EVC depending on the ceVlanMap
491 //Cannot build up the EVC until we know the details - the key is the tableID and port
492 Ea1000Port port = Ea1000Port.fromNum(
493 ((PortCriterion) fr.selector().getCriterion(Type.IN_PORT)).port().toLong());
494 Integer evcKey = (fr.tableId() << 2) + port.portNum();
495 VlanId sourceVid = ((VlanIdCriterion) fr.selector().getCriterion(Type.VLAN_VID)).vlanId();
496 FlowMapping.FlowMappingBuilder fmBuilder =
497 DefaultFlowMapping.builder()
498 .ceVlanId(VlanIdType.of(sourceVid.id()))
499 .flowId(BigInteger.valueOf(fr.id().value()));
500 if (evcMap.containsKey(evcKey)) { //Is there an entry already for this EVC and port?
501 //Replace ceVlanMap
502 evcMap.put(evcKey, CustomEvc.builder(evcMap.get(evcKey))
503 .addToCeVlanMap(new ServiceListType(sourceVid.toString()), port.nOrC(portAssignment))
504 .addToFlowMapping(fmBuilder.build(), port.nOrC(portAssignment))
505 .build());
506
507 } else if (evcMap.containsKey((evcKey ^ 1))) { //Is there an entry for this EVC but the opposite port?
508 TagManipulation tm = getTagManipulation(fr);
509 if (port.nOrC(portAssignment) == UniSide.NETWORK) {
510 EvcPerUnin epun = CustomEvcPerUnin.builder(evcMap.get(evcKey ^ 1).evcPerUni().evcPerUnin())
511 .addToCeVlanMap(new ServiceListType(sourceVid.toString()))
512 .tagManipulation(tm)
513 .addToFlowMapping(fmBuilder.build())
514 .ingressBwpGroupIndex(getMeterId(fr.treatment()))
515 .build();
516 evcMap.put((evcKey ^ 1), CustomEvc.builder(evcMap.get((evcKey ^ 1))).addUniN(epun).build());
517 } else {
518 EvcPerUnic epuc = CustomEvcPerUnic.builder(evcMap.get(evcKey ^ 1).evcPerUni().evcPerUnic())
519 .addToCeVlanMap(new ServiceListType(sourceVid.toString()))
520 .tagManipulation(tm)
521 .addToFlowMapping(fmBuilder.build())
522 .ingressBwpGroupIndex(getMeterId(fr.treatment()))
523 .build();
524 evcMap.put((evcKey ^ 1), CustomEvc.builder(evcMap.get((evcKey ^ 1))).addUniC(epuc).build());
525 }
526 } else {
527 Evc.EvcBuilder evcBuilder = new DefaultEvc.EvcBuilder();
528 EvcPerUninBuilder epunBuilder = new CustomEvcPerUnin.EvcPerUninBuilder();
529 EvcPerUnicBuilder epucBuilder = new CustomEvcPerUnic.EvcPerUnicBuilder();
530 TagManipulation tm = getTagManipulation(fr);
531
532 UniSide side = port.nOrC(portAssignment);
533 String oldCeVlanMap = getCeVlanMapForIdxFromEvcList(activeEvcs, fr.tableId(), side);
534 String newCeVlanMap =
535 CeVlanMapUtils.addtoCeVlanMap(oldCeVlanMap, sourceVid.id());
536 String oppositeCeVlanMap =
537 getCeVlanMapForIdxFromEvcList(activeEvcs, fr.tableId(),
538 port.opposite().nOrC(portAssignment));
539 oppositeCeVlanMap = oppositeCeVlanMap.isEmpty() ? "0" : oppositeCeVlanMap;
540 if (side == UniSide.NETWORK) {
541 epunBuilder
542 .ceVlanMap(new ServiceListType(newCeVlanMap))
543 .tagManipulation(tm)
544 .addToFlowMapping(fmBuilder.build())
545 .ingressBwpGroupIndex(getMeterId(fr.treatment()));
546
547 epucBuilder.ceVlanMap(new ServiceListType(oppositeCeVlanMap));
548 } else {
549 epucBuilder
550 .ceVlanMap(new ServiceListType(newCeVlanMap))
551 .tagManipulation(tm)
552 .addToFlowMapping(fmBuilder.build())
553 .ingressBwpGroupIndex(getMeterId(fr.treatment()));
554
555 epunBuilder.ceVlanMap(new ServiceListType(oppositeCeVlanMap));
556 }
557
558 evcBuilder
559 .evcIndex(fr.tableId())
560 .name(new Identifier45("EVC-" + String.valueOf(fr.tableId())))
561 .evcPerUni(new DefaultEvcPerUni.EvcPerUniBuilder()
562 .evcPerUnin(epunBuilder.build())
563 .evcPerUnic(epucBuilder.build())
564 .build());
565 evcMap.put(evcKey, evcBuilder.build());
566 }
567
568 frList.add(fr);
569 }
570
571
572 private MseaSaFilteringOpParam buildSaFilteringObject(List<SourceAddressRange> saRangeList) {
573 InterfaceEth0.InterfaceEth0Builder ifBuilder = new DefaultInterfaceEth0.InterfaceEth0Builder();
574 for (SourceAddressRange sa:saRangeList) {
575 ifBuilder = ifBuilder.addToSourceAddressRange(sa);
576 }
577 InterfaceEth0 saIf = ifBuilder.filterAdminState(FilterAdminStateEnum.BLACKLIST).build();
578
579 SourceIpaddressFiltering.SourceIpaddressFilteringBuilder saFilterBuilder =
580 new DefaultSourceIpaddressFiltering.SourceIpaddressFilteringBuilder();
581 SourceIpaddressFiltering saFilter = saFilterBuilder.interfaceEth0(saIf).build();
582
583 MseaSaFilteringOpParam.MseaSaFilteringBuilder opBuilder =
584 new MseaSaFilteringOpParam.MseaSaFilteringBuilder();
585 MseaSaFilteringOpParam mseaSaFiltering =
586 (MseaSaFilteringOpParam) opBuilder.sourceIpaddressFiltering(saFilter).build();
587
588 return mseaSaFiltering;
589 }
590
591 private Collection<FlowEntry> convertSaFilteringToFlowRules(
592 MseaSaFiltering saFilteringCurrent, ApplicationId appId) {
593 Collection<FlowEntry> flowEntryCollection = new HashSet<FlowEntry>();
594
595 List<SourceAddressRange> saRangelist =
596 saFilteringCurrent.sourceIpaddressFiltering().interfaceEth0().sourceAddressRange();
597 Criterion matchInPort = Criteria.matchInPort(PortNumber.portNumber(0));
598 TrafficSelector.Builder tsBuilder = DefaultTrafficSelector.builder();
599
600 for (SourceAddressRange sa:saRangelist) {
601 Criterion matchIpSrc = Criteria.matchIPSrc(IpPrefix.valueOf(sa.ipv4AddressPrefix()));
602
603 TrafficSelector selector = tsBuilder.add(matchIpSrc).add(matchInPort).build();
604
605 TrafficTreatment.Builder trBuilder = DefaultTrafficTreatment.builder();
606 TrafficTreatment treatment = trBuilder.drop().build();
607
608 FlowRule.Builder feBuilder = new DefaultFlowRule.Builder();
609 if (sa.name() != null && sa.name().startsWith("Flow:")) {
610 String[] nameParts = sa.name().split(":");
611 Long cookie = Long.valueOf(nameParts[1], 16);
612 feBuilder = feBuilder.withCookie(cookie);
613 } else {
614 feBuilder = feBuilder.fromApp(appId);
615 }
616
617 FlowRule fr = feBuilder
618 .forDevice(handler().data().deviceId())
619 .withSelector(selector)
620 .withTreatment(treatment)
621 .forTable(sa.rangeId())
622 .makePermanent()
623 .withPriority(PRIORITY_DEFAULT)
624 .build();
625
626 flowEntryCollection.add(new DefaultFlowEntry(fr, FlowEntryState.ADDED, 0, 0, 0));
627 }
628
629 return flowEntryCollection;
630 }
631
632
633 private Collection<FlowEntry> convertEvcUniToFlowRules(
634 MseaUniEvcService uniEvcCurrent, UniSideInterfaceAssignmentEnum portAssignment) {
635 Collection<FlowEntry> flowEntryCollection = new HashSet<FlowEntry>();
636
637 if (uniEvcCurrent == null || uniEvcCurrent.mefServices() == null ||
638 uniEvcCurrent.mefServices().uni() == null || uniEvcCurrent.mefServices().uni().evc() == null) {
639 log.info("No EVC's found when getting flow rules");
640 return flowEntryCollection;
641 }
642
643 for (Evc evc:uniEvcCurrent.mefServices().uni().evc()) {
644 FlowRule.Builder frBuilder = new DefaultFlowRule.Builder();
645 TrafficSelector.Builder tsBuilder = DefaultTrafficSelector.builder();
646
647 TrafficTreatment uniNTreatment = treatmentForUniSde(evc.evcPerUni(), true);
648 //Depending on the ceVlanMap there may be multiple VLans and hence multiple flow entries
649 Short[] vlanIdsUniN =
650 CeVlanMapUtils.getVlanSet(ceVlanMapForUniSide(evc.evcPerUni(), true));
651 for (Short vlanId:vlanIdsUniN) {
652 if (vlanId == 0) {
653 continue;
654 }
655 Criterion uniNportCriterion = criterionPortForUniSide(portAssignment, true);
656 TrafficSelector tsUniN = tsBuilder.matchVlanId(VlanId.vlanId(vlanId)).add(uniNportCriterion).build();
657 long flowId = getFlowIdForVlan(evc.evcPerUni().evcPerUnin().flowMapping(), vlanId);
658
659 FlowRule frUniN = frBuilder
660 .forDevice(handler().data().deviceId())
661 .withSelector(tsUniN)
662 .withTreatment(uniNTreatment)
663 .forTable(new Long(evc.evcIndex()).intValue()) //narrowing to int
664 .makePermanent()
665 .withPriority(PRIORITY_DEFAULT)
666 .withCookie(flowId)
667 .build();
668 flowEntryCollection.add(new DefaultFlowEntry(frUniN, FlowEntryState.ADDED, 0, 0, 0));
669 }
670
671 TrafficTreatment uniCTreatment = treatmentForUniSde(evc.evcPerUni(), false);
672 //Depending on the ceVlanMap there may be multiple VLans and hence multiple flow entries
673 Short[] vlanIdsUniC =
674 CeVlanMapUtils.getVlanSet(ceVlanMapForUniSide(evc.evcPerUni(), false));
675 if (vlanIdsUniC != null && vlanIdsUniC.length > 0) {
676 for (Short vlanId:vlanIdsUniC) {
677 if (vlanId == 0) {
678 continue;
679 }
680 Criterion uniCportCriterion = criterionPortForUniSide(portAssignment, false);
681 TrafficSelector tsUniC =
682 tsBuilder.matchVlanId(VlanId.vlanId(vlanId)).add(uniCportCriterion).build();
683 long flowId = getFlowIdForVlan(evc.evcPerUni().evcPerUnic().flowMapping(), vlanId);
684
685 FlowRule frUniC = frBuilder
686 .forDevice(handler().data().deviceId())
687 .withSelector(tsUniC)
688 .withTreatment(uniCTreatment)
689 .forTable(new Long(evc.evcIndex()).intValue()) //narrowing to int
690 .makePermanent()
691 .withPriority(PRIORITY_DEFAULT)
692 .withCookie(flowId)
693 .build();
694 flowEntryCollection.add(new DefaultFlowEntry(frUniC, FlowEntryState.ADDED, 0, 0, 0));
695 }
696 }
697 }
698
699 return flowEntryCollection;
700 }
701
702 private long getFlowIdForVlan(List<FlowMapping> fmList, Short vlanId) {
703 if (fmList == null || vlanId == null) {
704 log.warn("Flow Mapping list is null when reading EVCs");
705 return -1L;
706 }
707 for (FlowMapping fm:fmList) {
708 if (fm.ceVlanId().uint16() == vlanId.intValue()) {
709 return fm.flowId().longValue();
710 }
711 }
712 return 0L;
713 }
714
715 private String ceVlanMapForUniSide(
716 EvcPerUni evcPerUni, boolean portN) {
717 if (portN) {
718 return evcPerUni.evcPerUnin().ceVlanMap().string();
719 } else {
720 return evcPerUni.evcPerUnic().ceVlanMap().string();
721 }
722 }
723
724 private Criterion criterionPortForUniSide(
725 UniSideInterfaceAssignmentEnum portAssignment, boolean portN) {
726 boolean cOnOptics = (portAssignment == UniSideInterfaceAssignmentEnum.UNI_C_ON_OPTICS);
727 int portNum = ((cOnOptics && portN) || (!cOnOptics && !portN)) ? 1 : 0;
728 return Criteria.matchInPort(PortNumber.portNumber(portNum));
729 }
730
731 private TrafficTreatment treatmentForUniSde(
732 EvcPerUni evcPerUni, boolean portN) {
733 TrafficTreatment.Builder trBuilder = DefaultTrafficTreatment.builder();
734
735 TagManipulation tm = null;
736 short meterId = 0;
737 if (portN) {
738 tm = evcPerUni.evcPerUnin().tagManipulation();
739 meterId = (short) evcPerUni.evcPerUnin().ingressBwpGroupIndex();
740 } else {
741 tm = evcPerUni.evcPerUnic().tagManipulation();
742 meterId = (short) evcPerUni.evcPerUnic().ingressBwpGroupIndex();
743 }
744
745 if (meterId > 0L) {
746 trBuilder = trBuilder.meter(MeterId.meterId((long) meterId));
747// trBuilder = trBuilder.meter(MeterId.meterId(meterId)).transition(0);
748 }
749
750 if (tm == null) {
751 return trBuilder.build(); //no tag manipulation found
752 }
753
754 if (tm.getClass().equals(DefaultTagPush.class)) {
755 VlanId pushVlanNum = VlanId.vlanId((short) ((TagPush) tm).tagPush().outerTagVlan().uint16());
756 PushTagTypeEnum pushTagType = ((TagPush) tm).tagPush().pushTagType();
757 //Note - the order of elements below MUST match the order of the Treatment in the stored FlowRule
758 // to be an exactMatch. See DefaultFlowRule.exactMatch()
759 trBuilder = trBuilder
760 .pushVlan(pushTagType.equals(PushTagTypeEnum.PUSHCTAG) ?
761 EtherType.VLAN.ethType() : EtherType.QINQ.ethType())
762 .setVlanId(pushVlanNum).transition(Integer.valueOf(0));
763
764 } else if (tm.getClass().equals(DefaultTagPop.class)) {
765 trBuilder = trBuilder.popVlan();
766
767 } else if (tm.getClass().equals(DefaultTagOverwrite.class)) {
768 TagOverwrite to = (TagOverwrite) tm;
769 VlanId ovrVlanNum = VlanId
770 .vlanId((short) (
771 //There are 2 classes TagOverwrite - the other one is already imported
772 to
773 .tagOverwrite()
774 .outerTagVlan()
775 .uint16()));
776 trBuilder = trBuilder.setVlanId(ovrVlanNum);
777
778 }
779
780 return trBuilder.build();
781 }
782
783 private static TagManipulation getTagManipulation(FlowRule fr) {
784 boolean isPop = false;
785 boolean isPush = false;
786 VlanId vlanId = null;
787 EthType ethType = EtherType.VLAN.ethType(); //Default
788 for (Instruction inst:fr.treatment().allInstructions()) {
789 if (inst.type() == Instruction.Type.L2MODIFICATION) {
790 L2ModificationInstruction l2Mod = (L2ModificationInstruction) inst;
791 if (l2Mod.subtype() == L2ModificationInstruction.L2SubType.VLAN_POP) {
792 isPop = true;
793 } else if (l2Mod.subtype() == L2ModificationInstruction.L2SubType.VLAN_PUSH) {
794 isPush = true;
795 ethType = ((ModVlanHeaderInstruction) l2Mod).ethernetType();
796 } else if (l2Mod.subtype() == L2ModificationInstruction.L2SubType.VLAN_ID) {
797 vlanId = ((ModVlanIdInstruction) l2Mod).vlanId();
798 }
799 }
800 }
801
802 if (isPop) {
803 //The should be no vlanId in this case
804 TagPop.TagPopBuilder popBuilder = new DefaultTagPop.TagPopBuilder();
805 org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.uni.evc
806 .service.rev20160317.mseaunievcservice.evcperuniextensionattributes.tagmanipulation
807 .tagpop.TagPop.TagPopBuilder popInnerBuilder =
808 new org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea
809 .uni.evc.service.rev20160317.mseaunievcservice.evcperuniextensionattributes
810 .tagmanipulation.tagpop.DefaultTagPop.TagPopBuilder();
811 return popBuilder
812 .tagPop(popInnerBuilder.build())
813 .build();
814
815 } else if (isPush && vlanId != null) {
816 TagPush.TagPushBuilder pushBuilder = new DefaultTagPush.TagPushBuilder();
817 org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.uni.evc
818 .service.rev20160317.mseaunievcservice.evcperuniextensionattributes.tagmanipulation
819 .tagpush.TagPush.TagPushBuilder pushInnerBuilder =
820 new org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea
821 .uni.evc.service.rev20160317.mseaunievcservice.evcperuniextensionattributes
822 .tagmanipulation.tagpush.DefaultTagPush.TagPushBuilder();
823 return pushBuilder
824 .tagPush(pushInnerBuilder
825 .outerTagVlan(new VlanIdType(vlanId.id()))
826 .pushTagType(ethType.equals(EtherType.VLAN.ethType()) ?
827 PushTagTypeEnum.PUSHCTAG : PushTagTypeEnum.PUSHSTAG)
828 .build())
829 .build();
830
831 } else if (vlanId != null) { //This is overwrite, as it has vlanId, but not push or pop
832 TagOverwrite.TagOverwriteBuilder ovrBuilder = new DefaultTagOverwrite.TagOverwriteBuilder();
833 org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.uni.evc
834 .service.rev20160317.mseaunievcservice.evcperuniextensionattributes.tagmanipulation
835 .tagoverwrite.TagOverwrite.TagOverwriteBuilder ovrInnerBuilder =
836 new org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea
837 .uni.evc.service.rev20160317.mseaunievcservice.evcperuniextensionattributes
838 .tagmanipulation.tagoverwrite.DefaultTagOverwrite.TagOverwriteBuilder();
839 return ovrBuilder.
840 tagOverwrite(ovrInnerBuilder
841 .outerTagVlan(new VlanIdType(vlanId.id()))
842 .build())
843 .build();
844 }
845
846 return null;
847 }
848
849 private static long getMeterId(TrafficTreatment treatment) {
850 return (treatment.metered() != null && treatment.metered().meterId() != null)
851 ? treatment.metered().meterId().id() : 0L;
852 }
853
854 /**
855 * An enumerated type that characterises the 2 port layout of the EA1000 device.
856 * The device is in an SFP package and has only 2 ports, the HOST port which
857 * plugs in to the chassis (Port 1) and the Optics Port on the rear (Port 0).
858 */
859 public enum Ea1000Port {
860 HOST(1),
861 OPTICS(0);
862
863 private int num = 0;
864 private Ea1000Port(int num) {
865 this.num = num;
866 }
867
868 /**
869 * The numerical assignment of this port.
870 * @return The port number
871 */
872 public int portNum() {
873 return num;
874 }
875
876 /**
877 * Return the enumerated value from a port number.
878 * @param num The port number
879 * @return An enumerated value
880 */
881 public static Ea1000Port fromNum(long num) {
882 for (Ea1000Port a:Ea1000Port.values()) {
883 if (a.num == num) {
884 return a;
885 }
886 }
887 return HOST;
888 }
889
890 /**
891 * Get the port that the UNI-N is present on.
892 * @param side The assignment of UNI-side to port
893 * @return An enumerated value
894 */
895 public static Ea1000Port uniNNum(UniSideInterfaceAssignmentEnum side) {
896 if (side.equals(UniSideInterfaceAssignmentEnum.UNI_C_ON_HOST)) {
897 return OPTICS;
898 } else {
899 return HOST;
900 }
901 }
902
903 /**
904 * Get the port that the UNI-C is present on.
905 * @param side The assignment of UNI-side to port
906 * @return An enumerated value
907 */
908 public static Ea1000Port uniCNum(UniSideInterfaceAssignmentEnum side) {
909 if (side.equals(UniSideInterfaceAssignmentEnum.UNI_C_ON_HOST)) {
910 return HOST;
911 } else {
912 return OPTICS;
913 }
914 }
915
916 /**
917 * Get the port opposite the current port.
918 * @return An enumerated value for the opposite side
919 */
920 public Ea1000Port opposite() {
921 if (this.equals(HOST)) {
922 return OPTICS;
923 } else {
924 return HOST;
925 }
926 }
927
928 /**
929 * Evaluate which side of the UNI on the EA1000 device this port refers to.
930 * @param side The assignment of UNI-side to port
931 * @return An enumerated value representing the UniSide
932 */
933 public UniSide nOrC(UniSideInterfaceAssignmentEnum side) {
934 if ((this == HOST && side == UniSideInterfaceAssignmentEnum.UNI_C_ON_HOST) ||
935 (this == OPTICS && side == UniSideInterfaceAssignmentEnum.UNI_C_ON_OPTICS)) {
936 return UniSide.CUSTOMER;
937 } else {
938 return UniSide.NETWORK;
939 }
940 }
941 }
942}