2 * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved.
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
9 package org.opendaylight.groupbasedpolicy.ip.sgt.distribution.service.impl;
11 import com.google.common.base.Preconditions;
12 import com.google.common.collect.ArrayListMultimap;
13 import com.google.common.collect.Multimap;
14 import com.google.common.util.concurrent.FutureCallback;
15 import com.google.common.util.concurrent.Futures;
16 import com.google.common.util.concurrent.ListenableFuture;
17 import com.google.common.util.concurrent.SettableFuture;
18 import java.util.HashMap;
20 import java.util.Map.Entry;
21 import java.util.concurrent.Future;
22 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
23 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
24 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
25 import org.opendaylight.sxp.util.time.TimeConv;
26 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
27 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpPrefix;
28 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.DateAndTime;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.ip.sgt.distribution.rev160715.IpSgtDistributionService;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.ip.sgt.distribution.rev160715.RemoveIpSgtBindingFromPeerInput;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.ip.sgt.distribution.rev160715.SendIpSgtBindingToPeerInput;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.ip.sgt.distribution.rev160715.rpc.fields.Binding;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.ip.sgt.distribution.rev160715.rpc.fields.binding.PeerNode;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.controller.rev141002.AddNodeInput;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.controller.rev141002.AddNodeInputBuilder;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.controller.rev141002.AddNodeOutput;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.controller.rev141002.SxpControllerService;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.database.rev160308.Sgt;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.database.rev160308.master.database.fields.MasterDatabaseBinding;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.database.rev160308.master.database.fields.MasterDatabaseBindingBuilder;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.database.rev160308.master.database.fields.MasterDatabaseBindingKey;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.database.rev160308.peer.sequence.fields.PeerSequenceBuilder;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.node.rev160308.SxpNodeIdentity;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.node.rev160308.network.topology.topology.node.SxpDomains;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.node.rev160308.network.topology.topology.node.sxp.domains.SxpDomain;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.node.rev160308.network.topology.topology.node.sxp.domains.SxpDomainKey;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.node.rev160308.sxp.databases.fields.MasterDatabase;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.protocol.rev141002.NodeId;
49 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
50 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId;
51 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
52 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
53 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
54 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeKey;
55 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
56 import org.opendaylight.yangtools.yang.common.RpcResult;
57 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
58 import org.slf4j.Logger;
59 import org.slf4j.LoggerFactory;
61 public class IpSgtDistributionServiceImpl implements AutoCloseable, IpSgtDistributionService {
63 private static final Logger LOG = LoggerFactory.getLogger(IpSgtDistributionServiceImpl.class);
64 public static final String SXP_NODE_DESCRIPTION = "ODL-GBP SXP node";
65 public static final String SXP_TOPOLOGY_ID = "sxp";
66 private final String SXP_NODE_ID;
67 private DataBroker dataBroker;
68 private IpAddress sourceIp;
69 private SxpCapableNodeListener nodeCollector;
71 public IpSgtDistributionServiceImpl(DataBroker dataBroker, SxpControllerService sxpService, IpAddress sourceIp) {
72 this.dataBroker = Preconditions.checkNotNull(dataBroker);
73 this.sourceIp = Preconditions.checkNotNull(sourceIp);
74 Preconditions.checkNotNull(sxpService);
76 if (sourceIp.getIpv4Address() != null) {
77 SXP_NODE_ID = sourceIp.getIpv4Address().getValue();
79 SXP_NODE_ID = sourceIp.getIpv6Address().getValue();
81 createSxpNode(sxpService);
82 nodeCollector = new SxpCapableNodeListener(dataBroker, SXP_NODE_ID);
86 private void createSxpNode(SxpControllerService sxpService) {
87 AddNodeInput addNodeInput = new AddNodeInputBuilder().setNodeId(new NodeId(SXP_NODE_ID))
88 .setSourceIp(sourceIp)
89 .setDescription(SXP_NODE_DESCRIPTION)
91 Future<RpcResult<AddNodeOutput>> addNodeResult = sxpService.addNode(addNodeInput);
93 if (! addNodeResult.get().getResult().isResult()) {
94 LOG.error("RPC add-node wasn't successfull");
96 } catch (Exception e) {
97 LOG.error("RPC add-node wasn't successfull");
102 public Future<RpcResult<Void>> sendIpSgtBindingToPeer(SendIpSgtBindingToPeerInput input) {
103 Map<String, Multimap<Sgt, IpPrefix>> bindingsMap = new HashMap<>();
104 boolean success = true;
105 for (Binding binding : input.getBinding()) {
106 success = transformChanges(binding, bindingsMap);
112 return Futures.immediateCheckedFuture(RpcResultBuilder.<Void>failed().build());
114 WriteTransaction wtx = dataBroker.newWriteOnlyTransaction();
115 bindingsMap.entrySet().forEach(bindingEntries -> {
116 String domainId = bindingEntries.getKey();
117 bindingEntries.getValue().entries().forEach(binding -> writeBinding(binding, domainId, wtx));
119 ListenableFuture<Void> submit = wtx.submit();
120 SettableFuture<RpcResult<Void>> future = SettableFuture.create();
121 Futures.addCallback(submit, new FutureCallback<Void>() {
124 public void onSuccess(Void result) {
125 future.set(RpcResultBuilder.<Void>success().build());
129 public void onFailure(Throwable t) {
130 future.set(RpcResultBuilder.<Void>failed().build());
138 private boolean transformChanges(Binding binding, Map<String, Multimap<Sgt, IpPrefix>> bindingsMap) {
139 Sgt sgt = binding.getSgt();
140 IpPrefix addr = binding.getIpPrefix();
141 for (PeerNode peer : binding.getPeerNode()) {
142 String domainId = nodeCollector.getDomainIdForPeer((InstanceIdentifier<Node>) peer.getNodeIid());
143 if (domainId == null) {
144 LOG.debug("Node {} is not SXP capable", peer.getNodeIid());
147 Multimap<Sgt, IpPrefix> domainBindingMap = bindingsMap.get(domainId);
148 if (domainBindingMap == null) {
149 domainBindingMap = ArrayListMultimap.create();
150 bindingsMap.put(domainId, domainBindingMap);
152 domainBindingMap.get(sgt).add(addr);
157 private void writeBinding(Entry<Sgt, IpPrefix> binding, String domainId, WriteTransaction wtx) {
158 IpPrefix addr = binding.getValue();
159 InstanceIdentifier<MasterDatabaseBinding> iid = bindingIid(domainId, addr);
160 MasterDatabaseBinding newBinding = createBinding(binding);
161 wtx.put(LogicalDatastoreType.CONFIGURATION, iid, newBinding);
164 private InstanceIdentifier<MasterDatabaseBinding> bindingIid(String domainId, IpPrefix prefix) {
165 return InstanceIdentifier.builder(NetworkTopology.class)
166 .child(Topology.class, new TopologyKey(new TopologyId(SXP_TOPOLOGY_ID)))
169 new org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId(
171 .augmentation(SxpNodeIdentity.class)
172 .child(SxpDomains.class)
173 .child(SxpDomain.class, new SxpDomainKey(domainId))
174 .child(MasterDatabase.class)
175 .child(MasterDatabaseBinding.class, new MasterDatabaseBindingKey(prefix))
179 private MasterDatabaseBinding createBinding(Entry<Sgt, IpPrefix> binding) {
180 final DateAndTime nowDateTime = TimeConv.toDt(System.currentTimeMillis());
181 return new MasterDatabaseBindingBuilder()
182 .setIpPrefix(binding.getValue())
183 .setSecurityGroupTag(binding.getKey())
184 .setPeerSequence(new PeerSequenceBuilder().build())
185 .setTimestamp(nowDateTime)
190 public Future<RpcResult<Void>> removeIpSgtBindingFromPeer(RemoveIpSgtBindingFromPeerInput input) {
191 Map<String, Multimap<Sgt, IpPrefix>> bindingsMap = new HashMap<>();
192 boolean success = true;
193 for (Binding binding : input.getBinding()) {
194 success = transformChanges(binding, bindingsMap);
200 return Futures.immediateCheckedFuture(RpcResultBuilder.<Void>failed().build());
202 WriteTransaction wtx = dataBroker.newWriteOnlyTransaction();
203 bindingsMap.entrySet().forEach(bindingEntries -> {
204 String domainId = bindingEntries.getKey();
205 bindingEntries.getValue().entries().forEach(binding -> removeBinding(binding, domainId, wtx));
207 ListenableFuture<Void> submit = wtx.submit();
208 SettableFuture<RpcResult<Void>> future = SettableFuture.create();
209 Futures.addCallback(submit, new FutureCallback<Void>() {
212 public void onSuccess(Void result) {
213 future.set(RpcResultBuilder.<Void>success().build());
217 public void onFailure(Throwable t) {
218 future.set(RpcResultBuilder.<Void>failed().build());
226 private void removeBinding(Entry<Sgt, IpPrefix> binding, String domainId, WriteTransaction wtx) {
227 IpPrefix addr = binding.getValue();
228 InstanceIdentifier<MasterDatabaseBinding> iid = bindingIid(domainId, addr);
229 wtx.delete(LogicalDatastoreType.CONFIGURATION, iid);
233 public void close() throws Exception {
234 nodeCollector.close();