/* * Copyright (c) 2017 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.multipart; import io.netty.buffer.ByteBuf; import java.math.BigInteger; import java.util.ArrayList; import java.util.List; import org.opendaylight.openflowjava.protocol.api.extensibility.DeserializerRegistry; import org.opendaylight.openflowjava.protocol.api.extensibility.DeserializerRegistryInjector; import org.opendaylight.openflowjava.protocol.api.extensibility.OFDeserializer; import org.opendaylight.openflowjava.protocol.api.keys.MessageCodeKey; import org.opendaylight.openflowjava.protocol.api.util.EncodeConstants; import org.opendaylight.openflowplugin.api.OFConstants; import org.opendaylight.openflowplugin.extension.api.path.MatchPath; import org.opendaylight.openflowplugin.impl.protocol.deserialization.key.MessageCodeMatchKey; import org.opendaylight.openflowplugin.impl.protocol.deserialization.util.InstructionUtil; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Counter32; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Counter64; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.flow.and.statistics.map.list.FlowAndStatisticsMapList; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.flow.and.statistics.map.list.FlowAndStatisticsMapListBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.multipart.reply.multipart.reply.body.MultipartReplyFlowStatsBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.FlowCookie; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.FlowModFlags; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.InstructionsBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionKey; import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.Match; import org.opendaylight.yang.gen.v1.urn.opendaylight.model.statistics.types.rev130925.duration.DurationBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.multipart.types.rev170112.multipart.reply.MultipartReplyBody; public class MultipartReplyFlowStatsDeserializer implements OFDeserializer<MultipartReplyBody>, DeserializerRegistryInjector { private static final MessageCodeKey MATCH_KEY = new MessageCodeMatchKey(EncodeConstants.OF13_VERSION_ID, EncodeConstants.EMPTY_VALUE, Match.class, MatchPath.FLOWSSTATISTICSUPDATE_FLOWANDSTATISTICSMAPLIST_MATCH); private static final byte PADDING_IN_FLOW_STATS_HEADER_01 = 1; private static final byte PADDING_IN_FLOW_STATS_HEADER_02 = 4; private DeserializerRegistry registry; @Override public MultipartReplyBody deserialize(ByteBuf message) { final MultipartReplyFlowStatsBuilder builder = new MultipartReplyFlowStatsBuilder(); final List<FlowAndStatisticsMapList> items = new ArrayList<>(); while (message.readableBytes() > 0) { final FlowAndStatisticsMapListBuilder itemBuilder = new FlowAndStatisticsMapListBuilder(); final int itemLength = message.readUnsignedShort(); final ByteBuf itemMessage = message.readSlice(itemLength - EncodeConstants.SIZE_OF_SHORT_IN_BYTES); itemBuilder.setTableId(itemMessage.readUnsignedByte()); itemMessage.skipBytes(PADDING_IN_FLOW_STATS_HEADER_01); itemBuilder .setDuration(new DurationBuilder() .setSecond(new Counter32(itemMessage.readUnsignedInt())) .setNanosecond(new Counter32(itemMessage.readUnsignedInt())) .build()) .setPriority(itemMessage.readUnsignedShort()) .setIdleTimeout(itemMessage.readUnsignedShort()) .setHardTimeout(itemMessage.readUnsignedShort()) .setFlags(createFlowModFlagsFromBitmap(itemMessage.readUnsignedShort())); itemMessage.skipBytes(PADDING_IN_FLOW_STATS_HEADER_02); final byte[] cookie = new byte[EncodeConstants.SIZE_OF_LONG_IN_BYTES]; itemMessage.readBytes(cookie); final byte[] packetCount = new byte[EncodeConstants.SIZE_OF_LONG_IN_BYTES]; itemMessage.readBytes(packetCount); final byte[] byteCount = new byte[EncodeConstants.SIZE_OF_LONG_IN_BYTES]; itemMessage.readBytes(byteCount); itemBuilder .setCookie(new FlowCookie(new BigInteger(1, cookie))) .setCookieMask(new FlowCookie(OFConstants.DEFAULT_COOKIE_MASK)) .setPacketCount(new Counter64(new BigInteger(1, packetCount))) .setByteCount(new Counter64(new BigInteger(1, byteCount))); final OFDeserializer<Match> matchDeserializer = registry.getDeserializer(MATCH_KEY); itemBuilder.setMatch(new MatchBuilder(matchDeserializer.deserialize(itemMessage)).build()); final int length = itemMessage.readableBytes(); if (length > 0) { final List<org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list .Instruction> instructions = new ArrayList<>(); final int startIndex = itemMessage.readerIndex(); int offset = 0; while ((itemMessage.readerIndex() - startIndex) < length) { instructions.add(new InstructionBuilder() .setKey(new InstructionKey(offset)) .setOrder(offset) .setInstruction(InstructionUtil .readInstruction(EncodeConstants.OF13_VERSION_ID, itemMessage, registry)) .build()); offset++; } itemBuilder.setInstructions(new InstructionsBuilder() .setInstruction(instructions) .build()); } items.add(itemBuilder.build()); } return builder .setFlowAndStatisticsMapList(items) .build(); } private static FlowModFlags createFlowModFlagsFromBitmap(int input) { final Boolean _oFPFFSENDFLOWREM = (input & (1)) > 0; final Boolean _oFPFFCHECKOVERLAP = (input & (1 << 1)) > 0; final Boolean _oFPFFRESETCOUNTS = (input & (1 << 2)) > 0; final Boolean _oFPFFNOPKTCOUNTS = (input & (1 << 3)) > 0; final Boolean _oFPFFNOBYTCOUNTS = (input & (1 << 4)) > 0; return new FlowModFlags(_oFPFFCHECKOVERLAP, _oFPFFNOBYTCOUNTS, _oFPFFNOPKTCOUNTS, _oFPFFRESETCOUNTS, _oFPFFSENDFLOWREM); } @Override public void injectDeserializerRegistry(DeserializerRegistry deserializerRegistry) { registry = deserializerRegistry; } }