/* * Copyright (c) 2013 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.openflowjava.protocol.impl.util; import io.netty.buffer.ByteBuf; import java.util.List; import org.opendaylight.openflowjava.protocol.api.extensibility.OFSerializer; import org.opendaylight.openflowjava.protocol.api.extensibility.SerializerRegistry; import org.opendaylight.openflowjava.protocol.api.extensibility.SerializerRegistryInjector; import org.opendaylight.openflowjava.protocol.api.keys.MatchEntrySerializerKey; import org.opendaylight.openflowjava.protocol.api.util.EncodeConstants; import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev150225.oxm.container.match.entry.value.ExperimenterIdCase; import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.StandardMatchType; import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.ExperimenterClass; import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.OxmMatchType; import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entries.grouping.MatchEntry; import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.grouping.Match; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Serializes ofp_match (OpenFlow v1.3) * @author michal.polkorab * @author timotej.kubas */ public class OF13MatchSerializer implements OFSerializer<Match>, SerializerRegistryInjector { private static final Logger LOG = LoggerFactory.getLogger(OF13MatchSerializer.class); private static final byte STANDARD_MATCH_TYPE_CODE = 0; private static final byte OXM_MATCH_TYPE_CODE = 1; private SerializerRegistry registry; @Override public void serialize(Match match, ByteBuf outBuffer) { if (match == null) { LOG.debug("Match is null"); return; } int matchStartIndex = outBuffer.writerIndex(); serializeType(match, outBuffer); int matchLengthIndex = outBuffer.writerIndex(); outBuffer.writeShort(EncodeConstants.EMPTY_LENGTH); serializeMatchEntries(match.getMatchEntry(), outBuffer); // Length of ofp_match (excluding padding) int matchLength = outBuffer.writerIndex() - matchStartIndex; outBuffer.setShort(matchLengthIndex, matchLength); int paddingRemainder = matchLength % EncodeConstants.PADDING; if (paddingRemainder != 0) { outBuffer.writeZero(EncodeConstants.PADDING - paddingRemainder); } } private static void serializeType(Match match, ByteBuf out) { if (match.getType().isAssignableFrom(StandardMatchType.class)) { out.writeShort(STANDARD_MATCH_TYPE_CODE); } else if (match.getType().isAssignableFrom(OxmMatchType.class)) { out.writeShort(OXM_MATCH_TYPE_CODE); } } /** * Serializes MatchEntries * @param matchEntries list of match entries (oxm_fields) * @param out output ByteBuf */ public void serializeMatchEntries(List<MatchEntry> matchEntries, ByteBuf out) { if (matchEntries == null) { LOG.debug("Match entries are null"); return; } for (MatchEntry entry : matchEntries) { MatchEntrySerializerKey<?, ?> key = new MatchEntrySerializerKey<>( EncodeConstants.OF13_VERSION_ID, entry.getOxmClass(), entry.getOxmMatchField()); if (entry.getOxmClass().equals(ExperimenterClass.class)) { ExperimenterIdCase entryValue = (ExperimenterIdCase) entry.getMatchEntryValue(); key.setExperimenterId(entryValue.getExperimenter().getExperimenter().getValue()); } else { key.setExperimenterId(null); } OFSerializer<MatchEntry> entrySerializer = registry.getSerializer(key); entrySerializer.serialize(entry, out); } } @Override public void injectSerializerRegistry(SerializerRegistry serializerRegistry) { this.registry = serializerRegistry; } }