/* * Copyright (c) 2016 Pantheon Technologies s.r.o. and others. All rights reserved. * * This program and the accompanying materials are made available under the * 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.deserialization; import com.google.common.annotations.VisibleForTesting; import java.util.function.Consumer; import java.util.function.Function; import org.opendaylight.openflowjava.protocol.api.extensibility.DeserializerExtensionProvider; import org.opendaylight.openflowjava.protocol.api.keys.MatchEntryDeserializerKey; import org.opendaylight.openflowjava.protocol.api.util.EncodeConstants; import org.opendaylight.openflowjava.protocol.api.util.OxmMatchConstants; import org.opendaylight.openflowplugin.api.openflow.protocol.deserialization.MatchEntryDeserializer; import org.opendaylight.openflowplugin.api.openflow.protocol.deserialization.MatchEntryDeserializerRegistry; import org.opendaylight.openflowplugin.extension.api.path.MatchPath; import org.opendaylight.openflowplugin.impl.protocol.deserialization.key.MessageCodeMatchKey; import org.opendaylight.openflowplugin.impl.protocol.deserialization.match.ArpOpEntryDeserializer; import org.opendaylight.openflowplugin.impl.protocol.deserialization.match.ArpSourceHardwareAddressEntryDeserializer; import org.opendaylight.openflowplugin.impl.protocol.deserialization.match.ArpSourceTransportAddressEntryDeserializer; import org.opendaylight.openflowplugin.impl.protocol.deserialization.match.ArpTargetHardwareAddressEntryDeserializer; import org.opendaylight.openflowplugin.impl.protocol.deserialization.match.ArpTargetTransportAddressEntryDeserializer; import org.opendaylight.openflowplugin.impl.protocol.deserialization.match.EthernetDestinationEntryDeserializer; import org.opendaylight.openflowplugin.impl.protocol.deserialization.match.EthernetSourceEntryDeserializer; import org.opendaylight.openflowplugin.impl.protocol.deserialization.match.EthernetTypeEntryDeserializer; import org.opendaylight.openflowplugin.impl.protocol.deserialization.match.Icmpv4CodeEntryDeserializer; import org.opendaylight.openflowplugin.impl.protocol.deserialization.match.Icmpv4TypeEntryDeserializer; import org.opendaylight.openflowplugin.impl.protocol.deserialization.match.Icmpv6CodeEntryDeserializer; import org.opendaylight.openflowplugin.impl.protocol.deserialization.match.Icmpv6TypeEntryDeserializer; import org.opendaylight.openflowplugin.impl.protocol.deserialization.match.InPhyPortEntryDeserializer; import org.opendaylight.openflowplugin.impl.protocol.deserialization.match.InPortEntryDeserializer; import org.opendaylight.openflowplugin.impl.protocol.deserialization.match.IpDscpEntryDeserializer; import org.opendaylight.openflowplugin.impl.protocol.deserialization.match.IpEcnEntryDeserializer; import org.opendaylight.openflowplugin.impl.protocol.deserialization.match.IpProtoEntryDeserializer; import org.opendaylight.openflowplugin.impl.protocol.deserialization.match.Ipv4DestinationEntryDeserializer; import org.opendaylight.openflowplugin.impl.protocol.deserialization.match.Ipv4SourceEntryDeserializer; import org.opendaylight.openflowplugin.impl.protocol.deserialization.match.Ipv6DestinationEntryDeserializer; import org.opendaylight.openflowplugin.impl.protocol.deserialization.match.Ipv6ExtHeaderEntryDeserializer; import org.opendaylight.openflowplugin.impl.protocol.deserialization.match.Ipv6FlabelEntryDeserializer; import org.opendaylight.openflowplugin.impl.protocol.deserialization.match.Ipv6NdSllEntryDeserializer; import org.opendaylight.openflowplugin.impl.protocol.deserialization.match.Ipv6NdTargetEntryDeserializer; import org.opendaylight.openflowplugin.impl.protocol.deserialization.match.Ipv6NdTllEntryDeserializer; import org.opendaylight.openflowplugin.impl.protocol.deserialization.match.Ipv6SourceEntryDeserializer; import org.opendaylight.openflowplugin.impl.protocol.deserialization.match.MatchDeserializer; import org.opendaylight.openflowplugin.impl.protocol.deserialization.match.MetadataEntryDeserializer; import org.opendaylight.openflowplugin.impl.protocol.deserialization.match.MplsBosEntryDeserializer; import org.opendaylight.openflowplugin.impl.protocol.deserialization.match.MplsLabelEntryDeserializer; import org.opendaylight.openflowplugin.impl.protocol.deserialization.match.MplsTcEntryDeserializer; import org.opendaylight.openflowplugin.impl.protocol.deserialization.match.PbbEntryDeserializer; import org.opendaylight.openflowplugin.impl.protocol.deserialization.match.SctpDestinationPortEntryDeserializer; import org.opendaylight.openflowplugin.impl.protocol.deserialization.match.SctpSourcePortEntryDeserializer; import org.opendaylight.openflowplugin.impl.protocol.deserialization.match.TcpDestinationPortEntryDeserializer; import org.opendaylight.openflowplugin.impl.protocol.deserialization.match.TcpFlagsEntryDeserializer; import org.opendaylight.openflowplugin.impl.protocol.deserialization.match.TcpSourcePortEntryDeserializer; import org.opendaylight.openflowplugin.impl.protocol.deserialization.match.TunnelIdEntryDeserializer; import org.opendaylight.openflowplugin.impl.protocol.deserialization.match.UdpDestinationPortEntryDeserializer; import org.opendaylight.openflowplugin.impl.protocol.deserialization.match.UdpSourcePortEntryDeserializer; import org.opendaylight.openflowplugin.impl.protocol.deserialization.match.VlanPcpEntryDeserializer; import org.opendaylight.openflowplugin.impl.protocol.deserialization.match.VlanVidEntryDeserializer; import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.Match; /** * Util class for injecting new match entry deserializers into OpenflowJava */ public class MatchDeserializerInjector { /** * Injects deserializers into provided {@link org.opendaylight.openflowjava.protocol.api.extensibility.DeserializerExtensionProvider} * @param provider OpenflowJava deserializer extension provider */ static void injectDeserializers(final DeserializerExtensionProvider provider) { for (MatchPath path : MatchPath.values()) { final MatchDeserializer deserializer = new MatchDeserializer(path); provider.registerDeserializer( new MessageCodeMatchKey( EncodeConstants.OF13_VERSION_ID, EncodeConstants.EMPTY_LENGTH, Match.class, path), deserializer); // Inject new match entry serializers here using injector created by createInjector method final Function<Integer, Function<Long, Function<Integer, Consumer<MatchEntryDeserializer>>>> injector = createInjector(deserializer, EncodeConstants.OF13_VERSION_ID); // Wrapped injector that uses OPENFLOW_BASIC_CLASS final Function<Integer, Consumer<MatchEntryDeserializer>> basicInjector = injector.apply(OxmMatchConstants.OPENFLOW_BASIC_CLASS).apply(null); // Wrapped injector that uses EXPERIMENTER_CLASS final Function<Long, Function<Integer, Consumer<MatchEntryDeserializer>>> experInjector = injector.apply(OxmMatchConstants.EXPERIMENTER_CLASS); basicInjector.apply(OxmMatchConstants.ARP_OP).accept(new ArpOpEntryDeserializer()); basicInjector.apply(OxmMatchConstants.ARP_SHA).accept(new ArpSourceHardwareAddressEntryDeserializer()); basicInjector.apply(OxmMatchConstants.ARP_THA).accept(new ArpTargetHardwareAddressEntryDeserializer()); basicInjector.apply(OxmMatchConstants.ARP_SPA).accept(new ArpSourceTransportAddressEntryDeserializer()); basicInjector.apply(OxmMatchConstants.ARP_TPA).accept(new ArpTargetTransportAddressEntryDeserializer()); basicInjector.apply(OxmMatchConstants.IN_PORT).accept(new InPortEntryDeserializer()); basicInjector.apply(OxmMatchConstants.IN_PHY_PORT).accept(new InPhyPortEntryDeserializer()); basicInjector.apply(OxmMatchConstants.METADATA).accept(new MetadataEntryDeserializer()); basicInjector.apply(OxmMatchConstants.ETH_DST).accept(new EthernetDestinationEntryDeserializer()); basicInjector.apply(OxmMatchConstants.ETH_SRC).accept(new EthernetSourceEntryDeserializer()); basicInjector.apply(OxmMatchConstants.ETH_TYPE).accept(new EthernetTypeEntryDeserializer()); basicInjector.apply(OxmMatchConstants.VLAN_PCP).accept(new VlanPcpEntryDeserializer()); basicInjector.apply(OxmMatchConstants.VLAN_VID).accept(new VlanVidEntryDeserializer()); basicInjector.apply(OxmMatchConstants.IP_DSCP).accept(new IpDscpEntryDeserializer()); basicInjector.apply(OxmMatchConstants.IP_ECN).accept(new IpEcnEntryDeserializer()); basicInjector.apply(OxmMatchConstants.IP_PROTO).accept(new IpProtoEntryDeserializer()); basicInjector.apply(OxmMatchConstants.TCP_SRC).accept(new TcpSourcePortEntryDeserializer()); basicInjector.apply(OxmMatchConstants.TCP_DST).accept(new TcpDestinationPortEntryDeserializer()); basicInjector.apply(OxmMatchConstants.UDP_SRC).accept(new UdpSourcePortEntryDeserializer()); basicInjector.apply(OxmMatchConstants.UDP_DST).accept(new UdpDestinationPortEntryDeserializer()); basicInjector.apply(OxmMatchConstants.SCTP_SRC).accept(new SctpSourcePortEntryDeserializer()); basicInjector.apply(OxmMatchConstants.SCTP_DST).accept(new SctpDestinationPortEntryDeserializer()); basicInjector.apply(OxmMatchConstants.ICMPV4_CODE).accept(new Icmpv4CodeEntryDeserializer()); basicInjector.apply(OxmMatchConstants.ICMPV4_TYPE).accept(new Icmpv4TypeEntryDeserializer()); basicInjector.apply(OxmMatchConstants.ICMPV6_CODE).accept(new Icmpv6CodeEntryDeserializer()); basicInjector.apply(OxmMatchConstants.ICMPV6_TYPE).accept(new Icmpv6TypeEntryDeserializer()); // TODO: How to differentiate between Ipv4 and Tunnel when both are serialized to same format? basicInjector.apply(OxmMatchConstants.IPV4_SRC).accept(new Ipv4SourceEntryDeserializer()); basicInjector.apply(OxmMatchConstants.IPV4_DST).accept(new Ipv4DestinationEntryDeserializer()); basicInjector.apply(OxmMatchConstants.IPV6_SRC).accept(new Ipv6SourceEntryDeserializer()); basicInjector.apply(OxmMatchConstants.IPV6_DST).accept(new Ipv6DestinationEntryDeserializer()); basicInjector.apply(OxmMatchConstants.IPV6_EXTHDR).accept(new Ipv6ExtHeaderEntryDeserializer()); basicInjector.apply(OxmMatchConstants.IPV6_FLABEL).accept(new Ipv6FlabelEntryDeserializer()); basicInjector.apply(OxmMatchConstants.IPV6_ND_SLL).accept(new Ipv6NdSllEntryDeserializer()); basicInjector.apply(OxmMatchConstants.IPV6_ND_TLL).accept(new Ipv6NdTllEntryDeserializer()); basicInjector.apply(OxmMatchConstants.IPV6_ND_TARGET).accept(new Ipv6NdTargetEntryDeserializer()); basicInjector.apply(OxmMatchConstants.MPLS_LABEL).accept(new MplsLabelEntryDeserializer()); basicInjector.apply(OxmMatchConstants.MPLS_BOS).accept(new MplsBosEntryDeserializer()); basicInjector.apply(OxmMatchConstants.MPLS_TC).accept(new MplsTcEntryDeserializer()); basicInjector.apply(OxmMatchConstants.PBB_ISID).accept(new PbbEntryDeserializer()); basicInjector.apply(OxmMatchConstants.TUNNEL_ID).accept(new TunnelIdEntryDeserializer()); experInjector.apply(EncodeConstants.ONF_EXPERIMENTER_ID).apply(EncodeConstants.ONFOXM_ET_TCP_FLAGS).accept(new TcpFlagsEntryDeserializer()); } } /** * Create injector that will inject new serializers into {@link org.opendaylight.openflowplugin.api.openflow.protocol.deserialization.MatchEntryDeserializerRegistry} * @param registry Match entry deserializer registry * @param version Openflow version * @return injector */ @VisibleForTesting static Function<Integer, Function<Long, Function<Integer, Consumer<MatchEntryDeserializer>>>> createInjector( final MatchEntryDeserializerRegistry registry, final short version ) { return oxmClass -> expId -> oxmField -> deserializer -> { final MatchEntryDeserializerKey key = new MatchEntryDeserializerKey(version, oxmClass, oxmField); key.setExperimenterId(expId); registry.registerEntryDeserializer(key, deserializer); }; } }