/** * Copyright 2012, Big Switch Networks, Inc. * * 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 net.floodlightcontroller.packet; import java.nio.ByteBuffer; import java.util.HashMap; import java.util.Map; /** * @author Shudong Zhou (shudong.zhou@bigswitch.com) * */ public class BSN extends BasePacket { public static final int BSN_MAGIC = 0x20000604; public static final short BSN_VERSION_CURRENT = 0x0; public static final short BSN_TYPE_PROBE = 0x1; public static final short BSN_TYPE_BDDP = 0x2; public static Map<Short, Class<? extends IPacket>> typeClassMap; static { typeClassMap = new HashMap<Short, Class<? extends IPacket>>(); typeClassMap.put(BSN_TYPE_PROBE, BSNPROBE.class); typeClassMap.put(BSN_TYPE_BDDP, LLDP.class); } protected short type; protected short version; public BSN() { version = BSN_VERSION_CURRENT; } public BSN(short type) { this.type = type; version = BSN_VERSION_CURRENT; } public short getType() { return type; } public BSN setType(short type) { this.type = type; return this; } public short getVersion() { return version; } public BSN setVersion(short version) { this.version = version; return this; } @Override public byte[] serialize() { short length = 4 /* magic */ + 2 /* type */ + 2 /* version */; byte[] payloadData = null; if (this.payload != null) { payload.setParent(this); payloadData = payload.serialize(); length += payloadData.length; } byte[] data = new byte[length]; ByteBuffer bb = ByteBuffer.wrap(data); bb.putInt(BSN_MAGIC); bb.putShort(this.type); bb.putShort(this.version); if (payloadData != null) bb.put(payloadData); if (this.parent != null && this.parent instanceof Ethernet) ((Ethernet)this.parent).setEtherType(Ethernet.TYPE_BSN); return data; } @Override public IPacket deserialize(byte[] data, int offset, int length) throws PacketParsingException { ByteBuffer bb = ByteBuffer.wrap(data, offset, length); int magic = bb.getInt(); if (magic != BSN_MAGIC) { throw new PacketParsingException("Invalid BSN magic " + magic); } this.type = bb.getShort(); this.version = bb.getShort(); if (this.version != BSN_VERSION_CURRENT) { throw new PacketParsingException( "Invalid BSN packet version " + this.version + ", should be " + BSN_VERSION_CURRENT); } IPacket payload; if (typeClassMap.containsKey(this.type)) { Class<? extends IPacket> clazz = typeClassMap.get(this.type); try { payload = clazz.newInstance(); } catch (Exception e) { throw new RuntimeException("Error parsing payload for BSN packet" + e); } } else { payload = new Data(); } this.payload = payload.deserialize(data, bb.position(), bb.limit() - bb.position()); this.payload.setParent(this); return this; } /* (non-Javadoc) * @see java.lang.Object#hashCode() */ @Override public int hashCode() { final int prime = 883; int result = super.hashCode(); result = prime * result + version; result = prime * result + type; return result; } /* (non-Javadoc) * @see java.lang.Object#equals(java.lang.Object) */ @Override public boolean equals(Object obj) { if (this == obj) return true; if (!super.equals(obj)) return false; if (!(obj instanceof BSN)) return false; BSN other = (BSN) obj; return (type == other.type && version == other.version); } public String toString() { StringBuffer sb = new StringBuffer("\n"); sb.append("BSN packet"); if (typeClassMap.containsKey(this.type)) sb.append(" type: " + typeClassMap.get(this.type).getCanonicalName()); else sb.append(" type: " + this.type); return sb.toString(); } }