78c8b7cf808641250fd5b6aff26872d6f616a22d
[groupbasedpolicy.git] / renderers / vpp / src / main / java / org / opendaylight / groupbasedpolicy / renderer / vpp / dhcp / DhcpRelayHandler.java
1 /*
2  * Copyright (c) 2017 Cisco Systems. 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.groupbasedpolicy.renderer.vpp.dhcp;
10
11 import com.google.common.base.Optional;
12 import com.google.common.collect.SetMultimap;
13 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
14 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
15 import org.opendaylight.groupbasedpolicy.renderer.vpp.commands.DhcpRelayCommand;
16 import org.opendaylight.groupbasedpolicy.renderer.vpp.util.GbpNetconfTransaction;
17 import org.opendaylight.groupbasedpolicy.renderer.vpp.util.General;
18 import org.opendaylight.groupbasedpolicy.renderer.vpp.util.MountedDataBrokerProvider;
19 import org.opendaylight.groupbasedpolicy.renderer.vpp.util.VppIidFactory;
20 import org.opendaylight.groupbasedpolicy.util.DataStoreHelper;
21 import org.opendaylight.groupbasedpolicy.util.NetUtils;
22 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.NetworkDomainId;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev170511.has.subnet.Subnet;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.Config;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425._interface.attributes._interface.type.choice.TapCase;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.config.VppEndpoint;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.dhcp.rev170315.Ipv4;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.dhcp.rev170315.relay.attributes.ServerBuilder;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.dhcp.rev170315.relay.attributes.ServerKey;
31 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
32 import org.slf4j.Logger;
33 import org.slf4j.LoggerFactory;
34
35 import java.util.Collections;
36 import java.util.Set;
37 import java.util.stream.Stream;
38
39 import static org.opendaylight.groupbasedpolicy.renderer.vpp.util.VppIidFactory.getVppRendererConfig;
40
41 public class DhcpRelayHandler {
42
43     private static final Logger LOG = LoggerFactory.getLogger(DhcpRelayHandler.class);
44     private final MountedDataBrokerProvider mountDataProvider;
45     private final DataBroker dataBroker;
46
47     public DhcpRelayHandler(DataBroker dataBroker, MountedDataBrokerProvider mountDataProvider) {
48         this.mountDataProvider = mountDataProvider;
49         this.dataBroker = dataBroker;
50     }
51
52     public void createIpv4DhcpRelay(long vni_vrfid, Subnet subnet, SetMultimap<String, NodeId> vppNodesByL2Fd) {
53         if (subnet.getDefaultSubnetGatewayIp() == null) {
54             LOG.trace("Subnet GW IP is null, skipping processing DhcpRelay for vrfid: {}, subnet: {}, VPP nodes: {}",
55                 vni_vrfid, subnet, vppNodesByL2Fd);
56             return;
57         }
58
59         for (String bd : vppNodesByL2Fd.keySet()) {
60             Set<NodeId> vppNodes = vppNodesByL2Fd.get(bd);
61             for (NodeId vppNode : vppNodes) {
62                 IpAddress ipAddress = resolveDhcpIpAddress(vppNode, subnet);
63                 if (ipAddress != null) {
64                     DhcpRelayCommand dhcpRelayCommand =
65                         getDhcpRelayBuilder(vni_vrfid, subnet, ipAddress, General.Operations.PUT).build();
66
67                     if (!submitDhcpRelay(dhcpRelayCommand, vppNode)) {
68                         LOG.warn("DHCP Relay was not configured: {}", dhcpRelayCommand);
69                     }
70                 } else {
71                     LOG.warn("DHCP server IP address was not found for node: {}. Skipping processing", vppNode);
72                 }
73             }
74
75         }
76     }
77
78     private DhcpRelayCommand.DhcpRelayBuilder getDhcpRelayBuilder(long vni_vrfid, Subnet subnet, IpAddress ipAddress,
79         General.Operations operations) {
80         return DhcpRelayCommand.builder()
81             .setRxVrfId(vni_vrfid)
82             .setOperation(operations)
83             .setAddressType(Ipv4.class)
84             .setGatewayIpAddress(subnet.getDefaultSubnetGatewayIp())
85             .setServerIpAddresses(Collections.singletonList(
86                 new ServerBuilder()
87                     .setAddress(ipAddress)
88                     .setVrfId(vni_vrfid)
89                     .setKey(new ServerKey(ipAddress, vni_vrfid))
90                     .build()));
91     }
92
93     private IpAddress resolveDhcpIpAddress(NodeId vppNode, Subnet subnet) {
94         Optional<Config> vppEndpointOptional =
95             DataStoreHelper.readFromDs(LogicalDatastoreType.CONFIGURATION, getVppRendererConfig(),
96                 dataBroker.newReadOnlyTransaction());
97
98         if (vppEndpointOptional.isPresent() && !vppEndpointOptional.get().getVppEndpoint().isEmpty()) {
99             Stream<VppEndpoint> vppEndpointStream = vppEndpointOptional.get().getVppEndpoint().stream()
100                 .filter(vppEndpoint -> vppEndpoint.getInterfaceTypeChoice() instanceof TapCase)
101                 .filter(vppEndpoint -> vppEndpoint.getVppNodeId().equals(vppNode))
102                 .filter(vppEndpoint -> ((TapCase) vppEndpoint.getInterfaceTypeChoice()).getDhcpServerAddress() != null)
103                 .filter(vppEndpoint -> NetUtils.isInRange(subnet.getIpPrefix(), ((TapCase) vppEndpoint
104                     .getInterfaceTypeChoice()).getDhcpServerAddress().getIpv4Address().getValue()));
105             java.util.Optional<VppEndpoint> vppEpOptional = vppEndpointStream.findFirst();
106             if (vppEpOptional.isPresent()) {
107                 IpAddress dhcpServerAddress =
108                     ((TapCase) vppEpOptional.get().getInterfaceTypeChoice()).getDhcpServerAddress();
109                 LOG.trace("Found Dhcp server: {} on VPP node: {}", dhcpServerAddress, vppNode);
110                 return dhcpServerAddress;
111             } else {
112                 LOG.trace("Dhcp server ip not found in subnet: {}, for node: {},in VPP endpoints: {}",
113                     subnet, vppNode, vppEndpointOptional.get().getVppEndpoint());
114             }
115         }
116         return null;
117     }
118
119     public void deleteIpv4DhcpRelay(long vni_vrfid, Subnet subnet, SetMultimap<String, NodeId> vppNodesByL2Fd) {
120         if (subnet.getDefaultSubnetGatewayIp() == null) {
121             LOG.trace("Subnet GW IP is null, skipping processing DhcpRelay for vrfid: {}, subnet: {}, VPP nodes: {}",
122                 vni_vrfid, subnet, vppNodesByL2Fd);
123             return;
124         }
125
126         for (String bd : vppNodesByL2Fd.keySet()) {
127             Set<NodeId> vppNodes = vppNodesByL2Fd.get(bd);
128             for (NodeId vppNode : vppNodes) {
129                 IpAddress ipAddress = resolveDhcpIpAddress(vppNode, subnet);
130                 if (ipAddress != null) {
131                     DhcpRelayCommand dhcpRelayCommand =
132                         getDhcpRelayBuilder(vni_vrfid, subnet, ipAddress, General.Operations.DELETE).build();
133
134                     if (!submitDhcpRelay(dhcpRelayCommand, vppNode)) {
135                         LOG.warn("DHCP Relay was not deleted: {}", dhcpRelayCommand);
136                     }
137                 } else {
138                     LOG.trace("DHCP server IP address was not found for node: {}. Skipping processing.", vppNode);
139                 }
140
141             }
142
143         }
144     }
145
146     private boolean submitDhcpRelay(DhcpRelayCommand dhcpRelayCommand, NodeId nodeIid) {
147         LOG.trace("Submitting DhcpRelay command: {}, nodeId: {}", dhcpRelayCommand, nodeIid);
148
149         Optional<DataBroker> mountPointDataBroker =
150             mountDataProvider.getDataBrokerForMountPoint(VppIidFactory.getNetconfNodeIid(nodeIid));
151         if (!mountPointDataBroker.isPresent()) {
152             throw new IllegalStateException("Cannot find data broker for mount point " + nodeIid);
153         }
154         if (dhcpRelayCommand.getOperation() == General.Operations.PUT) {
155             return GbpNetconfTransaction.netconfSyncedWrite(mountPointDataBroker.get(), dhcpRelayCommand,
156                 GbpNetconfTransaction.RETRY_COUNT);
157         } else if (dhcpRelayCommand.getOperation() == General.Operations.DELETE) {
158             return GbpNetconfTransaction.netconfSyncedDelete(mountPointDataBroker.get(), dhcpRelayCommand,
159                 GbpNetconfTransaction.RETRY_COUNT);
160         }
161         return false;
162     }
163 }