2 * Copyright (c) 2016 Pantheon Technologies s.r.o. 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.openflowplugin.impl.protocol.serialization.match;
11 import io.netty.buffer.ByteBuf;
12 import java.util.LinkedHashMap;
14 import java.util.Objects;
15 import org.opendaylight.openflowjava.protocol.api.extensibility.HeaderSerializer;
16 import org.opendaylight.openflowjava.protocol.api.extensibility.OFSerializer;
17 import org.opendaylight.openflowjava.protocol.api.extensibility.SerializerRegistry;
18 import org.opendaylight.openflowjava.protocol.api.extensibility.SerializerRegistryInjector;
19 import org.opendaylight.openflowjava.protocol.api.keys.MatchEntrySerializerKey;
20 import org.opendaylight.openflowjava.protocol.api.util.EncodeConstants;
21 import org.opendaylight.openflowplugin.api.OFConstants;
22 import org.opendaylight.openflowplugin.api.openflow.protocol.serialization.MatchEntrySerializer;
23 import org.opendaylight.openflowplugin.api.openflow.protocol.serialization.MatchEntrySerializerRegistry;
24 import org.opendaylight.openflowplugin.extension.api.ConverterExtensionKey;
25 import org.opendaylight.openflowplugin.openflow.md.core.extension.ExtensionResolvers;
26 import org.opendaylight.openflowplugin.openflow.md.core.session.OFSessionUtil;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.Match;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev150225.oxm.container.match.entry.value.ExperimenterIdCase;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.ExperimenterClass;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entries.grouping.MatchEntry;
31 import org.slf4j.Logger;
32 import org.slf4j.LoggerFactory;
34 public class MatchSerializer implements OFSerializer<Match>, HeaderSerializer<Match>,
35 MatchEntrySerializerRegistry, SerializerRegistryInjector {
37 private static final Logger LOG = LoggerFactory.getLogger(MatchSerializer.class);
38 private static final byte OXM_MATCH_TYPE_CODE = 1;
39 private final Map<org.opendaylight.openflowplugin.api.openflow.protocol.serialization.
40 MatchEntrySerializerKey, MatchEntrySerializer> entryRegistry = new LinkedHashMap<>();
41 private SerializerRegistry registry;
44 public void serialize(Match match, ByteBuf outBuffer) {
46 LOG.debug("Match is null");
50 // Save start index in buffer
51 int matchStartIndex = outBuffer.writerIndex();
53 // With OpenflowPlugin models, we cannot check difference between OXM and Standard match type
54 // so all matches will be OXM
55 outBuffer.writeShort(OXM_MATCH_TYPE_CODE);
57 // Save length of match type
58 int matchLengthIndex = outBuffer.writerIndex();
59 outBuffer.writeShort(EncodeConstants.EMPTY_LENGTH);
61 // Small hack to be able to serialize only match entryRegistry externally
62 serializeHeader(match, outBuffer);
64 // Length of ofp_match (excluding padding)
65 int matchLength = outBuffer.writerIndex() - matchStartIndex;
66 outBuffer.setShort(matchLengthIndex, matchLength);
68 // If we have any remaining padding, write it at end
69 int paddingRemainder = matchLength % EncodeConstants.PADDING;
70 if (paddingRemainder != 0) {
71 outBuffer.writeZero(EncodeConstants.PADDING - paddingRemainder);
76 public void serializeHeader(Match match, ByteBuf outBuffer) {
78 LOG.debug("Match is null");
82 // Serialize match entries
83 entryRegistry.entrySet().forEach(entry -> {
84 if (entry.getValue().matchTypeCheck(match)) {
85 entry.getValue().serialize(match, outBuffer);
89 // Serialize match extensions
90 ExtensionResolvers.getMatchExtensionResolver().getExtension(match).map(extensions -> {
91 if (Objects.nonNull(extensions)) {
92 extensions.getExtensionList().forEach(extension -> {
93 // TODO: Remove also extension converters
94 final MatchEntry entry = OFSessionUtil
95 .getExtensionConvertorProvider()
96 .<MatchEntry>getConverter(new ConverterExtensionKey<>(
97 extension.getExtensionKey(),
98 OFConstants.OFP_VERSION_1_3))
99 .convert(extension.getExtension());
101 final MatchEntrySerializerKey<?, ?> key = new MatchEntrySerializerKey<>(
102 EncodeConstants.OF13_VERSION_ID, entry.getOxmClass(), entry.getOxmMatchField());
104 // If entry is experimenter, set experimenter ID to key
105 if (entry.getOxmClass().equals(ExperimenterClass.class)) {
106 key.setExperimenterId(ExperimenterIdCase.class.cast(entry.getMatchEntryValue())
107 .getExperimenter().getExperimenter().getValue());
110 final OFSerializer<MatchEntry> entrySerializer = registry.getSerializer(key);
111 entrySerializer.serialize(entry, outBuffer);
120 public void injectSerializerRegistry(SerializerRegistry serializerRegistry) {
121 registry = serializerRegistry;
125 public void registerEntrySerializer(org.opendaylight.openflowplugin.api.openflow.protocol.serialization.MatchEntrySerializerKey key, MatchEntrySerializer serializer) {
126 if (Objects.isNull(key) || Objects.isNull(serializer)) {
127 throw new IllegalArgumentException("MatchEntrySerializerKey or Serializer is null");
130 final MatchEntrySerializer seInRegistry = entryRegistry.put(key, serializer);
131 if (seInRegistry != null) {
132 LOG.debug("Serializer for key {} overwritten. Old serializer: {}, new serializer: {}", key,
133 seInRegistry.getClass().getName(), serializer.getClass().getName());
138 public boolean unregisterEntrySerializer(org.opendaylight.openflowplugin.api.openflow.protocol.serialization.MatchEntrySerializerKey key) {
139 return Objects.nonNull(entryRegistry.remove(key));