| /* |
| * Copyright 2016-present Open Networking Foundation |
| * |
| * 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 org.onosproject.segmentrouting.config; |
| |
| import com.fasterxml.jackson.databind.JsonNode; |
| import com.fasterxml.jackson.databind.node.JsonNodeFactory; |
| import com.fasterxml.jackson.databind.node.ObjectNode; |
| import com.google.common.collect.ImmutableSet; |
| import org.apache.felix.scr.annotations.Reference; |
| import org.apache.felix.scr.annotations.ReferenceCardinality; |
| import org.onlab.packet.MplsLabel; |
| import org.onlab.packet.VlanId; |
| import org.onosproject.cli.AbstractShellCommand; |
| import org.onosproject.core.ApplicationId; |
| import org.onosproject.net.ConnectPoint; |
| import org.onosproject.net.config.Config; |
| import org.onosproject.net.device.DeviceService; |
| import org.onosproject.net.intf.InterfaceService; |
| import org.onosproject.segmentrouting.pwaas.DefaultL2Tunnel; |
| import org.onosproject.segmentrouting.pwaas.DefaultL2TunnelDescription; |
| import org.onosproject.segmentrouting.pwaas.DefaultL2TunnelPolicy; |
| import org.onosproject.segmentrouting.pwaas.L2Mode; |
| import org.slf4j.Logger; |
| import org.slf4j.LoggerFactory; |
| |
| import java.util.HashMap; |
| import java.util.HashSet; |
| import java.util.Map; |
| import java.util.Set; |
| import java.util.stream.Collectors; |
| |
| /** |
| * App configuration object for Pwaas. |
| */ |
| public class PwaasConfig extends Config<ApplicationId> { |
| |
| @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) |
| public DeviceService deviceService; |
| |
| @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) |
| public InterfaceService intfService; |
| |
| private static Logger log = LoggerFactory |
| .getLogger(PwaasConfig.class); |
| |
| private static final String SRC_CP = "cP1"; |
| private static final String DST_CP = "cP2"; |
| private static final String SRC_OUTER_TAG = "cP1OuterTag"; |
| private static final String DST_OUTER_TAG = "cP2OuterTag"; |
| private static final String SRC_INNER_TAG = "cP1InnerTag"; |
| private static final String DST_INNER_TAG = "cP2InnerTag"; |
| private static final String MODE = "mode"; |
| private static final String SD_TAG = "sdTag"; |
| private static final String PW_LABEL = "pwLabel"; |
| |
| public PwaasConfig(DeviceService devS, InterfaceService intfS) { |
| |
| super(); |
| |
| deviceService = devS; |
| intfService = intfS; |
| } |
| |
| public PwaasConfig() { |
| |
| super(); |
| |
| deviceService = AbstractShellCommand.get(DeviceService.class); |
| intfService = AbstractShellCommand.get(InterfaceService.class); |
| } |
| /** |
| * Error message for missing parameters. |
| */ |
| private static final String MISSING_PARAMS = "Missing parameters in pseudo wire description"; |
| |
| /** |
| * Error message for invalid l2 mode. |
| */ |
| private static final String INVALID_L2_MODE = "Invalid pseudo wire mode"; |
| |
| /** |
| * Error message for invalid VLAN. |
| */ |
| private static final String INVALID_VLAN = "Vlan should be either int or */-"; |
| |
| /** |
| * Error message for invalid PW label. |
| */ |
| private static final String INVALID_PW_LABEL = "Pseudowire label should be an integer"; |
| |
| /** |
| * Verify if the pwaas configuration block is valid. |
| * |
| * Here we try to ensure that the provided pseudowires will get instantiated |
| * correctly in the network. We also check for any collisions with already used |
| * interfaces and also between different pseudowires. Most of the restrictions stem |
| * from the fact that all vlan matching is done in table 10 of ofdpa. |
| * |
| * @return true, if the configuration block is valid. |
| * False otherwise. |
| */ |
| @Override |
| public boolean isValid() { |
| |
| Set<DefaultL2TunnelDescription> pseudowires; |
| try { |
| pseudowires = getPwIds().stream() |
| .map(this::getPwDescription) |
| .collect(Collectors.toSet()); |
| |
| // check semantics now and return |
| return configurationValidity(pseudowires); |
| |
| } catch (IllegalArgumentException e) { |
| log.warn("{}", e.getMessage()); |
| return false; |
| } |
| } |
| |
| /** |
| * Helper method to verify if the tunnel is whether or not |
| * supported. |
| * |
| * @param l2Tunnel the tunnel to verify |
| * @return the result of the verification |
| */ |
| private void verifyTunnel(DefaultL2Tunnel l2Tunnel) { |
| |
| // Service delimiting tag not supported yet. |
| if (!l2Tunnel.sdTag().equals(VlanId.NONE)) { |
| throw new IllegalArgumentException(String.format("Service delimiting tag not supported yet for " + |
| "pseudowire %d.", l2Tunnel.tunnelId())); |
| } |
| |
| // Tag mode not supported yet. |
| if (l2Tunnel.pwMode() == L2Mode.TAGGED) { |
| throw new IllegalArgumentException(String.format("Tagged mode not supported yet for pseudowire %d.", |
| l2Tunnel.tunnelId())); |
| } |
| |
| // Raw mode without service delimiting tag |
| // is the only mode supported for now. |
| } |
| |
| /** |
| * Helper method to verify if the policy is whether or not |
| * supported and if policy will be successfully instantiated in the |
| * network. |
| * |
| * @param ingressInner the ingress inner tag |
| * @param ingressOuter the ingress outer tag |
| * @param egressInner the egress inner tag |
| * @param egressOuter the egress outer tag |
| * @return the result of verification |
| */ |
| private void verifyPolicy(ConnectPoint cP1, |
| ConnectPoint cP2, |
| VlanId ingressInner, |
| VlanId ingressOuter, |
| VlanId egressInner, |
| VlanId egressOuter, |
| Long tunnelId) { |
| |
| if (cP1.deviceId().equals(cP2.deviceId())) { |
| throw new IllegalArgumentException(String.format("Pseudowire connection points can not reside in the " + |
| "same node, in pseudowire %d.", tunnelId)); |
| } |
| |
| // We can have multiple tags, all of them can be NONE, |
| // indicating untagged traffic, however, the outer tag can |
| // not have value if the inner tag is None |
| if (ingressInner.equals(VlanId.NONE) && !ingressOuter.equals(VlanId.NONE)) { |
| throw new IllegalArgumentException(String.format("Inner tag should not be empty when " + |
| "outer tag is set for pseudowire %d for cP1.", |
| tunnelId)); |
| } |
| |
| if (egressInner.equals(VlanId.NONE) && !egressOuter.equals(VlanId.NONE)) { |
| throw new IllegalArgumentException(String.valueOf(String.format("Inner tag should not be empty when" + |
| " outer tag is set for pseudowire %d " + |
| "for cP2.", tunnelId))); |
| } |
| |
| if (ingressInner.equals(VlanId.ANY) || |
| ingressOuter.equals(VlanId.ANY) || |
| egressInner.equals(VlanId.ANY) || |
| egressOuter.equals(VlanId.ANY)) { |
| throw new IllegalArgumentException(String.valueOf(String.format("Wildcard VLAN matching not yet " + |
| "supported for pseudowire %d.", |
| tunnelId))); |
| } |
| |
| if (((!ingressOuter.equals(VlanId.NONE) && !ingressInner.equals(VlanId.NONE)) && |
| (egressOuter.equals(VlanId.NONE) && egressInner.equals(VlanId.NONE))) |
| || ((ingressOuter.equals(VlanId.NONE) && ingressInner.equals(VlanId.NONE)) && |
| (!egressOuter.equals(VlanId.NONE) && !egressInner.equals(VlanId.NONE)))) { |
| throw new IllegalArgumentException(String.valueOf(String.format("Support for double tag <-> untag is not" + |
| "supported for pseudowire %d.", |
| tunnelId))); |
| } |
| if ((!ingressInner.equals(VlanId.NONE) && |
| ingressOuter.equals(VlanId.NONE) && |
| !egressOuter.equals(VlanId.NONE)) |
| || (!ingressOuter.equals(VlanId.NONE) && |
| egressOuter.equals(VlanId.NONE) && |
| !ingressOuter.equals(VlanId.NONE))) { |
| throw new IllegalArgumentException(String.valueOf(String.format("Support for double-tag<->" + |
| "single-tag is not supported" + |
| " for pseudowire %d.", tunnelId))); |
| } |
| |
| if ((ingressInner.equals(VlanId.NONE) && !egressInner.equals(VlanId.NONE)) |
| || (!ingressInner.equals(VlanId.NONE) && egressInner.equals(VlanId.NONE))) { |
| throw new IllegalArgumentException(String.valueOf(String.format("single-tag <-> untag is not supported" + |
| " for pseudowire %d.", tunnelId))); |
| } |
| |
| |
| if (!ingressInner.equals(egressInner) && !ingressOuter.equals(egressOuter)) { |
| throw new IllegalArgumentException(String.valueOf(String.format("We do not support changing both tags " + |
| "in double tagged pws, only the outer," + |
| " for pseudowire %d.", tunnelId))); |
| } |
| |
| // check if cp1 and port of cp1 exist |
| if (deviceService.getDevice(cP1.deviceId()) == null) { |
| throw new IllegalArgumentException(String.valueOf(String.format("cP1 device %s does not exist for" + |
| " pseudowire %d.", cP1.deviceId(), |
| tunnelId))); |
| } |
| |
| if (deviceService.getPort(cP1) == null) { |
| throw new IllegalArgumentException(String.valueOf(String.format("Port %s for cP1 device %s does not" + |
| " exist for pseudowire %d.", cP1.port(), |
| cP1.deviceId(), tunnelId))); |
| } |
| |
| // check if cp2 and port of cp2 exist |
| if (deviceService.getDevice(cP2.deviceId()) == null) { |
| throw new IllegalArgumentException(String.valueOf(String.format("cP2 device %s does not exist for" + |
| " pseudowire %d.", cP2.deviceId(), |
| tunnelId))); |
| } |
| |
| if (deviceService.getPort(cP2) == null) { |
| throw new IllegalArgumentException(String.valueOf(String.format("Port %s for cP2 device %s does " + |
| "not exist for pseudowire %d.", |
| cP2.port(), cP2.deviceId(), tunnelId))); |
| } |
| } |
| |
| /** |
| * Verifies that the pseudowires will not conflict with each other. |
| * |
| * Further, check if vlans for connect points are already used. |
| * |
| * @param tunnel Tunnel for pw |
| * @param policy Policy for pw |
| * @param labelSet Label set used so far with this configuration |
| * @param vlanSet Vlan set used with this configuration |
| * @param tunnelSet Tunnel set used with this configuration |
| */ |
| private void verifyGlobalValidity(DefaultL2Tunnel tunnel, |
| DefaultL2TunnelPolicy policy, |
| Set<MplsLabel> labelSet, |
| Map<ConnectPoint, Set<VlanId>> vlanSet, |
| Set<Long> tunnelSet) { |
| |
| if (tunnelSet.contains(tunnel.tunnelId())) { |
| throw new IllegalArgumentException(String.valueOf(String.format("Tunnel Id %d already used by" + |
| " another pseudowire, in " + |
| "pseudowire %d!", tunnel.tunnelId(), |
| tunnel.tunnelId()))); |
| } |
| tunnelSet.add(tunnel.tunnelId()); |
| |
| // check if tunnel id is used again |
| ConnectPoint cP1 = policy.cP1(); |
| ConnectPoint cP2 = policy.cP2(); |
| |
| // insert cps to hashmap if this is the first time seen |
| if (!vlanSet.containsKey(cP1)) { |
| vlanSet.put(cP1, new HashSet<VlanId>()); |
| } |
| if (!vlanSet.containsKey(cP2)) { |
| vlanSet.put(cP2, new HashSet<VlanId>()); |
| } |
| |
| // if single tagged or untagged vlan is the inner |
| // if double tagged vlan is the outer |
| VlanId vlanToCheckCP1; |
| if (policy.cP1OuterTag().equals(VlanId.NONE)) { |
| vlanToCheckCP1 = policy.cP1InnerTag(); |
| } else { |
| vlanToCheckCP1 = policy.cP1OuterTag(); |
| } |
| |
| VlanId vlanToCheckCP2; |
| if (policy.cP2OuterTag().equals(VlanId.NONE)) { |
| vlanToCheckCP2 = policy.cP2InnerTag(); |
| } else { |
| vlanToCheckCP2 = policy.cP2OuterTag(); |
| } |
| |
| if (labelSet.contains(tunnel.pwLabel())) { |
| throw new IllegalArgumentException(String.valueOf(String.format("Label %s already used by another" + |
| " pseudowire, in pseudowire %d!", |
| tunnel.pwLabel(), tunnel.tunnelId()))); |
| } |
| labelSet.add(tunnel.pwLabel()); |
| |
| if (vlanSet.get(cP1).contains(vlanToCheckCP1)) { |
| throw new IllegalArgumentException(String.valueOf(String.format("Vlan '%s' for cP1 %s already used " + |
| "by another pseudowire, in pseudowire" + |
| " %d!", vlanToCheckCP1, cP1, |
| tunnel.tunnelId()))); |
| } |
| vlanSet.get(cP1).add(vlanToCheckCP1); |
| |
| if (vlanSet.get(cP2).contains(vlanToCheckCP2)) { |
| throw new IllegalArgumentException(String.valueOf(String.format("Vlan '%s' for cP2 %s already used" + |
| " by another pseudowire, in" + |
| " pseudowire %d!", vlanToCheckCP2, cP2, |
| tunnel.tunnelId()))); |
| } |
| vlanSet.get(cP2).add(vlanToCheckCP2); |
| |
| // check that vlans for the connect points are not used |
| intfService.getInterfacesByPort(cP1).stream() |
| .forEach(intf -> { |
| |
| // check if tagged pw affects tagged interface |
| if (intf.vlanTagged().contains(vlanToCheckCP1)) { |
| throw new IllegalArgumentException(String.valueOf(String.format("Vlan '%s' for cP1 %s already" + |
| " used for this interface, in" + |
| " pseudowire %d!", |
| vlanToCheckCP1, cP1, |
| tunnel.tunnelId()))); |
| } |
| |
| // if vlanNative != null this interface is configured with untagged traffic also |
| // check if it collides with untagged interface |
| if ((intf.vlanNative() != null) && vlanToCheckCP1.equals(VlanId.NONE)) { |
| throw new IllegalArgumentException(String.valueOf(String.format("Untagged traffic for cP1 " + |
| "%s already used for this " + |
| "interface, in pseudowire " + |
| "%d!", cP1, |
| tunnel.tunnelId()))); |
| } |
| |
| // if vlanUntagged != null this interface is configured only with untagged traffic |
| // check if it collides with untagged interface |
| if ((intf.vlanUntagged() != null) && vlanToCheckCP1.equals(VlanId.NONE)) { |
| throw new IllegalArgumentException(String.valueOf(String.format("Untagged traffic for " + |
| "cP1 %s already" + |
| " used for this interface," + |
| " in pseudowire %d!", |
| cP1, tunnel.tunnelId()))); |
| } |
| }); |
| |
| intfService.getInterfacesByPort(cP2).stream() |
| .forEach(intf -> { |
| if (intf.vlanTagged().contains(vlanToCheckCP2)) { |
| throw new IllegalArgumentException(String.valueOf(String.format("Vlan '%s' for cP2 %s already" + |
| " used for this interface, " + |
| "in pseudowire %d!", |
| vlanToCheckCP2, cP2, |
| tunnel.tunnelId()))); |
| } |
| |
| // if vlanNative != null this interface is configured with untagged traffic also |
| // check if it collides with untagged interface |
| if ((intf.vlanNative() != null) && vlanToCheckCP2.equals(VlanId.NONE)) { |
| throw new IllegalArgumentException(String.valueOf(String.format("Untagged traffic for cP2 %s " + |
| "already used for this" + |
| " interface, " + |
| "in pseudowire %d!", |
| cP2, tunnel.tunnelId()))); |
| } |
| |
| // if vlanUntagged != null this interface is configured only with untagged traffic |
| // check if it collides with untagged interface |
| if ((intf.vlanUntagged() != null) && vlanToCheckCP2.equals(VlanId.NONE)) { |
| throw new IllegalArgumentException(String.valueOf(String.format("Untagged traffic for cP2 %s" + |
| " already" + |
| " used for this interface, " + |
| "in pseudowire %d!", |
| cP2, tunnel.tunnelId()))); |
| } |
| }); |
| |
| } |
| |
| /** |
| * Helper method to verify the integrity of the pseudo wire. |
| * |
| * @param l2TunnelDescription the pseudo wire description |
| * @return the result of the check |
| */ |
| private void verifyPseudoWire(DefaultL2TunnelDescription l2TunnelDescription, |
| Set<MplsLabel> labelSet, |
| Map<ConnectPoint, Set<VlanId>> vlanset, |
| Set<Long> tunnelSet) { |
| |
| DefaultL2Tunnel l2Tunnel = l2TunnelDescription.l2Tunnel(); |
| DefaultL2TunnelPolicy l2TunnelPolicy = l2TunnelDescription.l2TunnelPolicy(); |
| |
| verifyTunnel(l2Tunnel); |
| |
| verifyPolicy( |
| l2TunnelPolicy.cP1(), |
| l2TunnelPolicy.cP2(), |
| l2TunnelPolicy.cP1InnerTag(), |
| l2TunnelPolicy.cP1OuterTag(), |
| l2TunnelPolicy.cP2InnerTag(), |
| l2TunnelPolicy.cP2OuterTag(), |
| l2Tunnel.tunnelId() |
| ); |
| |
| verifyGlobalValidity(l2Tunnel, |
| l2TunnelPolicy, |
| labelSet, |
| vlanset, |
| tunnelSet); |
| |
| } |
| |
| /** |
| * Checks if the configured pseudowires will create problems in the network. |
| * If yes, then no pseudowires is deployed from this configuration. |
| * |
| * @param pseudowires Set of pseudowries to validate |
| * @return returns true if everything goes well. |
| */ |
| public boolean configurationValidity(Set<DefaultL2TunnelDescription> pseudowires) { |
| |
| // structures to keep pw information |
| // in order to see if instantiating them will create |
| // problems |
| Set<Long> tunIds = new HashSet<>(); |
| Set<MplsLabel> labelsUsed = new HashSet<>(); |
| Map<ConnectPoint, Set<VlanId>> vlanIds = new HashMap<>(); |
| |
| // check that pseudowires can be instantiated in the network |
| // we try to guarantee that all the pws will work before |
| // instantiating any of them |
| for (DefaultL2TunnelDescription pw : pseudowires) { |
| verifyPseudoWire(pw, labelsUsed, vlanIds, tunIds); |
| } |
| |
| return true; |
| } |
| |
| /** |
| * Returns all pseudo wire keys. |
| * |
| * @return all keys (tunnels id) |
| * @throws IllegalArgumentException if wrong format |
| */ |
| public Set<Long> getPwIds() { |
| ImmutableSet.Builder<Long> builder = ImmutableSet.builder(); |
| object.fields().forEachRemaining(entry -> { |
| Long tunnelId = Long.parseLong(entry.getKey()); |
| builder.add(tunnelId); |
| }); |
| return builder.build(); |
| } |
| |
| /** |
| * Parses a vlan as a string. Returns the VlanId if |
| * provided String can be parsed as an integer or is '' / '*' |
| * |
| * @param vlan string as read from configuration |
| * @return VlanId |
| * @throws IllegalArgumentException if wrong format of vlan |
| */ |
| public VlanId parseVlan(String vlan) { |
| |
| if (vlan.equals("*") || vlan.equals("Any")) { |
| return VlanId.vlanId("Any"); |
| } else if (vlan.equals("") || vlan.equals("None")) { |
| return VlanId.vlanId("None"); |
| } else { |
| try { |
| VlanId newVlan = VlanId.vlanId(vlan); |
| return newVlan; |
| } catch (IllegalArgumentException e) { |
| throw new IllegalArgumentException(INVALID_VLAN); |
| } |
| } |
| } |
| |
| /** |
| * |
| * @param mode RAW or TAGGED |
| * @return the L2Mode if input is correct |
| * @throws IllegalArgumentException if not supported mode |
| */ |
| public L2Mode parseMode(String mode) { |
| |
| if (!mode.equals("RAW") && !mode.equals("TAGGED")) { |
| throw new IllegalArgumentException(INVALID_L2_MODE); |
| } |
| |
| return L2Mode.valueOf(mode); |
| } |
| |
| /** |
| * |
| * @param label the mpls label of the pseudowire |
| * @return the MplsLabel |
| * @throws IllegalArgumentException if label is invalid |
| */ |
| public MplsLabel parsePWLabel(String label) { |
| |
| try { |
| MplsLabel pwLabel = MplsLabel.mplsLabel(label); |
| return pwLabel; |
| } catch (Exception e) { |
| throw new IllegalArgumentException(INVALID_PW_LABEL); |
| } |
| } |
| |
| /** |
| * Returns pw description of given pseudo wire id. |
| * |
| * @param tunnelId pseudo wire key |
| * @return set of l2 tunnel descriptions |
| * @throws IllegalArgumentException if wrong format |
| */ |
| public DefaultL2TunnelDescription getPwDescription(Long tunnelId) { |
| JsonNode pwDescription = object.get(tunnelId.toString()); |
| if (!hasFields((ObjectNode) pwDescription, |
| SRC_CP, SRC_INNER_TAG, SRC_OUTER_TAG, |
| DST_CP, DST_INNER_TAG, DST_OUTER_TAG, |
| MODE, SD_TAG, PW_LABEL)) { |
| throw new IllegalArgumentException(MISSING_PARAMS); |
| } |
| String tempString; |
| |
| tempString = pwDescription.get(SRC_CP).asText(); |
| ConnectPoint srcCp = ConnectPoint.deviceConnectPoint(tempString); |
| |
| tempString = pwDescription.get(DST_CP).asText(); |
| ConnectPoint dstCp = ConnectPoint.deviceConnectPoint(tempString); |
| |
| tempString = pwDescription.get(SRC_INNER_TAG).asText(); |
| VlanId srcInnerTag = parseVlan(tempString); |
| |
| tempString = pwDescription.get(SRC_OUTER_TAG).asText(); |
| VlanId srcOuterTag = parseVlan(tempString); |
| |
| tempString = pwDescription.get(DST_INNER_TAG).asText(); |
| VlanId dstInnerTag = parseVlan(tempString); |
| |
| tempString = pwDescription.get(DST_OUTER_TAG).asText(); |
| VlanId dstOuterTag = parseVlan(tempString); |
| |
| tempString = pwDescription.get(MODE).asText(); |
| L2Mode l2Mode = parseMode(tempString); |
| |
| tempString = pwDescription.get(SD_TAG).asText(); |
| VlanId sdTag = parseVlan(tempString); |
| |
| tempString = pwDescription.get(PW_LABEL).asText(); |
| MplsLabel pwLabel = parsePWLabel(tempString); |
| |
| DefaultL2Tunnel l2Tunnel = new DefaultL2Tunnel( |
| l2Mode, |
| sdTag, |
| tunnelId, |
| pwLabel |
| ); |
| |
| DefaultL2TunnelPolicy l2TunnelPolicy = new DefaultL2TunnelPolicy( |
| tunnelId, |
| srcCp, |
| srcInnerTag, |
| srcOuterTag, |
| dstCp, |
| dstInnerTag, |
| dstOuterTag |
| ); |
| |
| return new DefaultL2TunnelDescription(l2Tunnel, l2TunnelPolicy); |
| } |
| |
| /** |
| * Removes a pseudowire from the configuration tree. |
| * @param pwId Pseudowire id |
| * @return null if pwId did not exist, or the object representing the |
| * udpated configuration tree |
| */ |
| public ObjectNode removePseudowire(String pwId) { |
| |
| JsonNode value = object.remove(pwId); |
| if (value == null) { |
| return (ObjectNode) value; |
| } else { |
| return object; |
| } |
| } |
| |
| /** |
| * Adds a pseudowire to the configuration tree of pwwas. It also checks |
| * if the configuration is valid, if not return null and does not add the node, |
| * if yes return the new configuration. Caller will propagate update events. |
| * |
| * If the pseudowire already exists in the configuration it gets updated. |
| * |
| * @param tunnelId Id of tunnel |
| * @param pwLabel PW label of tunnel |
| * @param cP1 Connection point 1 |
| * @param cP1InnerVlan Inner vlan of cp1 |
| * @param cP1OuterVlan Outer vlan of cp2 |
| * @param cP2 Connection point 2 |
| * @param cP2InnerVlan Inner vlan of cp2 |
| * @param cP2OuterVlan Outer vlan of cp2 |
| * @param mode Mode for the pw |
| * @param sdTag Service delimiting tag for the pw |
| * @return The ObjectNode config if configuration is valid with the new pseudowire |
| * or null. |
| */ |
| public ObjectNode addPseudowire(String tunnelId, String pwLabel, String cP1, |
| String cP1InnerVlan, String cP1OuterVlan, String cP2, |
| String cP2InnerVlan, String cP2OuterVlan, |
| String mode, String sdTag) { |
| |
| |
| ObjectNode newPw = new ObjectNode(JsonNodeFactory.instance); |
| |
| // add fields for pseudowire |
| newPw.put(SRC_CP, cP1); |
| newPw.put(DST_CP, cP2); |
| newPw.put(PW_LABEL, pwLabel); |
| newPw.put(SRC_INNER_TAG, cP1InnerVlan); |
| newPw.put(SRC_OUTER_TAG, cP1OuterVlan); |
| newPw.put(DST_INNER_TAG, cP2InnerVlan); |
| newPw.put(DST_OUTER_TAG, cP2OuterVlan); |
| newPw.put(SD_TAG, sdTag); |
| newPw.put(MODE, mode); |
| |
| object.set(tunnelId, newPw); |
| |
| if (!isValid()) { |
| log.info("Pseudowire could not be created : {}"); |
| object.remove(tunnelId); |
| return null; |
| } |
| |
| return object; |
| } |
| } |