00a1a6121847371d191c2a9c0f816d4edd0aa7e6
[ovsdb.git] / southbound / southbound-impl / src / main / java / org / opendaylight / ovsdb / southbound / transactions / md / OvsdbPortUpdateCommand.java
1 /*
2  * Copyright (c) 2014, 2017 Intel Corp. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8
9 package org.opendaylight.ovsdb.southbound.transactions.md;
10
11 import static org.opendaylight.ovsdb.southbound.SouthboundUtil.schemaMismatchLog;
12
13 import com.google.common.annotations.VisibleForTesting;
14 import com.google.common.base.Optional;
15 import java.util.ArrayList;
16 import java.util.Collection;
17 import java.util.Iterator;
18 import java.util.List;
19 import java.util.Map;
20 import java.util.Map.Entry;
21 import java.util.Set;
22
23 import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
24 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
25 import org.opendaylight.ovsdb.lib.error.ColumnSchemaNotFoundException;
26 import org.opendaylight.ovsdb.lib.error.SchemaVersionMismatchException;
27 import org.opendaylight.ovsdb.lib.message.TableUpdates;
28 import org.opendaylight.ovsdb.lib.notation.Column;
29 import org.opendaylight.ovsdb.lib.notation.UUID;
30 import org.opendaylight.ovsdb.lib.schema.DatabaseSchema;
31 import org.opendaylight.ovsdb.lib.schema.GenericTableSchema;
32 import org.opendaylight.ovsdb.lib.schema.typed.TyperUtils;
33 import org.opendaylight.ovsdb.schema.openvswitch.Bridge;
34 import org.opendaylight.ovsdb.schema.openvswitch.Interface;
35 import org.opendaylight.ovsdb.schema.openvswitch.Port;
36 import org.opendaylight.ovsdb.schema.openvswitch.Qos;
37 import org.opendaylight.ovsdb.southbound.InstanceIdentifierCodec;
38 import org.opendaylight.ovsdb.southbound.OvsdbConnectionInstance;
39 import org.opendaylight.ovsdb.southbound.SouthboundConstants;
40 import org.opendaylight.ovsdb.southbound.SouthboundMapper;
41 import org.opendaylight.ovsdb.southbound.SouthboundUtil;
42 import org.opendaylight.ovsdb.utils.mdsal.utils.TransactionType;
43 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Uri;
44 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.MacAddress;
45 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.VlanId;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbNodeAugmentation;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbPortInterfaceAttributes;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbQosRef;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbTerminationPointAugmentation;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbTerminationPointAugmentationBuilder;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.ManagedNodeEntry;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.QosEntries;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.QosEntriesKey;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.InterfaceBfd;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.InterfaceBfdBuilder;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.InterfaceBfdKey;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.InterfaceBfdStatus;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.InterfaceBfdStatusBuilder;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.InterfaceBfdStatusKey;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.InterfaceExternalIds;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.InterfaceExternalIdsBuilder;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.InterfaceLldp;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.InterfaceLldpBuilder;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.InterfaceLldpKey;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.InterfaceOtherConfigs;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.InterfaceOtherConfigsBuilder;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.Options;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.OptionsBuilder;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.OptionsKey;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.PortExternalIds;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.PortExternalIdsBuilder;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.PortOtherConfigs;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.PortOtherConfigsBuilder;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.QosEntry;
76 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.QosEntryBuilder;
77 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.QosEntryKey;
78 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.Trunks;
79 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.TrunksBuilder;
80 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
81 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
82 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TpId;
83 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
84 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
85 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
86 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeKey;
87 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPoint;
88 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPointBuilder;
89 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPointKey;
90 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
91 import org.slf4j.Logger;
92 import org.slf4j.LoggerFactory;
93
94 public class OvsdbPortUpdateCommand extends AbstractTransactionCommand {
95     private static final Logger LOG = LoggerFactory.getLogger(OvsdbPortUpdateCommand.class);
96
97     private final InstanceIdentifierCodec instanceIdentifierCodec;
98     private final Map<UUID, Port> portUpdatedRows;
99     private final Map<UUID, Port> portOldRows;
100     private final Map<UUID, Interface> interfaceUpdatedRows;
101     private final Map<UUID, Interface> interfaceOldRows;
102     private final Map<UUID, Bridge> bridgeUpdatedRows;
103     private final Map<UUID, Qos> qosUpdatedRows;
104
105     public OvsdbPortUpdateCommand(InstanceIdentifierCodec instanceIdentifierCodec, OvsdbConnectionInstance key,
106             TableUpdates updates, DatabaseSchema dbSchema) {
107         super(key, updates, dbSchema);
108         this.instanceIdentifierCodec = instanceIdentifierCodec;
109         portUpdatedRows = TyperUtils.extractRowsUpdated(Port.class, updates, dbSchema);
110         portOldRows = TyperUtils.extractRowsOld(Port.class, updates, dbSchema);
111         interfaceUpdatedRows = TyperUtils.extractRowsUpdated(Interface.class, updates, dbSchema);
112         interfaceOldRows = TyperUtils.extractRowsOld(Interface.class, updates, dbSchema);
113         bridgeUpdatedRows = TyperUtils.extractRowsUpdated(Bridge.class, updates, dbSchema);
114         qosUpdatedRows = TyperUtils.extractRowsUpdated(Qos.class, updates, dbSchema);
115     }
116
117     @Override
118     public void execute(ReadWriteTransaction transaction) {
119         final InstanceIdentifier<Node> connectionIId = getOvsdbConnectionInstance().getInstanceIdentifier();
120         if (portUpdatedRows == null && interfaceOldRows == null
121                 || interfaceOldRows.isEmpty() && portUpdatedRows.isEmpty()) {
122             return;
123         }
124         Optional<Node> node = readNode(transaction, connectionIId);
125         if (node.isPresent()) {
126             updateTerminationPoints(transaction, node.get());
127         }
128     }
129
130     @VisibleForTesting
131     void updateTerminationPoints(ReadWriteTransaction transaction, Node node) {
132         for (Entry<UUID, Port> portUpdate : portUpdatedRows.entrySet()) {
133             String portName = null;
134             portName = portUpdate.getValue().getNameColumn().getData();
135             Optional<InstanceIdentifier<Node>> bridgeIid = getTerminationPointBridge(portUpdate.getKey());
136             if (!bridgeIid.isPresent()) {
137                 bridgeIid = getTerminationPointBridge(transaction, node, portName);
138             }
139             if (bridgeIid.isPresent()) {
140                 NodeId bridgeId = SouthboundMapper.createManagedNodeId(bridgeIid.get());
141                 TerminationPointKey tpKey = new TerminationPointKey(new TpId(portName));
142                 TerminationPointBuilder tpBuilder = new TerminationPointBuilder();
143                 tpBuilder.withKey(tpKey);
144                 tpBuilder.setTpId(tpKey.getTpId());
145                 InstanceIdentifier<TerminationPoint> tpPath =
146                         getInstanceIdentifier(bridgeIid.get(), portUpdate.getValue());
147                 OvsdbTerminationPointAugmentationBuilder tpAugmentationBuilder =
148                         new OvsdbTerminationPointAugmentationBuilder();
149                 buildTerminationPoint(transaction, tpPath, tpAugmentationBuilder, node, portUpdate);
150                 UUID interfaceUuid = (UUID)portUpdate.getValue().getInterfacesColumn().getData().toArray()[0];
151                 if (interfaceUpdatedRows.containsKey(interfaceUuid)) {
152                     buildTerminationPoint(tpAugmentationBuilder, interfaceUpdatedRows.get(interfaceUuid));
153                     interfaceUpdatedRows.remove(interfaceUuid);
154                     interfaceOldRows.remove(interfaceUuid);
155                 }
156                 tpBuilder.addAugmentation(OvsdbTerminationPointAugmentation.class, tpAugmentationBuilder.build());
157                 if (portOldRows.containsKey(portUpdate.getKey()) && !portQosCleared(portUpdate)) {
158                     updateToDataStore(transaction, tpBuilder, tpPath, true);
159                     LOG.info("DEVICE - {} TerminationPoint : {} to Bridge : {}", TransactionType.ADD,
160                             tpKey.getTpId().getValue(), bridgeId.getValue());
161                 } else {
162                     updateToDataStore(transaction, tpBuilder, tpPath, false);
163                     LOG.debug("DEVICE - {} TerminationPoint : {} to Bridge : {}", TransactionType.UPDATE,
164                             tpKey.getTpId().getValue(), bridgeId.getValue());
165                 }
166             }
167         }
168         for (Entry<UUID, Interface> interfaceUpdate : interfaceUpdatedRows.entrySet()) {
169             String interfaceName = null;
170             interfaceName = interfaceUpdatedRows.get(interfaceUpdate.getKey()).getNameColumn().getData();
171             Optional<InstanceIdentifier<Node>> bridgeIid = getTerminationPointBridge(transaction, node, interfaceName);
172             if (bridgeIid.isPresent()) {
173                 TerminationPointKey tpKey = new TerminationPointKey(new TpId(interfaceName));
174                 TerminationPointBuilder tpBuilder = new TerminationPointBuilder();
175                 tpBuilder.withKey(tpKey);
176                 tpBuilder.setTpId(tpKey.getTpId());
177                 OvsdbTerminationPointAugmentationBuilder tpAugmentationBuilder =
178                         new OvsdbTerminationPointAugmentationBuilder();
179                 buildTerminationPoint(tpAugmentationBuilder, interfaceUpdate.getValue());
180                 tpBuilder.addAugmentation(OvsdbTerminationPointAugmentation.class, tpAugmentationBuilder.build());
181                 NodeId bridgeId = SouthboundMapper.createManagedNodeId(bridgeIid.get());
182                 InstanceIdentifier<TerminationPoint> tpPath = InstanceIdentifier
183                         .create(NetworkTopology.class)
184                         .child(Topology.class, new TopologyKey(SouthboundConstants.OVSDB_TOPOLOGY_ID))
185                         .child(Node.class,new NodeKey(bridgeId))
186                         .child(TerminationPoint.class,tpKey);
187                 updateToDataStore(transaction, tpBuilder, tpPath, true);
188             }
189         }
190
191     }
192
193     protected void updateToDataStore(ReadWriteTransaction transaction, TerminationPointBuilder tpBuilder,
194                                      InstanceIdentifier<TerminationPoint> tpPath, boolean merge) {
195         if (merge) {
196             transaction.merge(LogicalDatastoreType.OPERATIONAL,
197                     tpPath, tpBuilder.build());
198         } else {
199             transaction.put(LogicalDatastoreType.OPERATIONAL,
200                     tpPath, tpBuilder.build());
201         }
202     }
203
204     @VisibleForTesting
205     void buildTerminationPoint(ReadWriteTransaction transaction,
206             InstanceIdentifier<TerminationPoint> tpPath,
207             OvsdbTerminationPointAugmentationBuilder tpAugmentationBuilder,
208             Node node, Entry<UUID, Port> portUpdate) {
209
210         tpAugmentationBuilder
211                 .setName(portUpdate.getValue().getName());
212         tpAugmentationBuilder.setPortUuid(new Uuid(
213                 portUpdate.getValue().getUuid().toString()));
214         updatePort(transaction, node, tpPath, portUpdate, tpAugmentationBuilder);
215     }
216
217     private void buildTerminationPoint(OvsdbTerminationPointAugmentationBuilder tpAugmentationBuilder,
218             Interface interfaceUpdate) {
219
220         tpAugmentationBuilder
221                 .setName(interfaceUpdate.getName());
222         tpAugmentationBuilder.setInterfaceUuid(new Uuid(
223                 interfaceUpdate.getUuid().toString()));
224         updateInterfaces(interfaceUpdate, tpAugmentationBuilder);
225     }
226
227     @SuppressWarnings("IllegalCatch")
228     private Optional<Node> readNode(final ReadWriteTransaction transaction, final InstanceIdentifier<Node> nodePath) {
229         Optional<Node> node = Optional.absent();
230         try {
231             node = SouthboundUtil.readNode(transaction, nodePath);
232         } catch (Exception exp) {
233             LOG.error("Error in getting the Node for {}", nodePath, exp);
234         }
235         return node;
236     }
237
238     private Optional<InstanceIdentifier<Node>> getTerminationPointBridge(UUID portUuid) {
239         for (Entry<UUID, Bridge> entry : this.bridgeUpdatedRows.entrySet()) {
240             UUID bridgeUuid = entry.getKey();
241             if (entry.getValue().getPortsColumn().getData().contains(portUuid)) {
242                 return Optional.of(
243                         SouthboundMapper.createInstanceIdentifier(instanceIdentifierCodec, getOvsdbConnectionInstance(),
244                                 this.bridgeUpdatedRows.get(bridgeUuid)));
245             }
246         }
247         return Optional.absent();
248     }
249
250     @SuppressWarnings("unchecked")
251     private Optional<InstanceIdentifier<Node>> getTerminationPointBridge(
252             final ReadWriteTransaction transaction, Node node, String tpName) {
253         OvsdbNodeAugmentation ovsdbNode = node.augmentation(OvsdbNodeAugmentation.class);
254         List<ManagedNodeEntry> managedNodes = ovsdbNode.getManagedNodeEntry();
255         TpId tpId = new TpId(tpName);
256
257         for (ManagedNodeEntry managedNodeEntry : managedNodes) {
258             Optional<Node> optManagedNode = SouthboundUtil.readNode(transaction,
259                     (InstanceIdentifier<Node>)managedNodeEntry.getBridgeRef().getValue());
260             if (optManagedNode.isPresent()) {
261                 Node managedNode = optManagedNode.get();
262                 List<TerminationPoint> tpEntrys = managedNode.getTerminationPoint();
263                 if (tpEntrys != null) {
264                     for (TerminationPoint tpEntry : tpEntrys) {
265                         if (tpId.equals(tpEntry.getTpId())) {
266                             return Optional.of((InstanceIdentifier<Node>) managedNodeEntry.getBridgeRef().getValue());
267                         }
268                     }
269                 }
270             }
271         }
272
273         return Optional.absent();
274     }
275
276     @VisibleForTesting
277     void updateInterfaces(Interface interfaceUpdate,
278             final OvsdbTerminationPointAugmentationBuilder ovsdbTerminationPointBuilder) {
279
280         Column<GenericTableSchema, String> typeColumn = interfaceUpdate.getTypeColumn();
281         String type = typeColumn.getData();
282         updateInterface(interfaceUpdate, type,ovsdbTerminationPointBuilder);
283     }
284
285     @VisibleForTesting
286     void updatePort(final ReadWriteTransaction transaction, final Node node,
287             final InstanceIdentifier<TerminationPoint> tpPath, final Entry<UUID, Port> port,
288             final OvsdbTerminationPointAugmentationBuilder ovsdbTerminationPointBuilder) {
289
290         updateVlan(port.getValue(), ovsdbTerminationPointBuilder);
291         updateVlanTrunks(port.getValue(), ovsdbTerminationPointBuilder);
292         updateVlanMode(port.getValue(), ovsdbTerminationPointBuilder);
293         updateQos(transaction, node, tpPath, port, ovsdbTerminationPointBuilder);
294         updatePortExternalIds(port.getValue(), ovsdbTerminationPointBuilder);
295         updatePortOtherConfig(port.getValue(), ovsdbTerminationPointBuilder);
296     }
297
298     @VisibleForTesting
299     void updateInterface(final Interface interf,
300             final String type,
301             final OvsdbTerminationPointAugmentationBuilder ovsdbTerminationPointBuilder) {
302
303         ovsdbTerminationPointBuilder.setInterfaceUuid(
304                 new Uuid(interf.getUuid().toString()));
305         ovsdbTerminationPointBuilder.setInterfaceType(
306                 SouthboundMapper.createInterfaceType(type));
307         updateIfIndex(interf, ovsdbTerminationPointBuilder);
308         updateMac(interf, ovsdbTerminationPointBuilder);
309         updateMacInUse(interf, ovsdbTerminationPointBuilder);
310         updateOfPort(interf, ovsdbTerminationPointBuilder);
311         updateOfPortRequest(interf, ovsdbTerminationPointBuilder);
312         updateInterfaceExternalIds(interf, ovsdbTerminationPointBuilder);
313         updateOptions(interf, ovsdbTerminationPointBuilder);
314         updateInterfaceOtherConfig(interf, ovsdbTerminationPointBuilder);
315         updateInterfaceLldp(interf, ovsdbTerminationPointBuilder);
316         updateInterfaceBfd(interf, ovsdbTerminationPointBuilder);
317         updateInterfaceBfdStatus(interf, ovsdbTerminationPointBuilder);
318         updateInterfacePolicing(interf, ovsdbTerminationPointBuilder);
319     }
320
321     @VisibleForTesting
322     void updateVlan(final Port port,
323             final OvsdbTerminationPointAugmentationBuilder ovsdbTerminationPointBuilder) {
324
325         Collection<Long> vlanId = port.getTagColumn().getData();
326         if (vlanId.size() > 0) {
327             Iterator<Long> itr = vlanId.iterator();
328             // There are no loops here, just get the first element.
329             int id = itr.next().intValue();
330             ovsdbTerminationPointBuilder.setVlanTag(new VlanId(id));
331         }
332     }
333
334     @VisibleForTesting
335     void updateVlanTrunks(final Port port,
336             final OvsdbTerminationPointAugmentationBuilder ovsdbTerminationPointBuilder) {
337
338         Set<Long> portTrunks = port.getTrunksColumn().getData();
339         List<Trunks> modelTrunks = new ArrayList<>();
340         if (!portTrunks.isEmpty()) {
341             for (Long trunk: portTrunks) {
342                 if (trunk != null) {
343                     modelTrunks.add(new TrunksBuilder()
344                         .setTrunk(new VlanId(trunk.intValue())).build());
345                 }
346             }
347         }
348         ovsdbTerminationPointBuilder.setTrunks(modelTrunks);
349     }
350
351     @VisibleForTesting
352     void updateVlanMode(final Port port,
353             final OvsdbTerminationPointAugmentationBuilder ovsdbTerminationPointBuilder) {
354
355         Collection<String> vlanMode = port.getVlanModeColumn().getData();
356         if (!vlanMode.isEmpty()) {
357             Iterator<String> itr = vlanMode.iterator();
358             String vlanType = itr.next();
359             if (vlanType.equals(SouthboundConstants.VlanModes.ACCESS.getMode())) {
360                 ovsdbTerminationPointBuilder
361                     .setVlanMode(OvsdbPortInterfaceAttributes.VlanMode.Access);
362             } else if (vlanType.equals(SouthboundConstants.VlanModes.NATIVE_TAGGED.getMode())) {
363                 ovsdbTerminationPointBuilder
364                     .setVlanMode(OvsdbPortInterfaceAttributes.VlanMode.NativeTagged);
365             } else if (vlanType.equals(SouthboundConstants.VlanModes.NATIVE_UNTAGGED.getMode())) {
366                 ovsdbTerminationPointBuilder
367                     .setVlanMode(OvsdbPortInterfaceAttributes.VlanMode.NativeUntagged);
368             } else if (vlanType.equals(SouthboundConstants.VlanModes.TRUNK.getMode())) {
369                 ovsdbTerminationPointBuilder
370                     .setVlanMode(OvsdbPortInterfaceAttributes.VlanMode.Trunk);
371             } else {
372                 LOG.debug("Invalid vlan mode {}.", vlanType);
373             }
374         }
375     }
376
377     private void updateQos(final ReadWriteTransaction transaction, final Node node,
378                            InstanceIdentifier<TerminationPoint> tpPath, final Entry<UUID, Port> port,
379                            final OvsdbTerminationPointAugmentationBuilder ovsdbTerminationPointBuilder) {
380         if (port.getValue() == null) {
381             return;
382         }
383         Collection<UUID> qosUuidCol = port.getValue().getQosColumn().getData();
384         if (!qosUuidCol.isEmpty()) {
385             UUID qosUuid = qosUuidCol.iterator().next();
386
387             NodeId nodeId = node.getNodeId();
388             OvsdbNodeAugmentation ovsdbNode = node.augmentation(OvsdbNodeAugmentation.class);
389
390             // Delete an older QoS entry
391             if (portOldRows.containsKey(port.getKey()) && portOldRows.get(port.getKey()).getQosColumn() != null) {
392                 Collection<UUID> oldQos = portOldRows.get(port.getKey()).getQosColumn().getData();
393                 if (!oldQos.isEmpty()) {
394                     UUID oldQosUuid = oldQos.iterator().next();
395                     if (!oldQosUuid.equals(qosUuid)) {
396                         InstanceIdentifier<QosEntries> oldQosIid = getQosIid(nodeId, ovsdbNode, oldQosUuid);
397                         if (oldQosIid != null) {
398                             InstanceIdentifier<QosEntry> oldPortQosIid = tpPath
399                                 .augmentation(OvsdbTerminationPointAugmentation.class)
400                                 .child(QosEntry.class,
401                                       new QosEntryKey(Long.valueOf(SouthboundConstants.PORT_QOS_LIST_KEY)));
402                             transaction.delete(LogicalDatastoreType.OPERATIONAL, oldPortQosIid);
403                         }
404                     }
405                 }
406             }
407
408             InstanceIdentifier<QosEntries> qosIid = getQosIid(nodeId, ovsdbNode, qosUuid);
409             if (qosIid != null) {
410                 List<QosEntry> qosList = new ArrayList<>();
411                 OvsdbQosRef qosRef = new OvsdbQosRef(qosIid);
412                 qosList.add(new QosEntryBuilder()
413                     .withKey(new QosEntryKey(Long.valueOf(SouthboundConstants.PORT_QOS_LIST_KEY)))
414                     .setQosRef(qosRef).build());
415                 ovsdbTerminationPointBuilder.setQosEntry(qosList);
416             }
417         }
418     }
419
420     @SuppressWarnings("unchecked")
421     private InstanceIdentifier<QosEntries> getQosIid(NodeId nodeId, OvsdbNodeAugmentation ovsdbNode, UUID qosUuid) {
422         // Search for the QoS entry first in the operational datastore
423         for (QosEntries qosEntry : ovsdbNode.getQosEntries()) {
424             if (qosEntry.getQosUuid().equals(new Uuid(qosUuid.toString()))) {
425                 return SouthboundMapper.createInstanceIdentifier(nodeId)
426                         .augmentation(OvsdbNodeAugmentation.class)
427                         .child(QosEntries.class, new QosEntriesKey(qosEntry.getQosId()));
428             }
429         }
430
431         // Search for the QoS entry in the current OVS updates
432         for (Entry<UUID, Qos> qosUpdate : qosUpdatedRows.entrySet()) {
433             Qos qos = qosUpdate.getValue();
434             if (qos.getUuid().equals(qosUuid)) {
435                 if (qos.getExternalIdsColumn().getData().containsKey(SouthboundConstants.IID_EXTERNAL_ID_KEY)) {
436                     return (InstanceIdentifier<QosEntries>) instanceIdentifierCodec.bindingDeserializerOrNull(
437                             qos.getExternalIdsColumn().getData().get(SouthboundConstants.IID_EXTERNAL_ID_KEY));
438                 } else {
439                     return SouthboundMapper.createInstanceIdentifier(nodeId)
440                             .augmentation(OvsdbNodeAugmentation.class)
441                             .child(QosEntries.class, new QosEntriesKey(
442                                     new Uri(SouthboundConstants.QOS_URI_PREFIX + "://" + qosUuid.toString())));
443                 }
444             }
445         }
446         LOG.debug("QoS UUID {} assigned to port not found in operational node {} or QoS updates", qosUuid, ovsdbNode);
447         return SouthboundMapper.createInstanceIdentifier(nodeId)
448                 .augmentation(OvsdbNodeAugmentation.class)
449                 .child(QosEntries.class, new QosEntriesKey(
450                         new Uri(SouthboundConstants.QOS_URI_PREFIX + "://" + qosUuid.toString())));
451     }
452
453     private void updateIfIndex(final Interface interf,
454             final OvsdbTerminationPointAugmentationBuilder ovsdbTerminationPointBuilder) {
455         Set<Long> ifIndexSet = null;
456         try {
457             if (interf.getIfIndexColumn() != null) {
458                 ifIndexSet = interf.getIfIndexColumn().getData();
459             }
460             if (ifIndexSet != null && !ifIndexSet.isEmpty()) {
461                 for (Long ifIndex : ifIndexSet) {
462                     ovsdbTerminationPointBuilder.setIfindex(ifIndex);
463                 }
464             }
465         } catch (SchemaVersionMismatchException e) {
466             schemaMismatchLog("ifindex", "Interface", e);
467         }
468     }
469
470     private void updateMac(final Interface interf,
471                            final OvsdbTerminationPointAugmentationBuilder ovsdbTerminationPointBuilder) {
472         Set<String> macSet = null;
473         try {
474             if (interf.getMacColumn() != null) {
475                 macSet = interf.getMacColumn().getData();
476             }
477             if (macSet != null && !macSet.isEmpty()) {
478                 /*
479                  * It is a set due to way JSON decoder converts [] objects. OVS
480                  * only supports ONE mac, so we're fine.
481                  */
482                 for (String mac: macSet) {
483                     ovsdbTerminationPointBuilder.setMac(new MacAddress(mac));
484                 }
485             }
486         } catch (SchemaVersionMismatchException e) {
487             schemaMismatchLog("mac", "Interface", e);
488         }
489     }
490
491     private void updateMacInUse(final Interface interf,
492                                final OvsdbTerminationPointAugmentationBuilder ovsdbTerminationPointBuilder) {
493         Set<String> macInUseSet = null;
494         try {
495             if (interf.getMacInUseColumn() != null) {
496                 macInUseSet = interf.getMacInUseColumn().getData();
497             }
498             if (macInUseSet != null && !macInUseSet.isEmpty()) {
499                 /*
500                  * It is a set due to way JSON decoder converts [] objects. OVS
501                  * only supports ONE mac, so we're fine.
502                  */
503                 for (String macInUse: macInUseSet) {
504                     ovsdbTerminationPointBuilder.setMacInUse(new MacAddress(macInUse));
505                 }
506             }
507         } catch (SchemaVersionMismatchException e) {
508             schemaMismatchLog("mac_in_use", "Interface", e);
509         }
510     }
511
512     @VisibleForTesting
513     void updateOfPort(final Interface interf,
514             final OvsdbTerminationPointAugmentationBuilder ovsdbTerminationPointBuilder) {
515
516         Set<Long> ofPorts = interf.getOpenFlowPortColumn().getData();
517         if (ofPorts != null && !ofPorts.isEmpty()) {
518             Iterator<Long> ofPortsIter = ofPorts.iterator();
519             long ofPort = ofPortsIter.next();
520             if (ofPort >= 0) {
521                 ovsdbTerminationPointBuilder
522                     .setOfport(ofPort);
523             } else {
524                 LOG.debug("Received negative value for ofPort from ovsdb for {} {}",
525                         interf.getName(),ofPort);
526             }
527         }
528     }
529
530     @VisibleForTesting
531     void updateOfPortRequest(final Interface interf,
532             final OvsdbTerminationPointAugmentationBuilder ovsdbTerminationPointBuilder) {
533
534         Set<Long> ofPortRequests = null;
535         try {
536             ofPortRequests = interf.getOpenFlowPortRequestColumn().getData();
537         } catch (ColumnSchemaNotFoundException e) {
538             LOG.warn("Cannot find openflow column", e);
539         }
540         if (ofPortRequests != null && !ofPortRequests.isEmpty()) {
541             Iterator<Long> ofPortRequestsIter = ofPortRequests.iterator();
542             int ofPort = ofPortRequestsIter.next().intValue();
543             if (ofPort >= 0) {
544                 ovsdbTerminationPointBuilder
545                     .setOfportRequest(ofPort);
546             } else {
547                 LOG.debug("Received negative value for ofPort from ovsdb for {} {}",
548                         interf.getName(),ofPort);
549             }
550         }
551     }
552
553     @VisibleForTesting
554     void updateInterfaceExternalIds(final Interface interf,
555             final OvsdbTerminationPointAugmentationBuilder ovsdbTerminationPointBuilder) {
556
557         Map<String, String> interfaceExternalIds =
558                 interf.getExternalIdsColumn().getData();
559         if (interfaceExternalIds != null && !interfaceExternalIds.isEmpty()) {
560             List<InterfaceExternalIds> externalIdsList = new ArrayList<>();
561             for (Entry<String, String> entry : interfaceExternalIds.entrySet()) {
562                 String externalIdKey = entry.getKey();
563                 String externalIdValue = entry.getValue();
564                 if (externalIdKey != null && externalIdValue != null) {
565                     externalIdsList.add(new InterfaceExternalIdsBuilder()
566                             .setExternalIdKey(externalIdKey)
567                             .setExternalIdValue(externalIdValue).build());
568                 }
569             }
570             ovsdbTerminationPointBuilder.setInterfaceExternalIds(externalIdsList);
571         }
572     }
573
574     @VisibleForTesting
575     void updatePortExternalIds(final Port port,
576             final OvsdbTerminationPointAugmentationBuilder ovsdbTerminationPointBuilder) {
577
578         Map<String, String> portExternalIds = port.getExternalIdsColumn().getData();
579         if (portExternalIds != null && !portExternalIds.isEmpty()) {
580             List<PortExternalIds> externalIdsList = new ArrayList<>();
581             for (Entry<String, String> entry : portExternalIds.entrySet()) {
582                 String externalIdKey = entry.getKey();
583                 String externalIdValue = entry.getValue();
584                 if (externalIdKey != null && externalIdValue != null) {
585                     externalIdsList.add(new PortExternalIdsBuilder()
586                             .setExternalIdKey(externalIdKey)
587                             .setExternalIdValue(externalIdValue).build());
588                 }
589             }
590             ovsdbTerminationPointBuilder.setPortExternalIds(externalIdsList);
591         }
592     }
593
594     @VisibleForTesting
595     void updateOptions(final Interface interf,
596             final OvsdbTerminationPointAugmentationBuilder ovsdbTerminationPointBuilder) {
597
598         Map<String, String> optionsMap = interf.getOptionsColumn().getData();
599         if (optionsMap != null && !optionsMap.isEmpty()) {
600             List<Options> options = new ArrayList<>();
601             for (Entry<String, String> entry : optionsMap.entrySet()) {
602                 String optionsKeyString = entry.getKey();
603                 String optionsValueString = entry.getValue();
604                 if (optionsKeyString != null && optionsValueString != null) {
605                     OptionsKey optionsKey = new OptionsKey(optionsKeyString);
606                     options.add(new OptionsBuilder()
607                         .withKey(optionsKey)
608                         .setValue(optionsValueString).build());
609                 }
610             }
611             ovsdbTerminationPointBuilder.setOptions(options);
612         }
613     }
614
615     @VisibleForTesting
616     void updatePortOtherConfig(final Port port,
617             final OvsdbTerminationPointAugmentationBuilder ovsdbTerminationPointBuilder) {
618
619         Map<String, String> portOtherConfigMap = port.getOtherConfigColumn().getData();
620         if (portOtherConfigMap != null && !portOtherConfigMap.isEmpty()) {
621             List<PortOtherConfigs> portOtherConfigs = new ArrayList<>();
622             for (Entry<String, String> entry : portOtherConfigMap.entrySet()) {
623                 String portOtherConfigKeyString = entry.getKey();
624                 String portOtherConfigValueString = entry.getValue();
625                 if (portOtherConfigKeyString != null && portOtherConfigValueString != null) {
626                     portOtherConfigs.add(new PortOtherConfigsBuilder()
627                         .setOtherConfigKey(portOtherConfigKeyString)
628                         .setOtherConfigValue(portOtherConfigValueString).build());
629                 }
630             }
631             ovsdbTerminationPointBuilder.setPortOtherConfigs(portOtherConfigs);
632         }
633     }
634
635     private void updateInterfaceLldp(final Interface interf,
636             final OvsdbTerminationPointAugmentationBuilder ovsdbTerminationPointBuilder) {
637
638         try {
639             Map<String, String> interfaceLldpMap = interf.getLldpColumn().getData();
640             if (interfaceLldpMap != null && !interfaceLldpMap.isEmpty()) {
641                 List<InterfaceLldp> interfaceLldpList = new ArrayList<>();
642                 for (Entry<String, String> entry : interfaceLldpMap.entrySet()) {
643                     String interfaceLldpKeyString = entry.getKey();
644                     String interfaceLldpValueString = entry.getValue();
645                     if (interfaceLldpKeyString != null && interfaceLldpValueString != null) {
646                         interfaceLldpList.add(new InterfaceLldpBuilder()
647                                 .withKey(new InterfaceLldpKey(interfaceLldpKeyString))
648                                 .setLldpKey(interfaceLldpKeyString)
649                                 .setLldpValue(interfaceLldpValueString)
650                                 .build());
651                     }
652                 }
653                 ovsdbTerminationPointBuilder.setInterfaceLldp(interfaceLldpList);
654             }
655         } catch (SchemaVersionMismatchException e) {
656             schemaMismatchLog("lldp", "Interface", e);
657         }
658     }
659
660     @VisibleForTesting
661     void updateInterfaceOtherConfig(final Interface interf,
662             final OvsdbTerminationPointAugmentationBuilder ovsdbTerminationPointBuilder) {
663
664         Map<String, String> interfaceOtherConfigMap = interf.getOtherConfigColumn().getData();
665         if (interfaceOtherConfigMap != null && !interfaceOtherConfigMap.isEmpty()) {
666             List<InterfaceOtherConfigs> interfaceOtherConfigs = new ArrayList<>();
667             for (Entry<String, String> entry : interfaceOtherConfigMap.entrySet()) {
668                 String interfaceOtherConfigKeyString = entry.getKey();
669                 String interfaceOtherConfigValueString = entry.getValue();
670                 if (interfaceOtherConfigKeyString != null && interfaceOtherConfigValueString != null) {
671                     interfaceOtherConfigs.add(new InterfaceOtherConfigsBuilder()
672                         .setOtherConfigKey(interfaceOtherConfigKeyString)
673                         .setOtherConfigValue(interfaceOtherConfigValueString).build());
674                 }
675             }
676             ovsdbTerminationPointBuilder.setInterfaceOtherConfigs(interfaceOtherConfigs);
677         }
678     }
679
680     private void updateInterfaceBfdStatus(final Interface interf,
681             final OvsdbTerminationPointAugmentationBuilder ovsdbTerminationPointBuilder) {
682
683         try {
684             Map<String, String> interfaceBfdStatusMap = interf.getBfdStatusColumn().getData();
685             if (interfaceBfdStatusMap != null && !interfaceBfdStatusMap.isEmpty()) {
686                 List<InterfaceBfdStatus> interfaceBfdStatusList = new ArrayList<>();
687                 for (Entry<String, String> entry : interfaceBfdStatusMap.entrySet()) {
688                     String interfaceBfdStatusKeyString = entry.getKey();
689                     String interfaceBfdStatusValueString = entry.getValue();
690                     if (interfaceBfdStatusKeyString != null && interfaceBfdStatusValueString != null) {
691                         interfaceBfdStatusList.add(new InterfaceBfdStatusBuilder()
692                                 .withKey(new InterfaceBfdStatusKey(interfaceBfdStatusKeyString))
693                                 .setBfdStatusKey(interfaceBfdStatusKeyString)
694                                 .setBfdStatusValue(interfaceBfdStatusValueString)
695                                 .build());
696                     }
697                 }
698                 ovsdbTerminationPointBuilder.setInterfaceBfdStatus(interfaceBfdStatusList);
699             }
700         } catch (SchemaVersionMismatchException e) {
701             schemaMismatchLog("bfd", "Interface", e);
702         }
703     }
704
705     private void updateInterfaceBfd(final Interface interf,
706             final OvsdbTerminationPointAugmentationBuilder ovsdbTerminationPointBuilder) {
707
708         try {
709             Map<String, String> interfaceBfdMap = interf.getBfdColumn().getData();
710             if (interfaceBfdMap != null && !interfaceBfdMap.isEmpty()) {
711                 List<InterfaceBfd> interfaceBfdList = new ArrayList<>();
712                 for (Entry<String, String> entry : interfaceBfdMap.entrySet()) {
713                     String interfaceBfdKeyString = entry.getKey();
714                     String interfaceBfdValueString = entry.getValue();
715                     if (interfaceBfdKeyString != null && interfaceBfdValueString != null) {
716                         interfaceBfdList.add(new InterfaceBfdBuilder()
717                                 .withKey(new InterfaceBfdKey(interfaceBfdKeyString))
718                                 .setBfdKey(interfaceBfdKeyString)
719                                 .setBfdValue(interfaceBfdValueString)
720                                 .build());
721                     }
722                 }
723                 ovsdbTerminationPointBuilder.setInterfaceBfd(interfaceBfdList);
724             }
725         } catch (SchemaVersionMismatchException e) {
726             schemaMismatchLog("bfd", "Interface", e);
727
728         }
729     }
730
731     private void updateInterfacePolicing(final Interface interf,
732             final OvsdbTerminationPointAugmentationBuilder ovsdbTerminationPointBuilder) {
733
734         Long ingressPolicingRate = null;
735         if (interf.getIngressPolicingRateColumn() != null) {
736             ingressPolicingRate = interf.getIngressPolicingRateColumn().getData();
737         }
738         if (ingressPolicingRate != null) {
739             if (ingressPolicingRate >= 0) {
740                 ovsdbTerminationPointBuilder
741                     .setIngressPolicingRate(ingressPolicingRate);
742             } else {
743                 LOG.debug("Received negative value for ingressPolicingRate from ovsdb for {} {}",
744                         interf.getName(),ingressPolicingRate);
745             }
746         }
747
748         Long ingressPolicingBurst = null;
749         if (interf.getIngressPolicingBurstColumn() != null) {
750             ingressPolicingBurst = interf.getIngressPolicingBurstColumn().getData();
751         }
752         if (ingressPolicingBurst != null) {
753             if (ingressPolicingBurst >= 0) {
754                 ovsdbTerminationPointBuilder
755                     .setIngressPolicingBurst(ingressPolicingBurst);
756             } else {
757                 LOG.debug("Received negative value for ingressPolicingBurst from ovsdb for {} {}",
758                         interf.getName(),ingressPolicingBurst);
759             }
760         }
761     }
762
763     private boolean portQosCleared(Entry<UUID, Port> portUpdate) {
764         if (portUpdate.getValue().getQosColumn() == null) {
765             return false;
766         }
767         Collection<UUID> newQos = portUpdate.getValue().getQosColumn().getData();
768         if (portOldRows.get(portUpdate.getKey()).getQosColumn() == null) {
769             return false;
770         }
771         Collection<UUID> oldQos = portOldRows.get(portUpdate.getKey()).getQosColumn().getData();
772
773         if (newQos.isEmpty() && !oldQos.isEmpty()) {
774             return true;
775         } else {
776             return false;
777         }
778     }
779
780     @SuppressWarnings("unchecked")
781     @VisibleForTesting
782     InstanceIdentifier<TerminationPoint> getInstanceIdentifier(InstanceIdentifier<Node> bridgeIid,Port port) {
783         if (port.getExternalIdsColumn() != null
784                 && port.getExternalIdsColumn().getData() != null
785                 && port.getExternalIdsColumn().getData().containsKey(SouthboundConstants.IID_EXTERNAL_ID_KEY)) {
786             String iidString = port.getExternalIdsColumn().getData().get(SouthboundConstants.IID_EXTERNAL_ID_KEY);
787             return (InstanceIdentifier<TerminationPoint>) instanceIdentifierCodec.bindingDeserializerOrNull(iidString);
788         } else {
789             return bridgeIid.child(TerminationPoint.class, new TerminationPointKey(new TpId(port.getName())));
790         }
791     }
792 }