import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
-import io.fd.honeycomb.translate.v3po.acl.AclWriter;
-import io.fd.honeycomb.translate.v3po.util.TranslateUtils;
-import io.fd.honeycomb.translate.v3po.util.WriteTimeoutException;
+import io.fd.honeycomb.translate.vpp.util.JvppReplyConsumer;
+import io.fd.honeycomb.translate.vpp.util.WriteTimeoutException;
import io.fd.honeycomb.translate.write.WriteContext;
import io.fd.honeycomb.translate.write.WriteFailedException;
import java.util.HashMap;
import java.util.concurrent.CompletionStage;
import java.util.stream.Collectors;
import java.util.stream.Stream;
+import javax.annotation.Nonnegative;
import javax.annotation.Nonnull;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.AclBase;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.access.lists.AclKey;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.access.lists.acl.access.list.entries.ace.matches.ace.type.ace.ip.ace.ip.version.AceIpv4;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.ietf.acl.base.attributes.access.lists.Acl;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-import org.openvpp.jvpp.VppBaseCallException;
-import org.openvpp.jvpp.core.dto.ClassifyAddDelTable;
-import org.openvpp.jvpp.core.dto.ClassifyAddDelTableReply;
-import org.openvpp.jvpp.core.dto.ClassifyTableByInterface;
-import org.openvpp.jvpp.core.dto.ClassifyTableByInterfaceReply;
-import org.openvpp.jvpp.core.dto.InputAclSetInterface;
-import org.openvpp.jvpp.core.dto.InputAclSetInterfaceReply;
-import org.openvpp.jvpp.core.future.FutureJVppCore;
+import io.fd.vpp.jvpp.VppBaseCallException;
+import io.fd.vpp.jvpp.core.dto.ClassifyAddDelTable;
+import io.fd.vpp.jvpp.core.dto.ClassifyAddDelTableReply;
+import io.fd.vpp.jvpp.core.dto.ClassifyTableByInterface;
+import io.fd.vpp.jvpp.core.dto.ClassifyTableByInterfaceReply;
+import io.fd.vpp.jvpp.core.dto.InputAclSetInterface;
+import io.fd.vpp.jvpp.core.dto.InputAclSetInterfaceReply;
+import io.fd.vpp.jvpp.core.future.FutureJVppCore;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-public final class IetfAClWriter {
+public final class IetfAClWriter implements JvppReplyConsumer {
private static final Logger LOG = LoggerFactory.getLogger(IetfAClWriter.class);
private final FutureJVppCore jvpp;
this.jvpp = Preconditions.checkNotNull(futureJVppCore, "futureJVppCore should not be null");
aceWriters.put(AclType.ETH, new AceEthWriter(futureJVppCore));
aceWriters.put(AclType.IP4, new AceIp4Writer(futureJVppCore));
+ aceWriters.put(AclType.IP6, new AceIp6Writer(futureJVppCore));
+ }
+
+ private static Stream<Ace> aclToAceStream(@Nonnull final Acl assignedAcl,
+ @Nonnull final WriteContext writeContext) {
+ final String aclName = assignedAcl.getName();
+ final Class<? extends AclBase> aclType = assignedAcl.getType();
+
+ // ietf-acl updates are handled first, so we use writeContext.readAfter
+ final Optional<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.access.lists.Acl>
+ aclOptional = writeContext.readAfter(AclWriter.ACL_ID.child(
+ org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.access.lists.Acl.class,
+ new AclKey(aclName, aclType)));
+ checkArgument(aclOptional.isPresent(), "Acl lists not configured");
+ final org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.access.lists.Acl
+ acl = aclOptional.get();
+
+ final AccessListEntries accessListEntries = acl.getAccessListEntries();
+ checkArgument(accessListEntries != null, "access list entries not configured");
+
+ return accessListEntries.getAce().stream();
}
void deleteAcl(@Nonnull final InstanceIdentifier<?> id, final int swIfIndex)
- throws WriteTimeoutException, WriteFailedException.DeleteFailedException {
+ throws WriteTimeoutException, WriteFailedException.DeleteFailedException {
final ClassifyTableByInterface request = new ClassifyTableByInterface();
request.swIfIndex = swIfIndex;
- jvpp.classifyTableByInterface(request);
try {
final CompletionStage<ClassifyTableByInterfaceReply> cs = jvpp.classifyTableByInterface(request);
- final ClassifyTableByInterfaceReply reply = TranslateUtils.getReplyForWrite(cs.toCompletableFuture(), id);
+ final ClassifyTableByInterfaceReply reply = getReplyForWrite(cs.toCompletableFuture(), id);
+
+ // We unassign and remove all ACL-related classify tables for given interface (we assume we are the only
+ // classify table manager)
+
+ unassignClassifyTables(id, reply);
- // We remove all ACL-related classify tables for given interface (we assume we are the only classify table
- // manager)
removeClassifyTable(id, reply.l2TableId);
removeClassifyTable(id, reply.ip4TableId);
removeClassifyTable(id, reply.ip6TableId);
}
}
+ private void unassignClassifyTables(@Nonnull final InstanceIdentifier<?> id,
+ final ClassifyTableByInterfaceReply currentState)
+ throws VppBaseCallException, WriteTimeoutException {
+ final InputAclSetInterface request = new InputAclSetInterface();
+ request.isAdd = 0;
+ request.swIfIndex = currentState.swIfIndex;
+ request.l2TableIndex = currentState.l2TableId;
+ request.ip4TableIndex = currentState.ip4TableId;
+ request.ip6TableIndex = currentState.ip6TableId;
+ final CompletionStage<InputAclSetInterfaceReply> inputAclSetInterfaceReplyCompletionStage =
+ jvpp.inputAclSetInterface(request);
+ getReplyForWrite(inputAclSetInterfaceReplyCompletionStage.toCompletableFuture(), id);
+ }
+
private void removeClassifyTable(@Nonnull final InstanceIdentifier<?> id, final int tableIndex)
- throws VppBaseCallException, WriteTimeoutException {
+ throws VppBaseCallException, WriteTimeoutException {
if (tableIndex == -1) {
return; // classify table id is absent
final ClassifyAddDelTable request = new ClassifyAddDelTable();
request.tableIndex = tableIndex;
final CompletionStage<ClassifyAddDelTableReply> cs = jvpp.classifyAddDelTable(request);
- TranslateUtils.getReplyForWrite(cs.toCompletableFuture(), id);
+ getReplyForWrite(cs.toCompletableFuture(), id);
}
void write(@Nonnull final InstanceIdentifier<?> id, final int swIfIndex, @Nonnull final List<Acl> acls,
@Nonnull final WriteContext writeContext)
- throws VppBaseCallException, WriteTimeoutException {
+ throws VppBaseCallException, WriteTimeoutException {
+ write(id, swIfIndex, acls, writeContext, 0);
+ }
+
+ void write(@Nonnull final InstanceIdentifier<?> id, final int swIfIndex, @Nonnull final List<Acl> acls,
+ @Nonnull final WriteContext writeContext, @Nonnegative final int numberOfTags)
+ throws VppBaseCallException, WriteTimeoutException {
// filter ACE entries and group by AceType
final Map<AclType, List<Ace>> acesByType = acls.stream()
- .flatMap(acl -> aclToAceStream(acl, writeContext))
- // TODO we should not tolerate nulls, but throw some meaningful exceptions instead
- .filter(ace -> ace != null && ace.getMatches() != null && ace.getMatches().getAceType() != null &&
- ace.getActions() != null && ace.getActions().getPacketHandling() != null)
- .collect(Collectors.groupingBy(AclType::fromAce));
+ .flatMap(acl -> aclToAceStream(acl, writeContext))
+ .collect(Collectors.groupingBy(AclType::fromAce));
final InputAclSetInterface request = new InputAclSetInterface();
request.isAdd = 1;
if (aceWriter == null) {
LOG.warn("AceProcessor for {} not registered. Skipping ACE.", aceType);
} else {
- aceWriter.write(id, aces, request);
+ aceWriter.write(id, aces, request, numberOfTags);
}
}
final CompletionStage<InputAclSetInterfaceReply> inputAclSetInterfaceReplyCompletionStage =
- jvpp.inputAclSetInterface(request);
- TranslateUtils.getReplyForWrite(inputAclSetInterfaceReplyCompletionStage.toCompletableFuture(), id);
-
- }
-
- private static Stream<Ace> aclToAceStream(@Nonnull final Acl assignedAcl,
- @Nonnull final WriteContext writeContext) {
- final String aclName = assignedAcl.getName();
- final Class<? extends AclBase> aclType = assignedAcl.getType();
-
- // ietf-acl updates are handled first, so we use writeContext.readAfter
- final Optional<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.access.lists.Acl>
- aclOptional = writeContext.readAfter(AclWriter.ACL_ID.child(
- org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.access.lists.Acl.class,
- new AclKey(aclName, aclType)));
- checkArgument(aclOptional.isPresent(), "Acl lists not configured");
- final org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.access.lists.Acl
- acl = aclOptional.get();
-
- final AccessListEntries accessListEntries = acl.getAccessListEntries();
- checkArgument(accessListEntries != null, "access list entries not configured");
-
- return accessListEntries.getAce().stream();
+ jvpp.inputAclSetInterface(request);
+ getReplyForWrite(inputAclSetInterfaceReplyCompletionStage.toCompletableFuture(), id);
}
private enum AclType {
@Nonnull
private static AclType fromAce(final Ace ace) {
AclType result = null;
- final AceType aceType = ace.getMatches().getAceType();
- if (aceType instanceof AceEth) {
- result = ETH;
- } else if (aceType instanceof AceIp) {
- final AceIpVersion aceIpVersion = ((AceIp) aceType).getAceIpVersion();
- if (aceIpVersion instanceof AceIpv4) {
- result = IP4;
- } else {
- result = IP6;
+ final AceType aceType;
+ try {
+ aceType = ace.getMatches().getAceType();
+ if (aceType instanceof AceEth) {
+ result = ETH;
+ } else if (aceType instanceof AceIp) {
+ final AceIpVersion aceIpVersion = ((AceIp) aceType).getAceIpVersion();
+ if (aceIpVersion instanceof AceIpv4) {
+ result = IP4;
+ } else {
+ result = IP6;
+ }
}
+ } catch (NullPointerException e) {
+ throw new IllegalArgumentException("Incomplete ACE: " + ace, e);
}
if (result == null) {
throw new IllegalArgumentException(String.format("Not supported ace type %s", aceType));