2 * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved.
\r
4 * This program and the accompanying materials are made available under the
\r
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
\r
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
\r
9 package org.opendaylight.groupbasedpolicy.neutron.vpp.mapper.processors;
\r
11 import org.opendaylight.controller.md.sal.binding.api.BindingTransactionChain;
\r
12 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
\r
13 import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
\r
14 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
\r
15 import org.opendaylight.controller.md.sal.common.api.data.AsyncTransaction;
\r
16 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
\r
17 import org.opendaylight.controller.md.sal.common.api.data.TransactionChain;
\r
18 import org.opendaylight.controller.md.sal.common.api.data.TransactionChainListener;
\r
19 import org.opendaylight.groupbasedpolicy.neutron.vpp.mapper.SocketInfo;
\r
20 import org.opendaylight.groupbasedpolicy.util.DataStoreHelper;
\r
21 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.PhysAddress;
\r
22 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
\r
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.UniqueId;
\r
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.gbp.mapper.rev150513.Mappings;
\r
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.gbp.mapper.rev150513.mappings.GbpByNeutronMappings;
\r
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.gbp.mapper.rev150513.mappings.gbp.by.neutron.mappings.BaseEndpointsByPorts;
\r
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.gbp.mapper.rev150513.mappings.gbp.by.neutron.mappings.base.endpoints.by.ports.BaseEndpointByPort;
\r
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.gbp.mapper.rev150513.mappings.gbp.by.neutron.mappings.base.endpoints.by.ports.BaseEndpointByPortKey;
\r
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.Config;
\r
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.config.VppEndpoint;
\r
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.config.VppEndpointBuilder;
\r
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.config.VppEndpointKey;
\r
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.config.vpp.endpoint._interface.type.choice.TapCase;
\r
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.config.vpp.endpoint._interface.type.choice.TapCaseBuilder;
\r
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.config.vpp.endpoint._interface.type.choice.VhostUserCaseBuilder;
\r
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.binding.rev150712.PortBindingExtension;
\r
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.Ports;
\r
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.Port;
\r
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.PortKey;
\r
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron;
\r
41 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
\r
42 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
\r
43 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId;
\r
44 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
\r
45 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
\r
46 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
\r
47 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeKey;
\r
48 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
\r
49 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder;
\r
50 import org.slf4j.Logger;
\r
51 import org.slf4j.LoggerFactory;
\r
53 import com.google.common.annotations.VisibleForTesting;
\r
54 import com.google.common.base.Optional;
\r
56 public class PortHandler implements TransactionChainListener {
\r
58 private static final Logger LOG = LoggerFactory.getLogger(MappingProvider.class);
\r
60 private static final String COMPUTE_OWNER = "compute";
\r
61 private static final String DHCP_OWNER = "dhcp";
\r
62 private static final String[] SUPPORTED_DEVICE_OWNERS = {COMPUTE_OWNER, DHCP_OWNER};
\r
63 private static final String VHOST_USER = "vhostuser";
\r
64 private static final String NETCONF_TOPOLOGY_ID = "topology-netconf";
\r
65 private static final String VPP_INTERFACE_NAME_PREFIX = "neutron_port_";
\r
66 private static final String TAP_PORT_NAME_PREFIX = "tap";
\r
68 private BindingTransactionChain transactionChain;
\r
69 PortAware portByBaseEpListener;
\r
70 DataBroker dataBroker;
\r
71 SocketInfo socketInfo;
\r
73 PortHandler(DataBroker dataBroker, SocketInfo socketInfo) {
\r
74 this.dataBroker = dataBroker;
\r
75 this.socketInfo = socketInfo;
\r
76 transactionChain = this.dataBroker.createTransactionChain(this);
\r
79 void processCreated(Port port) {
\r
80 ReadOnlyTransaction rTx = transactionChain.newReadOnlyTransaction();
\r
81 Optional<BaseEndpointByPort> optBaseEpByPort = DataStoreHelper.readFromDs(LogicalDatastoreType.OPERATIONAL,
\r
82 createBaseEpByPortIid(port.getUuid()), rTx);
\r
84 if (!optBaseEpByPort.isPresent()) {
\r
87 processCreatedData(port, optBaseEpByPort.get());
\r
90 void processCreated(BaseEndpointByPort bebp) {
\r
91 ReadOnlyTransaction rTx = transactionChain.newReadOnlyTransaction();
\r
92 Optional<Port> optPort = DataStoreHelper.readFromDs(LogicalDatastoreType.CONFIGURATION,
\r
93 createPortIid(bebp.getPortId()), rTx);
\r
95 if (!optPort.isPresent()) {
\r
98 processCreatedData(optPort.get(), bebp);
\r
102 void processCreatedData(Port port, BaseEndpointByPort bebp) {
\r
103 if (isValidVhostUser(port)) {
\r
104 VppEndpoint vppEp = buildVppEndpoint(port, bebp);
\r
105 writeVppEndpoint(createVppEndpointIid(vppEp.getKey()), vppEp);
\r
106 LOG.debug("Created vpp-endpoint {}", vppEp);
\r
110 private boolean isValidVhostUser(Port port) {
\r
111 PortBindingExtension portBindingExt = port.getAugmentation(PortBindingExtension.class);
\r
112 if (portBindingExt != null) {
\r
113 String vifType = portBindingExt.getVifType();
\r
114 String deviceOwner = port.getDeviceOwner();
\r
115 if (vifType != null && deviceOwner != null) {
\r
116 if (vifType.contains(VHOST_USER)) {
\r
117 for (String supportedDeviceOwner : SUPPORTED_DEVICE_OWNERS) {
\r
118 if (deviceOwner.contains(supportedDeviceOwner)) {
\r
128 void processUpdated(Port original, Port delta) {
\r
129 if (isValidVhostUser(original)) {
\r
130 ReadOnlyTransaction rTx = transactionChain.newReadOnlyTransaction();
\r
131 Optional<BaseEndpointByPort> optBebp = DataStoreHelper.readFromDs(LogicalDatastoreType.OPERATIONAL,
\r
132 createBaseEpByPortIid(original.getUuid()), rTx);
\r
134 if (!optBebp.isPresent()) {
\r
137 processDeleted(optBebp.get());
\r
139 processCreated(delta);
\r
142 void processDeleted(BaseEndpointByPort bebp) {
\r
143 VppEndpointKey vppEpKey = new VppEndpointKey(bebp.getAddress(), bebp.getAddressType(), bebp.getContextId(),
\r
144 bebp.getContextType());
\r
145 InstanceIdentifier<VppEndpoint> vppEpIid = createVppEndpointIid(vppEpKey);
\r
146 ReadOnlyTransaction rTx = transactionChain.newReadOnlyTransaction();
\r
147 Optional<VppEndpoint> readVppEp = DataStoreHelper.readFromDs(LogicalDatastoreType.CONFIGURATION, vppEpIid, rTx);
\r
149 if (readVppEp.isPresent()) {
\r
150 writeVppEndpoint(vppEpIid, null);
\r
151 LOG.debug("Deleted vpp-endpoint {}", vppEpKey);
\r
155 private synchronized void writeVppEndpoint(InstanceIdentifier<VppEndpoint> vppEpIid, VppEndpoint vppEp) {
\r
156 WriteTransaction wTx = transactionChain.newWriteOnlyTransaction();
\r
157 if (vppEp != null) {
\r
158 wTx.put(LogicalDatastoreType.CONFIGURATION, vppEpIid, vppEp, true);
\r
160 wTx.delete(LogicalDatastoreType.CONFIGURATION, vppEpIid);
\r
166 VppEndpoint buildVppEndpoint(Port port, BaseEndpointByPort bebp) {
\r
167 PortBindingExtension portBinding = port.getAugmentation(PortBindingExtension.class);
\r
168 VppEndpointBuilder vppEpBuilder = new VppEndpointBuilder().setDescription("neutron port")
\r
169 .setContextId(bebp.getContextId())
\r
170 .setContextType(bebp.getContextType())
\r
171 .setAddress(bebp.getAddress())
\r
172 .setAddressType(bebp.getAddressType())
\r
173 .setVppInterfaceName(VPP_INTERFACE_NAME_PREFIX + bebp.getPortId().getValue())
\r
174 .setVppNodePath(createNodeIid(new NodeId(portBinding.getHostId())));
\r
175 if (port.getDeviceOwner().contains(COMPUTE_OWNER)) {
\r
176 String socket = socketInfo.getSocketPath() + socketInfo.getSocketPrefix() + bebp.getPortId().getValue();
\r
177 vppEpBuilder.setInterfaceTypeChoice(new VhostUserCaseBuilder().setSocket(socket).build());
\r
178 } else if (port.getDeviceOwner().contains(DHCP_OWNER) && port.getMacAddress() != null) {
\r
179 TapCase tapCase = new TapCaseBuilder().setPhysicalAddress(new PhysAddress(port.getMacAddress().getValue()))
\r
180 .setName(createPortName(port.getUuid()))
\r
182 vppEpBuilder.setInterfaceTypeChoice(tapCase);
\r
184 return vppEpBuilder.build();
\r
187 private String createPortName(Uuid portUuid) {
\r
188 String tapPortName;
\r
189 String uuid = portUuid.getValue();
\r
190 if (uuid != null && uuid.length() >= 12) {
\r
191 tapPortName = TAP_PORT_NAME_PREFIX + uuid.substring(0, 11);
\r
193 tapPortName = TAP_PORT_NAME_PREFIX + uuid;
\r
195 return tapPortName;
\r
198 private InstanceIdentifier<Node> createNodeIid(NodeId nodeId) {
\r
199 return InstanceIdentifier.builder(NetworkTopology.class)
\r
200 .child(Topology.class, new TopologyKey(new TopologyId(NETCONF_TOPOLOGY_ID)))
\r
201 .child(Node.class, new NodeKey(nodeId))
\r
205 private InstanceIdentifier<VppEndpoint> createVppEndpointIid(VppEndpointKey vppEpKey) {
\r
206 return InstanceIdentifier.builder(Config.class).child(VppEndpoint.class, vppEpKey).build();
\r
209 private InstanceIdentifier<BaseEndpointByPort> createBaseEpByPortIid(Uuid uuid) {
\r
210 return createBaseEpByPortIid(new UniqueId(uuid.getValue()));
\r
213 private InstanceIdentifier<BaseEndpointByPort> createBaseEpByPortIid(UniqueId uuid) {
\r
214 return InstanceIdentifier.builder(Mappings.class)
\r
215 .child(GbpByNeutronMappings.class)
\r
216 .child(BaseEndpointsByPorts.class)
\r
217 .child(BaseEndpointByPort.class, new BaseEndpointByPortKey(uuid))
\r
221 InstanceIdentifier<Port> createWildcartedPortIid() {
\r
222 return portsIid().child(Port.class).build();
\r
225 private InstanceIdentifier<Port> createPortIid(UniqueId uuid) {
\r
226 return portsIid().child(Port.class, new PortKey(new Uuid(uuid.getValue()))).build();
\r
229 private InstanceIdentifierBuilder<Ports> portsIid() {
\r
230 return InstanceIdentifier.builder(Neutron.class).child(Ports.class);
\r
234 public void onTransactionChainFailed(TransactionChain<?, ?> chain, AsyncTransaction<?, ?> transaction,
\r
236 LOG.error("Transaction chain failed. {} \nTransaction which caused the chain to fail {}", cause.getMessage(),
\r
237 transaction, cause);
\r
238 transactionChain.close();
\r
239 transactionChain = dataBroker.createTransactionChain(this);
\r
243 public void onTransactionChainSuccessful(TransactionChain<?, ?> chain) {
\r
244 LOG.trace("Transaction chain was successfull. {}", chain);
\r