/* * Copyright 2017-present Open Networking Laboratory * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.onosproject.routing.fpm.protocol; import com.google.common.base.MoreObjects; import com.google.common.collect.ImmutableList; import org.onlab.packet.DeserializationException; import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.List; import static org.onlab.packet.PacketUtils.checkInput; /** * Netlink routing message (rtnetlink). * <p> * Taken from struct rtmsg in linux/rtnetlink.h * </p> */ public final class RtNetlink { private static final int RT_NETLINK_LENGTH = 12; private static final int MASK = 0xff; private final short addressFamily; private final int dstLength; private final int srcLength; private final short tos; private final short table; private final RtProtocol protocol; private final short scope; private final short type; private final long flags; private final List<RouteAttribute> attributes; /** * Class constructor. * * @param addressFamily address family * @param dstLength destination address length * @param srcLength source address length * @param tos type of service * @param table routing table * @param protocol protocol * @param scope scope * @param type type * @param flags flags * @param attributes list of attributes */ private RtNetlink(short addressFamily, int dstLength, int srcLength, short tos, short table, RtProtocol protocol, short scope, short type, long flags, List<RouteAttribute> attributes) { this.addressFamily = addressFamily; this.dstLength = dstLength; this.srcLength = srcLength; this.tos = tos; this.table = table; this.protocol = protocol; this.scope = scope; this.type = type; this.flags = flags; this.attributes = ImmutableList.copyOf(attributes); } /** * Returns the address family of the route. * * @return address family */ public short addressFamily() { return addressFamily; } /** * Returns the destination address length. * * @return destination address length */ public int dstLength() { return dstLength; } /** * Returns the source address length. * * @return source address length */ public int srcLength() { return srcLength; } /** * Returns the type of service. * * @return type of service */ public short tos() { return tos; } /** * Returns the routing table. * * @return routing table */ public short table() { return table; } /** * Returns the protocol. * * @return protocol */ public RtProtocol protocol() { return protocol; } /** * Returns the route scope. * * @return scope */ public short scope() { return scope; } /** * Returns the route type. * * @return route type */ public short type() { return type; } /** * Returns the route flags. * * @return route flags */ public long flags() { return flags; } /** * Returns the list of route attributes. * * @return route attributes */ public List<RouteAttribute> attributes() { return attributes; } @Override public String toString() { return MoreObjects.toStringHelper(getClass()) .add("addressFamily", addressFamily) .add("dstLength", dstLength) .add("srcLength", srcLength) .add("tos", tos) .add("table", table) .add("protocol", protocol) .add("scope", scope) .add("type", type) .add("flags", flags) .add("attributes", attributes) .toString(); } /** * Decodes an rtnetlink message from an input buffer. * * @param buffer input buffer * @param start starting position the rtnetlink message * @param length length of the message * @return rtnetlink message * @throws DeserializationException if an rtnetlink message could not be * decoded from the input buffer */ public static RtNetlink decode(byte[] buffer, int start, int length) throws DeserializationException { checkInput(buffer, start, length, RT_NETLINK_LENGTH); ByteBuffer bb = ByteBuffer.wrap(buffer, start, length); short addressFamily = (short) (bb.get() & MASK); int dstLength = bb.get() & MASK; int srcLength = bb.get() & MASK; short tos = (short) (bb.get() & MASK); short table = (short) (bb.get() & MASK); short protocol = (short) (bb.get() & MASK); short scope = (short) (bb.get() & MASK); short type = (short) (bb.get() & MASK); long flags = Integer.reverseBytes(bb.getInt()); List<RouteAttribute> attributes = new ArrayList<>(); RtProtocol rtProtocol = RtProtocol.get(protocol); while (bb.hasRemaining()) { RouteAttribute attribute = RouteAttribute.decode(buffer, bb.position(), bb.limit() - bb.position()); attributes.add(attribute); bb.position(bb.position() + attribute.length()); } return new RtNetlink( addressFamily, dstLength, srcLength, tos, table, rtProtocol, scope, type, flags, attributes); } }