/*
- * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ * Copyright (c) 2013-2014 Cisco Systems, Inc. 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,
import org.apache.commons.lang3.tuple.ImmutablePair;
import org.apache.commons.lang3.tuple.Pair;
+import org.opendaylight.controller.sal.match.Match;
+import org.opendaylight.controller.sal.match.MatchType;
import org.opendaylight.controller.sal.utils.IPProtocols;
import org.opendaylight.controller.sal.utils.NetUtils;
import org.slf4j.Logger;
private static final String DIP = "DestinationIPAddress";
private static final String OPTIONS = "Options";
+ private static final int UNIT_SIZE_SHIFT = 2;
+ private static final int UNIT_SIZE = (1 << UNIT_SIZE_SHIFT);
+ private static final int MIN_HEADER_SIZE = 20;
+
public static final Map<Byte, Class<? extends Packet>> protocolClassMap;
static {
protocolClassMap = new HashMap<Byte, Class<? extends Packet>>();
public int getHeaderSize() {
int headerLen = this.getHeaderLen();
if (headerLen == 0) {
- headerLen = 20;
- }
-
- byte[] options = hdrFieldsMap.get(OPTIONS);
- if (options != null) {
- headerLen += options.length;
+ headerLen = MIN_HEADER_SIZE;
}
return headerLen * NetUtils.NumBitsInAByte;
*/
public void setHeaderField(String headerField, byte[] readValue) {
if (headerField.equals(PROTOCOL)) {
- payloadClass = protocolClassMap.get(readValue[0]);
+ // Don't set payloadClass if framgment offset is not zero.
+ byte[] fragoff = hdrFieldsMap.get(FRAGOFFSET);
+ if (fragoff == null || BitBufferHelper.getShort(fragoff) == 0) {
+ payloadClass = protocolClassMap.get(readValue[0]);
+ }
+ } else if (headerField.equals(FRAGOFFSET)) {
+ if (readValue != null && BitBufferHelper.getShort(readValue) != 0) {
+ // Clear payloadClass because protocol header is not present
+ // in this packet.
+ payloadClass = null;
+ }
+ } else if (headerField.equals(OPTIONS) &&
+ (readValue == null || readValue.length == 0)) {
+ hdrFieldsMap.remove(headerField);
+ return;
}
hdrFieldsMap.put(headerField, readValue);
}
}
/**
- * Stores the length of IP header in words (2 bytes)
+ * Stores the length of IP header in words (4 bytes)
* @param headerLength the headerLength to set
* @return IPv4
*/
* @return IPv4
*/
public IPv4 setOptions(byte[] options) {
- fieldValues.put(OPTIONS, options);
- byte newIHL = (byte) (5 + options.length);
+ byte newIHL = (byte)(MIN_HEADER_SIZE >>> UNIT_SIZE_SHIFT);
+ if (options == null || options.length == 0) {
+ fieldValues.remove(OPTIONS);
+ } else {
+ int len = options.length;
+ int rlen = (len + (UNIT_SIZE - 1)) & ~(UNIT_SIZE - 1);
+ if (rlen > len) {
+ // Padding is required.
+ byte[] newopt = new byte[rlen];
+ System.arraycopy(options, 0, newopt, 0, len);
+ options = newopt;
+ len = rlen;
+ }
+ fieldValues.put(OPTIONS, options);
+ newIHL += (len >>> UNIT_SIZE_SHIFT);
+ }
+
setHeaderLength(newIHL);
return this;
@Override
/**
* Gets the number of bits for the fieldname specified
- * If the fieldname has variable length like "Options", then this value is computed using the
- * options length and the header length
+ * If the fieldname has variable length like "Options", then this value is computed using the header length
* @param fieldname - String
* @return number of bits for fieldname - int
*/
public int getfieldnumBits(String fieldName) {
if (fieldName.equals(OPTIONS)) {
- byte[] options = getOptions();
- return ((options == null) ? 0 : (options.length - getHeaderLen()));
+ return (getHeaderLen() - MIN_HEADER_SIZE) * NetUtils.NumBitsInAByte;
}
return hdrFieldCoordMap.get(fieldName).getRight();
}
corrupted = true;
}
}
+
+ @Override
+ public void populateMatch(Match match) {
+ match.setField(MatchType.NW_SRC, NetUtils.getInetAddress(this.getSourceAddress()));
+ match.setField(MatchType.NW_DST, NetUtils.getInetAddress(this.getDestinationAddress()));
+ match.setField(MatchType.NW_PROTO, this.getProtocol());
+ match.setField(MatchType.NW_TOS, this.getDiffServ());
+ }
}