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