/* * Copyright (c) 2012,2013 Big Switch Networks, Inc. * * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html * * 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.sdnplatform.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) { ByteBuffer bb = ByteBuffer.wrap(data, offset, length); int magic = bb.getInt(); if (magic != BSN_MAGIC) { throw new RuntimeException("Invalid BSN magic " + magic); } this.type = bb.getShort(); this.version = bb.getShort(); if (this.version != BSN_VERSION_CURRENT) { throw new RuntimeException( "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 = 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(); } }