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.renderer.vpp.policy.acl;
11 import java.net.UnknownHostException;
12 import java.util.ArrayList;
13 import java.util.List;
14 import java.util.stream.Collectors;
16 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.PortNumber;
17 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.packet.fields.rev160708.acl.transport.header.fields.DestinationPortRangeBuilder;
18 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.packet.fields.rev160708.acl.transport.header.fields.SourcePortRangeBuilder;
19 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoints.containment.endpoints.ContainmentEndpoint;
20 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev170511.IpPrefixType;
21 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev170511.L2BridgeDomain;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev170511.L3Context;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev170511.MacAddressType;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.endpoints.AddressEndpointWithLocation;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.acl.rev170615.access.lists.acl.access.list.entries.ace.matches.ace.type.vpp.ace.vpp.ace.nodes.ace.ip.version.AceIpv4;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.acl.rev170615.access.lists.acl.access.list.entries.ace.matches.ace.type.vpp.ace.vpp.ace.nodes.ace.ip.version.AceIpv6;
27 import org.slf4j.Logger;
28 import org.slf4j.LoggerFactory;
30 import com.google.common.base.Predicate;
31 import com.google.common.collect.ImmutableMap;
34 abstract class AddressMapper {
36 private static final Logger LOG = LoggerFactory.getLogger(AddressMapper.class);
38 private AccessListUtil.ACE_DIRECTION direction;
40 private static final PortNumber DHCP_67 = new PortNumber(67);
41 private static final PortNumber DHCP_68 = new PortNumber(68);
42 private static final PortNumber DHCPV6_547 = new PortNumber(547);
43 private static final PortNumber DHCPV6_548 = new PortNumber(548);
44 private static final ImmutableMap<PortNumber, PortNumber> dhcpSockets =
45 ImmutableMap.of(DHCP_67, DHCP_68, DHCP_68, DHCP_67, DHCPV6_548, DHCPV6_547, DHCPV6_547, DHCPV6_548);
47 AddressMapper(AccessListUtil.ACE_DIRECTION direction) {
48 this.direction = direction;
51 abstract void updateRule(AddressEndpointWithLocation addrEp, GbpAceBuilder aclRuleBuilder);
53 //TODO implement for peers with no location
54 abstract List<GbpAceBuilder> updateExtRules(List<GbpAceBuilder> rules, AddressEndpointWithLocation localEp,
55 ContainmentEndpoint cEp);
57 public boolean updateRules(List<GbpAceBuilder> rules, AddressEndpointWithLocation localEp,
58 AddressEndpointWithLocation peerEp) {
59 filterRulesWithIrrelevantAddresses(rules, localEp, peerEp);
60 for (GbpAceBuilder rule : rules) {
61 LOG.info("Rule: {} Updating rule between {} and {}. Start.", rule, localEp.getAddress(),
63 boolean isDhcpRule = dhcpSockets.entrySet().stream().anyMatch(dhcpSocket -> {
64 boolean srcMatch = isInRange(rule.getSourcePortRangeBuilder(), dhcpSocket.getKey());
65 boolean dstMatch = isInRange(rule.getDestinationPortRangeBuilder(), dhcpSocket.getValue());
66 return srcMatch && dstMatch;
69 if (!inSameSubnet(localEp, peerEp)) {
70 // do not process rules for DHCPs of other networks
71 LOG.info("Rule: {} Not updating rules between {} and {}. Returning false.", rule,
72 localEp.getAddress(), peerEp.getAddress());
75 // do not update addresses for DHCP traffic
76 LOG.info("Rule: {} Not updating rule between {} and {}. Continue with next.", rule,
77 localEp.getAddress(), peerEp.getAddress());
80 if (this instanceof SourceMapper) {
81 LOG.info("Rule: {} Updating rule between {} and {}. SourceMapper.", rule, localEp.getAddress(),
83 if (AccessListUtil.ACE_DIRECTION.INGRESS.equals(direction)) {
84 updateRule(localEp, rule);
87 updateRule(peerEp, rule);
88 } else if (this instanceof DestinationMapper) {
89 LOG.info("Rule: {} Updating rule between {} and {}. SourceMapper.", rule, localEp.getAddress(),
91 if (AccessListUtil.ACE_DIRECTION.INGRESS.equals(direction)) {
92 updateRule(peerEp, rule);
95 updateRule(localEp, rule);
98 LOG.info("Updating rules between {} and {}. Done, returning true.",
99 localEp.getAddress(), peerEp.getAddress());
103 private void filterRulesWithIrrelevantAddresses(List<GbpAceBuilder> rules, AddressEndpointWithLocation localEp,
104 AddressEndpointWithLocation peerEp) {
106 if (!IpPrefixType.class.equals(localEp.getAddressType())
107 || !IpPrefixType.class.equals(peerEp.getAddressType())) {
110 boolean addressV4Check = AccessListUtil.isIpv4Address(localEp.getAddress())
111 && AccessListUtil.isIpv4Address(peerEp.getAddress());
112 boolean addressV6Check = AccessListUtil.isIpv6Address(localEp.getAddress())
113 && AccessListUtil.isIpv6Address(peerEp.getAddress());
114 Predicate<GbpAceBuilder> p;
115 if (addressV4Check) {
116 p = rule -> rule.getEtherType().get() instanceof AceIpv6;
117 } else if (addressV6Check) {
118 p = rule -> rule.getEtherType().get() instanceof AceIpv4;
122 List<GbpAceBuilder> rulesToRemove = rules.stream()
123 .filter(rule -> rule.getEtherType().isPresent())
125 .collect(Collectors.toList());
126 rulesToRemove.forEach(rule -> { LOG.info("Filtering rules by ethertype {}", rule); rules.remove(rule);});
127 } catch (UnknownHostException e) {
128 LOG.error("Failed to parse addresses {}", e);
132 private static boolean inSameSubnet(AddressEndpointWithLocation localEp, AddressEndpointWithLocation peerEp) {
133 List<Predicate<AddressEndpointWithLocation>> list = new ArrayList<>();
134 list.add(x -> x != null);
135 list.add(x -> x.getContextType().equals(L3Context.class));
136 list.add(x -> x.getChildEndpoint() != null && !x.getChildEndpoint().isEmpty());
137 list.add(x -> x.getAbsoluteLocation() != null);
138 list.add(x -> x.getChildEndpoint().get(0).getContextType().equals(L2BridgeDomain.class));
139 list.add(x -> x.getChildEndpoint().get(0).getAddressType().equals(MacAddressType.class));
140 if (list.stream().filter(i -> !i.apply(peerEp)).findFirst().isPresent()) {
143 return localEp.getChildEndpoint().get(0).getContextId().equals(peerEp.getChildEndpoint().get(0).getContextId());
146 private static boolean isInRange(SourcePortRangeBuilder spr, PortNumber portNumber) {
147 return spr != null && isInRange(spr.getLowerPort(), spr.getUpperPort(), portNumber);
150 private static boolean isInRange(DestinationPortRangeBuilder dpr, PortNumber portNumber) {
151 return dpr != null && isInRange(dpr.getLowerPort(),dpr.getUpperPort(), portNumber);
154 private static boolean isInRange(PortNumber lower, PortNumber upper, PortNumber ref) {
155 if (lower != null && upper != null) {
156 return (lower.getValue() <= ref.getValue()) && (ref.getValue() <= upper.getValue());
158 return (lower != null && lower.getValue().equals(ref.getValue()))
159 || (upper != null && upper.getValue().equals(ref.getValue()));