import org.opendaylight.groupbasedpolicy.renderer.vpp.policy.PolicyContext;
import org.opendaylight.groupbasedpolicy.renderer.vpp.policy.RendererResolvedPolicy;
import org.opendaylight.groupbasedpolicy.renderer.vpp.sf.SubjectFeatures;
-import org.opendaylight.groupbasedpolicy.util.EndpointUtils;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.access.lists.acl.access.list.entries.ace.Actions;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.access.lists.acl.access.list.entries.ace.ActionsBuilder;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.access.lists.acl.access.list.entries.ace.actions.packet.handling.PermitBuilder;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpPrefix;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Prefix;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Prefix;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.parent.child.endpoints.parent.endpoint.choice.parent.endpoint._case.ParentEndpoint;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev160427.SubnetAugmentRenderer;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev160427.has.subnet.Subnet;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.RuleName;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev170511.SubnetAugmentRenderer;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev170511.has.subnet.Subnet;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.HasDirection.Direction;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.subject.feature.instance.ParameterValue;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.EndpointPolicyParticipation;
import com.google.common.base.Optional;
- /*
- * Transforms Renderer policy into access-list configuration for Honeycomb.
- *
- * */
+/*
+ * Transforms Renderer policy into access-list configuration for Honeycomb.
+ *
+ */
public class AccessListUtil {
private static final Logger LOG = LoggerFactory.getLogger(AccessListUtil.class);
- private static final String UNDERSCORE = "_";
+ static final String UNDERSCORE = "_";
private static final String PERMIT_EXTERNAL_INGRESS = "permit_external_ingress";
private static final String PERMIT_EXTERNAL_EGRESS = "permit_external_egress";
private static final String DENY_INGRESS_IPV4 = "deny_ingress_ipv4";
.stream()
.filter(peerEpKey -> peerHasLocation(ctx, peerEpKey))
.forEach(peerEpKey -> {
+ List<GbpAceBuilder> rules = new ArrayList<>();
ctx.getPolicyTable().get(rEpKey, peerEpKey).forEach(resolvedRules -> {
- List<GbpAceBuilder> rules = new ArrayList<>();
- LOG.debug("Resolving policy for {} and peer endpoint {}", rEpKey, peerEpKey);
Direction classifDir = calculateClassifDirection(resolvedRules.getRendererEndpointParticipation(),
policyDirection);
- rules.addAll(resolveAclRulesFromPolicy(resolvedRules, classifDir,
- rEpKey.getAddress() + UNDERSCORE + peerEpKey.getAddress()));
- updateAddressesInRules(rules, rEpKey, peerEpKey, ctx, policyDirection, true);
- aclWrapper.writeRules(rules);
+ rules.addAll(resolveAclRulesFromPolicy(resolvedRules, classifDir, rEpKey, peerEpKey));
});
+ if (validateAndUpdateAddressesInRules(rules, rEpKey, peerEpKey, ctx, policyDirection, true)) {
+ aclWrapper.writeRules(rules);
+ }
});
}
/**
* Resolves direction for classifiers that will be applied to INBOUND or OUTBOUND direction.
* </p>
- * Rule is applied in INGRESS direction when participation is PROVIDER and classifier direction is OUT
+ * Rule is applied in INGRESS direction when participation is PROVIDER and classifier direction
+ * is OUT
* </p>
- * Rule is applied in INGRESS direction when participation is CONSUMER and classifier direction is IN
+ * Rule is applied in INGRESS direction when participation is CONSUMER and classifier direction
+ * is IN
* </p>
* INBOUND direction is applied otherwise.
* </p>
* </p>
* IN is resolved otherwise.
* </p>
+ *
* @param participation provider or consumer
* @param direction EGRESS or INGRESS
* @return Direction that classifiers should match for given policy direction.
*/
- private static Direction calculateClassifDirection(EndpointPolicyParticipation participation, ACE_DIRECTION direction) {
+ static Direction calculateClassifDirection(EndpointPolicyParticipation participation, ACE_DIRECTION direction) {
if (EndpointPolicyParticipation.PROVIDER.equals(participation) && ACE_DIRECTION.INGRESS.equals(direction)) {
return Direction.Out;
}
return Direction.In;
}
- private static void updateAddressesInRules(List<GbpAceBuilder> rules, RendererEndpointKey rEpKey,
+ static boolean validateAndUpdateAddressesInRules(List<GbpAceBuilder> rules, RendererEndpointKey rEpKey,
PeerEndpointKey peerEpKey, PolicyContext ctx, ACE_DIRECTION policyDirection,
boolean resolveForLocationPeers) {
for (AddressMapper addrMapper : Arrays.asList(new SourceMapper(policyDirection),
new DestinationMapper(policyDirection))) {
if (peerHasLocation(ctx, peerEpKey) && resolveForLocationPeers) {
- addrMapper.updateRules(rules, findAddrEp(ctx, rEpKey), findAddrEp(ctx, peerEpKey));
+ if (!addrMapper.updateRules(rules, findAddrEp(ctx, rEpKey), findAddrEp(ctx, peerEpKey))) {
+ return false;
+ }
} else if (!peerHasLocation(ctx, peerEpKey) && !resolveForLocationPeers) {
addrMapper.updateExtRules(rules, findAddrEp(ctx, rEpKey), null);
}
}
+ return true;
}
private static boolean peerHasLocation(PolicyContext ctx, PeerEndpointKey peerEpKey) {
- return ctx.getAddrEpByKey().get(
- AddressEndpointUtils.fromPeerEpKey(peerEpKey)) != null;
+ return ctx.getAddrEpByKey().get(AddressEndpointUtils.fromPeerEpKey(peerEpKey)) != null;
}
static AddressEndpointWithLocation findAddrEp(PolicyContext ctx, RendererEndpointKey rEpKey) {
- return ctx.getAddrEpByKey().get(
- AddressEndpointUtils.fromRendererEpKey(rEpKey));
+ return ctx.getAddrEpByKey().get(AddressEndpointUtils.fromRendererEpKey(rEpKey));
}
private static AddressEndpointWithLocation findAddrEp(PolicyContext ctx, PeerEndpointKey rEpKey) {
- return ctx.getAddrEpByKey().get(
- AddressEndpointUtils.fromPeerEpKey(rEpKey));
+ return ctx.getAddrEpByKey().get(AddressEndpointUtils.fromPeerEpKey(rEpKey));
}
- /** Transform a resolved rule to ACE with corresponding classification and action fields
+ /**
+ * Transform a resolved rule to ACE with corresponding classification and action fields
*
* @param resolvedPolicy resolved rules, with the same participation - provider or consumer
* @param direction rules matching corresponding direction will be collected
* @return resolved ACE entries
*/
+
+ static @Nonnull String resolveAceName(@Nonnull RuleName ruleName, @Nonnull RendererEndpointKey key,
+ @Nonnull PeerEndpointKey peer) {
+ return ruleName.getValue() + "_" + key.getAddress() + "_" + peer.getAddress();
+ }
+
private static List<GbpAceBuilder> resolveAclRulesFromPolicy(RendererResolvedPolicy resolvedPolicy,
- Direction direction, String namePasphrase) {
+ Direction direction, RendererEndpointKey r, PeerEndpointKey p) {
List<GbpAceBuilder> aclRules = new ArrayList<>();
for (ResolvedRule resolvedRule : resolvedPolicy.getRuleGroup().getRules()) {
- Map<String, ParameterValue> params = resolveClassifParamsForDir(direction, resolvedRule.getClassifier());
- if (params.isEmpty()) {
- continue;
- }
- LOG.debug("Processing classifification params {} in resolved rule {}.", params,
- resolvedRule.getName() + UNDERSCORE + namePasphrase);
- org.opendaylight.groupbasedpolicy.renderer.vpp.sf.Classifier classif =
- resolveImplementedClassifForDir(direction, resolvedRule.getClassifier());
- GbpAceBuilder aclRuleBuilder =
- new GbpAceBuilder(resolvedRule.getName().getValue() + UNDERSCORE + namePasphrase);
- boolean updated = classif != null && classif.updateMatch(aclRuleBuilder, params);
- Optional<Actions> optAction = resolveActions(resolvedRule.getAction());
- if (!optAction.isPresent() || !updated) {
- LOG.error("Failed to process rule {}. Resolved parameters {}, resolved classifier. Actions resolved: {}"
- + "{}.", resolvedRule.getName().getValue(), params, classif, optAction.isPresent());
- continue;
+ Optional<GbpAceBuilder> resolveAce = resolveAceClassifersAndAction(resolvedRule, direction,
+ resolveAceName(resolvedRule.getName(), r, p));
+ if (resolveAce.isPresent()) {
+ aclRules.add(resolveAce.get());
}
- aclRuleBuilder.setAction(optAction.get());
- aclRules.add(aclRuleBuilder);
}
return aclRules;
}
+ public static Optional<GbpAceBuilder> resolveAceClassifersAndAction(ResolvedRule resolvedRule, Direction direction,
+ String ruleName) {
+ Map<String, ParameterValue> params = resolveClassifParamsForDir(direction, resolvedRule.getClassifier());
+ if (params.isEmpty()) {
+ return Optional.absent();
+ }
+ org.opendaylight.groupbasedpolicy.renderer.vpp.sf.Classifier classif =
+ resolveImplementedClassifForDir(direction, resolvedRule.getClassifier());
+ GbpAceBuilder aclRuleBuilder = new GbpAceBuilder(ruleName);
+ // new GbpAceBuilder(resolvedRule.getName().getValue() + UNDERSCORE + namePasphrase);
+ boolean updated = classif != null && classif.updateMatch(aclRuleBuilder, params);
+ Optional<Actions> optAction = resolveActions(resolvedRule.getAction());
+ if (!optAction.isPresent() || !updated) {
+ LOG.error("Failed to process rule {}. Resolved parameters {}, resolved classifier. Actions resolved: {}"
+ + "{}.", resolvedRule.getName().getValue(), params, classif, optAction.isPresent());
+ return Optional.absent();
+ }
+ aclRuleBuilder.setAction(optAction.get());
+ return Optional.of(aclRuleBuilder);
+ }
+
private static org.opendaylight.groupbasedpolicy.renderer.vpp.sf.Classifier resolveImplementedClassifForDir(
@Nonnull Direction direction, @Nonnull List<Classifier> classifiers) {
org.opendaylight.groupbasedpolicy.renderer.vpp.sf.Classifier feasibleClassifier = null;
classifier.stream()
.filter(classif -> direction.equals(classif.getDirection()) || direction.equals(Direction.Bidirectional))
.forEach(classif -> {
- LOG.trace("Resolving parameters for classiifier: {} with direction", classif, direction);
classif.getParameterValue()
.stream()
.filter(v -> params.get(v.getName().getValue()) == null) // not unique
.filter(v -> v.getIntValue() != null || v.getStringValue() != null || v.getRangeValue() != null)
.forEach(v -> params.put(v.getName().getValue(), v));
- LOG.trace("Resolved parameters {} for classiifier: {} with direction {}", params, classif, direction);
});
return params;
}
private static Optional<Actions> resolveActions(List<Action> actions) {
for (Action action : actions) {
- if (AllowActionDefinition.ID
- .equals(action.getActionDefinitionId())) {
- LOG.trace("Applying supported action: {}", action);
+ if (AllowActionDefinition.ID.equals(action.getActionDefinitionId())) {
return Optional
.of(new ActionsBuilder().setPacketHandling(new PermitBuilder().setPermit(true).build()).build());
}
}
- LOG.warn("No supported action found among actions: {}", actions);
return Optional.absent();
}
* purposes
* TODO initial workaround for external networking
*/
- static Optional<GbpAceBuilder> allowExternalNetworksForEp(@Nonnull AddressEndpointWithLocation addrEp,
+ static GbpAceBuilder allowExternalNetworksForEp(@Nonnull RendererEndpointKey rendEp,
AccessListUtil.ACE_DIRECTION dir) {
- List<ParentEndpoint> parentEndpoints = EndpointUtils.getParentEndpoints(addrEp.getParentEndpointChoice());
- if (parentEndpoints.isEmpty()) {
- return Optional.absent();
+ InetAddress byName;
+ try {
+ byName = InetAddress.getByName(substringBeforeSlash(rendEp.getAddress()));
+ } catch (UnknownHostException e) {
+ LOG.error("Failed to parse IP address {}", e);
+ return null;
}
- for (ParentEndpoint parentEp : parentEndpoints) {
- InetAddress byName;
- try {
- byName = InetAddress.getByName(substringBeforeSlash(parentEp.getAddress()));
- } catch (UnknownHostException e) {
- LOG.error("Failed to parse IP address {}", e);
- return Optional.absent();
+ if (byName instanceof Inet4Address) {
+ if (AccessListUtil.ACE_DIRECTION.INGRESS.equals(dir)) {
+ return new GbpAceBuilder(PERMIT_EXTERNAL_INGRESS)
+ .setIpAddresses(new Ipv4Prefix(rendEp.getAddress()), null).setPermit();
+ } else {
+ return new GbpAceBuilder(PERMIT_EXTERNAL_EGRESS)
+ .setIpAddresses(null, new Ipv4Prefix(rendEp.getAddress())).setPermit();
}
- if (byName instanceof Inet4Address) {
- if (AccessListUtil.ACE_DIRECTION.INGRESS.equals(dir)) {
- return Optional.of(new GbpAceBuilder(PERMIT_EXTERNAL_INGRESS).setIpAddresses(
- new Ipv4Prefix(parentEp.getAddress()), null).setPermit());
- } else {
- return Optional.of(new GbpAceBuilder(PERMIT_EXTERNAL_EGRESS).setIpAddresses(null,
- new Ipv4Prefix(parentEp.getAddress())).setPermit());
- }
- } else if (byName instanceof Inet6Address) {
- if (AccessListUtil.ACE_DIRECTION.INGRESS.equals(dir)) {
- return Optional.of(new GbpAceBuilder(PERMIT_EXTERNAL_INGRESS).setIpAddresses(
- new Ipv6Prefix(parentEp.getAddress()), null).setPermit());
- } else {
- return Optional.of(new GbpAceBuilder(PERMIT_EXTERNAL_EGRESS).setIpAddresses(null,
- new Ipv6Prefix(parentEp.getAddress())).setPermit());
- }
+ } else if (byName instanceof Inet6Address) {
+ if (AccessListUtil.ACE_DIRECTION.INGRESS.equals(dir)) {
+ new GbpAceBuilder(PERMIT_EXTERNAL_INGRESS).setIpAddresses(new Ipv6Prefix(rendEp.getAddress()), null)
+ .setPermit();
+ } else {
+ new GbpAceBuilder(PERMIT_EXTERNAL_EGRESS).setIpAddresses(null, new Ipv6Prefix(rendEp.getAddress()))
+ .setPermit();
}
}
- return Optional.absent();
+ return null;
}
/**
.getRendererForwardingByTenant()) {
rf.getRendererNetworkDomain()
.stream()
- .filter(rnd -> org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev160427.Subnet.class
+ .filter(rnd -> org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev170511.Subnet.class
.equals(rnd.getNetworkDomainType()))
.forEach(rnd -> {
SubnetAugmentRenderer subnetAug = rnd.getAugmentation(SubnetAugmentRenderer.class);
subnetAug.getSubnet();
if (policyDirection.equals(ACE_DIRECTION.INGRESS) && subnetAug.getSubnet().isIsTenant()) {
aclRuleBuilders.add(denyIngressTrafficForPrefix(subnetAug.getSubnet()));
- }
- else if (subnetAug.getSubnet().isIsTenant()) {
+ } else if (subnetAug.getSubnet().isIsTenant()) {
aclRuleBuilders.add(denyEgressTrafficForPrefix(subnetAug.getSubnet()));
}
});
}
static void setSourceL3Address(GbpAceBuilder rule, String address) throws UnknownHostException {
- InetAddress addr = InetAddress.getByName(substringBeforeSlash(address));
- if (addr instanceof Inet6Address) {
+ if (isIpv6Address(address)) {
rule.setIpAddresses(new Ipv6Prefix(address), null);
} else {
rule.setIpAddresses(new Ipv4Prefix(address), null);
}
static void setDestinationL3Address(GbpAceBuilder rule, String address) throws UnknownHostException {
- InetAddress addr = InetAddress.getByName(substringBeforeSlash(address));
- if (addr instanceof Inet6Address) {
+ if (isIpv6Address(address)) {
rule.setIpAddresses(null, new Ipv6Prefix(address));
} else {
rule.setIpAddresses(null, new Ipv4Prefix(address));
}
}
+ public static boolean isIpv4Address(String address) throws UnknownHostException {
+ InetAddress addr = InetAddress.getByName(substringBeforeSlash(address));
+ return addr instanceof Inet4Address;
+ }
+
+ public static boolean isIpv6Address(String address) throws UnknownHostException {
+ InetAddress addr = InetAddress.getByName(substringBeforeSlash(address));
+ return addr instanceof Inet6Address;
+ }
+
static GbpAceBuilder denyIngressTrafficForPrefix(Subnet subnet) {
IpPrefix ipPrefix = subnet.getIpPrefix();
if (ipPrefix.getIpv4Prefix() != null) {