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