/*
* Copyright (c) Martin Schoeberl, martin@jopdesign.com
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by Martin Schoeberl
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*/
package jembench.ejip;
public class Ip {
public final static int CHKSUM = 2;
public final static int SOURCE = 3;
public final static int DESTINATION = 4;
// TODO: this should not be static and it should be a synch. access
static int ip_id = 0x12340000;
Ejip ejip;
public Ip(Ejip ejipRef) {
ejip = ejipRef;
}
/**
* Very simple generation of IP header. Just swap source and destination.
* Still used by ICMP and TCP.
*/
void doIp(Packet p, int prot) {
int[] buf = p.buf;
int len = p.len;
int i;
if (len == 0) {
ejip.returnPacket(p); // mark packet free
} else {
buf[0] = 0x45000000 + len; // ip length (header without options)
buf[1] = Ip.getId(); // identification, no fragmentation
buf[2] = (0x20 << 24) + (prot << 16); // ttl, protocol, clear
// checksum
i = buf[3]; // swap ip addresses
buf[3] = buf[4];
buf[4] = i;
buf[2] |= Ip.chkSum(buf, 0, 20);
p.llh[6] = 0x0800;
// send packet to the link layer for the packet
p.interf.txQueue.enq(p);
}
}
/**
* return IP id in upper 16 bit.
*/
public static int getId() {
Ip.ip_id += 0x10000;
return Ip.ip_id;
}
/**
* calc IP check sum. assume (32 bit) word boundaries. rest of buffer is 0.
* off offset in buffer (in words) cnt length in bytes
*/
public static int chkSum(int[] buf, int off, int cnt) {
int i;
int sum = 0;
int max = buf.length;
cnt = (cnt + 3) >> 2; // word count
// add max condition for DFA loop bound analysis
for (int j=0; j<cnt && j<max; ++j) {
i = buf[off];
sum += i & 0xffff;
sum += i >>> 16;
++off;
}
// that's the original ejip code
// while (cnt != 0) {
// i = buf[off];
// sum += i & 0xffff;
// sum += i >>> 16;
// ++off;
// --cnt;
// }
while ((sum >> 16) != 0) // @WCA loop<=2
sum = (sum & 0xffff) + (sum >> 16);
sum = (~sum) & 0xffff;
return sum;
}
/**
* Copy packet data into a StringBuffer
* @param p packet
* @param off offset in 32-bit words
* @param s StringBuffer destination
*/
public static void getData(Packet p, int off, StringBuffer s) {
int[] buf = p.buf;
int len = p.len;
s.setLength(0);
for (int i = off<<2; i < len; i++) {
s.append((char) ((buf[i>>2]>>(24 - ((i&3)<<3))) & 0xff));
}
}
/**
* Set data from StringBuffer into the packet
* @param p packet
* @param off offset in 32-bit words
* @param s StringBuffer source
*/
public static void setData(Packet p, int off, StringBuffer s) {
int[] buf = p.buf;
int cnt = s.length();
// copy buffer
int k = 0;
for (int i=0; i<cnt; i+=4) {
for (int j=0; j<4; ++j) {
k <<= 8;
if (i+j < cnt) k += s.charAt(i+j);
}
buf[off + (i>>>2)] = k;
}
p.len = (off<<2)+cnt;
}
/**
* Set data from StringBuffer into the packet
* @param p packet
* @param off offset in 32-bit words
* @param s StringBuffer source
* @param start offset into s
* @return offset up to which the data has been written
*/
public static int setData(Packet p, int off, StringBuffer s, int start) {
int[] buf = p.buf;
int cnt = s.length()-start;
if (cnt > ((buf.length-off)<<2)) {
cnt = (buf.length-off)<<2;
}
// copy buffer
int k = 0;
for (int i=0; i<cnt; i+=4) {
for (int j=0; j<4; ++j) {
k <<= 8;
if (i+j < cnt) k += s.charAt(start+i+j);
}
buf[off + (i>>>2)] = k;
}
p.len = (off<<2)+cnt;
return cnt+start;
}
/**
* Set data from String into the packet
* @param p packet
* @param off offset in 32-bit words
* @param s String source
*/
public static void setData(Packet p, int off, String s) {
int[] buf = p.buf;
int cnt = s.length();
// copy buffer
int k = 0;
for (int i=0; i<cnt; i+=4) {
for (int j=0; j<4; ++j) {
k <<= 8;
if (i+j < cnt) k += s.charAt(i+j);
}
buf[off + (i>>>2)] = k;
}
p.len = (off<<2)+cnt;
}
/**
* Set data from byte array into the packet
* @param p packet
* @param off offset in 32-bit words
* @param b byte array
*/
public static void setData(Packet p, int off, byte[] b) {
setData(p, off, b, b.length);
}
/**
* Set data from byte array into the packet
* @param p packet
* @param off offset in 32-bit words
* @param b byte array
* @param cnt length of payload data
*/
public static void setData(Packet p, int off, byte[] b, int cnt) {
int[] buf = p.buf;
// copy buffer
int k = 0;
for (int i=0; i<cnt; i+=4) {
for (int j=0; j<4; ++j) {
k <<= 8;
if (i+j < cnt) k += (int)b[i+j] & 0xff;
}
buf[off + (i>>>2)] = k;
}
p.len = (off<<2)+cnt;
}
}