X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;f=openflowplugin-impl%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fopenflowplugin%2Fimpl%2Fprotocol%2Fserialization%2Fmessages%2FFlowMessageSerializer.java;h=3eb2ad90abdaaccfd30f2f101d4c6c4817f442b8;hb=734f0886b8caf65dd749136ef8707b498d4e80fb;hp=49be46c0b487a7d6f6cd614ed4684d422b0d2029;hpb=0abc5bfe547f68c0d708ebc8aa69237ac6453417;p=openflowplugin.git diff --git a/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/protocol/serialization/messages/FlowMessageSerializer.java b/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/protocol/serialization/messages/FlowMessageSerializer.java index 49be46c0b4..3eb2ad90ab 100644 --- a/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/protocol/serialization/messages/FlowMessageSerializer.java +++ b/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/protocol/serialization/messages/FlowMessageSerializer.java @@ -5,18 +5,17 @@ * terms of the Eclipse Public License v1.0 which accompanies this distribution, * and is available at http://www.eclipse.org/legal/epl-v10.html */ - package org.opendaylight.openflowplugin.impl.protocol.serialization.messages; -import com.google.common.base.MoreObjects; +import static java.util.Objects.requireNonNull; +import static java.util.Objects.requireNonNullElse; + import io.netty.buffer.ByteBuf; -import java.math.BigInteger; import java.util.ArrayList; -import java.util.Collection; -import java.util.List; +import java.util.Map; import java.util.Objects; -import java.util.Optional; -import java.util.stream.Collectors; +import java.util.stream.Stream; +import org.eclipse.jdt.annotation.Nullable; import org.opendaylight.openflowjava.protocol.api.extensibility.OFSerializer; import org.opendaylight.openflowjava.protocol.api.extensibility.SerializerRegistry; import org.opendaylight.openflowjava.protocol.api.extensibility.SerializerRegistryInjector; @@ -26,7 +25,6 @@ import org.opendaylight.openflowjava.util.ByteBufUtils; import org.opendaylight.openflowplugin.api.OFConstants; import org.opendaylight.openflowplugin.impl.protocol.serialization.util.InstructionUtil; import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.common.OrderComparator; -import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.ActionList; import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.VlanCfi; import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.PushVlanActionCaseBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetTpDstActionCase; @@ -39,6 +37,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.acti import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.set.tp.src.action._case.SetTpSrcActionBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action; import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionKey; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.Flow; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.FlowCookie; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.FlowMessage; @@ -56,6 +55,11 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.VlanMatch; import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.VlanMatchBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.vlan.match.fields.VlanIdBuilder; +import org.opendaylight.yangtools.yang.binding.util.BindingMap; +import org.opendaylight.yangtools.yang.common.Uint16; +import org.opendaylight.yangtools.yang.common.Uint32; +import org.opendaylight.yangtools.yang.common.Uint64; +import org.opendaylight.yangtools.yang.common.Uint8; /** * Translates FlowMod messages. @@ -65,35 +69,36 @@ public class FlowMessageSerializer extends AbstractMessageSerializer>getSerializer(new MessageTypeKey<>(message.getVersion(), Match.class)) - .serialize(message.getMatch(), outBuffer); - + requireNonNull(registry).>getSerializer( + new MessageTypeKey<>(message.getVersion(), Match.class)).serialize(message.getMatch(), outBuffer); } /** @@ -175,27 +168,41 @@ public class FlowMessageSerializer extends AbstractMessageSerializer protocol = Optional - .ofNullable(message.getMatch()) - .flatMap(m -> Optional.ofNullable(m.getIpMatch())) - .flatMap(ipm -> Optional.ofNullable(ipm.getIpProtocol())); + final var instructions = message.getInstructions(); + if (instructions == null) { + // Nothing to do + return; + } + + // Extract all instructions ... + Stream flowInstructions = instructions.nonnullInstruction().values().stream() + .filter(Objects::nonNull) + .sorted(OrderComparator.build()) + .map(org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.Instruction::getInstruction) + .filter(Objects::nonNull); - // Update instructions if needed and then serialize all instructions - Optional.ofNullable(message.getInstructions()) - .flatMap(is -> Optional.ofNullable(is.getInstruction())) - .ifPresent(is -> is - .stream() - .filter(Objects::nonNull) - .sorted(OrderComparator.build()) - .map(org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types - .rev131026.Instruction::getInstruction) - .filter(Objects::nonNull) - .map(i -> protocol.flatMap(p -> updateInstruction(i, p)).orElse(i)) - .forEach(i -> InstructionUtil.writeInstruction(i, EncodeConstants.OF13_VERSION_ID, registry, - outBuffer))); + // ... updated them if needed ... + final Uint8 protocol = extractProtocol(message); + if (protocol != null) { + flowInstructions = flowInstructions.map(insn -> updateInstruction(insn, protocol)); + } + + // ... and serialize them + flowInstructions.forEach(i -> InstructionUtil.writeInstruction(i, EncodeConstants.OF_VERSION_1_3, registry, + outBuffer)); + } + + // Try to get IP protocol from IP match + private static @Nullable Uint8 extractProtocol(final FlowMessage message) { + final var match = message.getMatch(); + if (match != null) { + final var ipMatch = match.getIpMatch(); + if (ipMatch != null) { + return ipMatch.getIpProtocol(); + } + } + return null; } /** @@ -203,25 +210,23 @@ public class FlowMessageSerializer extends AbstractMessageSerializer updateInstruction(final Instruction instruction, final Short protocol) { - if (ApplyActionsCase.class.isInstance(instruction)) { - return Optional - .ofNullable(ApplyActionsCase.class.cast(instruction).getApplyActions()) - .flatMap(aa -> Optional.ofNullable(aa.getAction())) - .map(as -> new ApplyActionsCaseBuilder() - .setApplyActions(new ApplyActionsBuilder() - .setAction(as - .stream() - .filter(Objects::nonNull) - .map(a -> updateSetTpActions(a, protocol)) - .collect(Collectors.toList())) - .build()) - .build()); + private static Instruction updateInstruction(final Instruction instruction, final Uint8 protocol) { + if (instruction instanceof ApplyActionsCase applyActionsCase) { + final var actions = applyActionsCase.getApplyActions(); + if (actions != null) { + return new ApplyActionsCaseBuilder() + .setApplyActions(new ApplyActionsBuilder() + .setAction(actions.nonnullAction().values().stream() + .filter(Objects::nonNull) + .map(a -> updateSetTpActions(a, protocol)) + .collect(BindingMap.toOrderedMap())) + .build()) + .build(); + } } - - return Optional.empty(); + return instruction; } /** @@ -231,29 +236,24 @@ public class FlowMessageSerializer extends AbstractMessageSerializer updateSetVlanIdAction(final FlowMessage message) { - return message.getInstructions().getInstruction() - .stream() - .map(i -> { - final int[] offset = {0}; + private static Map< + org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionKey, + org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction> + updateSetVlanIdAction(final FlowMessage message) { + return message.getInstructions().nonnullInstruction().values().stream() + .map(FlowMessageSerializer::updateSetVlanIdAction) + .collect(BindingMap.toOrderedMap()); + } + + private static org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction + updateSetVlanIdAction(final org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction + .list.Instruction insn) { + if (insn.getInstruction() instanceof ApplyActionsCase applyActionsCase) { + final var applyActions = applyActionsCase.getApplyActions(); + if (applyActions != null) { + final var actions = applyActions.getAction(); + if (actions != null && !actions.isEmpty()) { + final int[] offset = { 0 }; - return ApplyActionsCase.class.isInstance(i.getInstruction()) - ? Optional - .ofNullable(ApplyActionsCase.class.cast(i.getInstruction()).getApplyActions()) - .flatMap(as -> Optional.ofNullable(as.getAction())) - .map(a -> a.stream() + return new InstructionBuilder(insn) + .setInstruction(new ApplyActionsCaseBuilder() + .setApplyActions(new ApplyActionsBuilder() + .setAction(actions.values().stream() .sorted(OrderComparator.build()) .flatMap(action -> { - final List actions = new ArrayList<>(); - - // If current action is SetVlanId, insert PushVlan action before it and - // update order - if (SetVlanIdActionCase.class.isInstance(action.getAction())) { - actions.add(new ActionBuilder() - .setAction(new PushVlanActionCaseBuilder() - .setPushVlanAction(new PushVlanActionBuilder() - .setCfi(new VlanCfi(1)) - .setVlanId(SetVlanIdActionCase.class.cast(action - .getAction()).getSetVlanIdAction() - .getVlanId()) - .setEthernetType(PUSH_VLAN) - .setTag(PUSH_VLAN) - .build()) - .build()) - .setKey(action.getKey()) - .setOrder(action.getOrder() + offset[0]) - .build()); + final var actionList = new ArrayList(); + // If current action is SetVlanId, insert PushVlan action before it and update + // order + if (action.getAction() instanceof SetVlanIdActionCase setVlanIdActionCase) { + actionList.add(new ActionBuilder() + .setAction(new PushVlanActionCaseBuilder() + .setPushVlanAction(new PushVlanActionBuilder() + .setCfi(PUSH_CFI) + .setVlanId(setVlanIdActionCase.getSetVlanIdAction().getVlanId()) + .setEthernetType(PUSH_VLAN) + .setTag(PUSH_TAG) + .build()) + .build()) + .withKey(action.key()) + .setOrder(action.getOrder() + offset[0]) + .build()); offset[0]++; } // Update offset of action if there is any inserted PushVlan actions - actions.add(offset[0] > 0 - ? new ActionBuilder(action).setOrder(action.getOrder() + offset[0]) - .build() - : action); - - return actions.stream(); - })) - .map(as -> new InstructionBuilder(i) - .setInstruction(new ApplyActionsCaseBuilder() - .setApplyActions(new ApplyActionsBuilder() - .setAction(as.collect(Collectors.toList())) - .build()) - .build()) - .build()) - .orElse(i) - : i; - }).collect(Collectors.toList()); + actionList.add(offset[0] <= 0 ? action : new ActionBuilder(action) + .setOrder(action.getOrder() + offset[0]) + .withKey(new ActionKey(action.getOrder() + offset[0])) + .build()); + return actionList.stream(); + }).collect(BindingMap.toOrderedMap())) + .build()) + .build()) + .build(); + } + } + } + return insn; } /** @@ -336,11 +340,11 @@ public class FlowMessageSerializer extends AbstractMessageSerializer Optional.ofNullable(m.getVlanMatch())) - .isPresent(); + final var match = flow.getMatch(); + return match != null && match.getVlanMatch() != null; } /** @@ -367,23 +369,15 @@ public class FlowMessageSerializer extends AbstractMessageSerializer Optional.ofNullable(is.getInstruction())) - .flatMap(is -> is - .stream() - .map(org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types - .rev131026.Instruction::getInstruction) - .filter(ApplyActionsCase.class::isInstance) - .map(i -> ApplyActionsCase.class.cast(i).getApplyActions()) - .filter(Objects::nonNull) - .map(ActionList::getAction) - .filter(Objects::nonNull) - .flatMap(Collection::stream) - .map(Action::getAction) - .filter(SetVlanIdActionCase.class::isInstance) - .findFirst()) - .isPresent(); + final var instructions = flow.getInstructions(); + return instructions != null && instructions.nonnullInstruction().values().stream() + .map(org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.Instruction::getInstruction) + .filter(ApplyActionsCase.class::isInstance) + .map(i -> ((ApplyActionsCase) i).getApplyActions()) + .filter(Objects::nonNull) + .flatMap(actionList -> actionList.nonnullAction().values().stream()) + .map(Action::getAction) + .anyMatch(SetVlanIdActionCase.class::isInstance); } @Override @@ -392,7 +386,7 @@ public class FlowMessageSerializer extends AbstractMessageSerializer