com.github.sdnwiselab.sdnwise.node.Node Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of sdn-wise-node Show documentation
Show all versions of sdn-wise-node Show documentation
SDN-WISE Node: An emulated SDN-WISE Java Node
/*
* Copyright (C) 2015 SDN-WISE
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
package com.github.sdnwiselab.sdnwise.node;
import com.github.sdnwiselab.sdnwise.flowtable.*;
import static com.github.sdnwiselab.sdnwise.flowtable.SetAction.*;
import static com.github.sdnwiselab.sdnwise.flowtable.Stats.SDN_WISE_RL_TTL_PERMANENT;
import static com.github.sdnwiselab.sdnwise.flowtable.Window.*;
import com.github.sdnwiselab.sdnwise.function.FunctionInterface;
import static com.github.sdnwiselab.sdnwise.node.Constants.*;
import com.github.sdnwiselab.sdnwise.packet.*;
import static com.github.sdnwiselab.sdnwise.packet.ConfigAcceptedIdPacket.*;
import static com.github.sdnwiselab.sdnwise.packet.ConfigFunctionPacket.*;
import static com.github.sdnwiselab.sdnwise.packet.ConfigNodePacket.*;
import static com.github.sdnwiselab.sdnwise.packet.ConfigRulePacket.*;
import static com.github.sdnwiselab.sdnwise.packet.ConfigTimerPacket.*;
import static com.github.sdnwiselab.sdnwise.packet.NetworkPacket.*;
import com.github.sdnwiselab.sdnwise.util.*;
import java.io.*;
import java.net.*;
import java.nio.file.*;
import java.util.*;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.logging.*;
/**
*
* @author Sebastiano Milardo
*/
public abstract class Node implements Runnable {
private static final Logger LOGGER = Logger.getLogger(Node.class.getName());
/**
* @param args the command line arguments
*/
private int sentBytes;
private int receivedBytes;
private int distanceFromSink;
private int rssiSink;
private final byte[] buf;
final ArrayBlockingQueue flowTableQueue;
final ArrayBlockingQueue txQueue;
int port,
semaphore,
flow_table_free_pos,
accepted_id_free_pos,
neighbors_number,
net_id,
cnt_beacon_max,
cnt_report_max,
cnt_updtable_max,
cnt_sleep_max,
ttl_max,
rssi_min;
NodeAddress addr;
DatagramSocket socket;
String neighborFilePath;
String logFilePath;
Battery battery;
ArrayList neighborTable;
ArrayList flowTable;
ArrayList acceptedId;
HashMap adcRegister = new HashMap<>();
HashMap> functionBuffer = new HashMap<>();
HashMap functions = new HashMap<>();
HashMap neighbourList;
public ArrayList statusRegister = new ArrayList<>();
public Node(NodeAddress addr, byte net_id, int port, String neighborFilePath, String log, String level) {
buf = new byte[NetworkPacket.SDN_WISE_MAX_LEN];
logFilePath = log;
neighborTable = new ArrayList<>(SDN_WISE_NEIGHBORS_MAX);
acceptedId = new ArrayList<>(SDN_WISE_ACCEPTED_ID_MAX);
flowTable = new ArrayList<>(0);
flowTableQueue = new ArrayBlockingQueue<>(1024);
txQueue = new ArrayBlockingQueue<>(1024);
this.addr = addr;
this.net_id = net_id;
this.neighborFilePath = neighborFilePath;
this.neighbourList = new HashMap<>();
this.port = port;
LOGGER.setLevel(Level.parse(level));
FileHandler fh;
try {
fh = new FileHandler(addr + ".log");
fh.setFormatter(new SimpleFormatter());
LOGGER.addHandler(fh);
LOGGER.setUseParentHandlers(false);
} catch (IOException | SecurityException ex) {
LOGGER.log(Level.SEVERE, null, ex);
}
setup();
}
public final void setNum_hop_vs_sink(int num_hop_vs_sink) {
this.distanceFromSink = num_hop_vs_sink;
}
public final void setRssi_vs_sink(int rssi_vs_sink) {
this.rssiSink = rssi_vs_sink;
}
public final void setSemaphore(int semaforo) {
this.semaphore = semaforo;
}
public final int getNum_hop_vs_sink() {
return distanceFromSink;
}
public final int getRssi_vs_sink() {
return rssiSink;
}
public final int getSemaphore() {
return semaphore;
}
public void initSdnWise() {
cnt_beacon_max = SDN_WISE_DFLT_CNT_BEACON_MAX;
cnt_report_max = SDN_WISE_DFLT_CNT_REPORT_MAX;
cnt_updtable_max = SDN_WISE_DFLT_CNT_UPDTABLE_MAX;
rssi_min = SDN_WISE_DFLT_RSSI_MIN;
ttl_max = SDN_WISE_DFLT_TTL_MAX;
battery = new Battery();
flow_table_free_pos = 1;
accepted_id_free_pos = 0;
InputStream is;
try {
is = new FileInputStream(neighborFilePath);
} catch (FileNotFoundException ex) {
LOGGER.log(Level.INFO, "External Config file not found, using embedded one {0}", neighborFilePath);
is = this.getClass().getResourceAsStream("/" + neighborFilePath);
}
try (BufferedReader br = new BufferedReader(new InputStreamReader(is, "UTF-8"))) {
String line;
while ((line = br.readLine()) != null) {
String[] tmp = line.split(",");
if (tmp.length == 4) {
neighbourList.put(new NodeAddress(tmp[0]), new FakeInfo(
new InetSocketAddress(tmp[1],
Integer.parseInt(tmp[2])),
Integer.parseInt(tmp[3]))
);
}
}
} catch (IOException ex) {
LOGGER.log(Level.SEVERE, null, ex);
}
}
public void initFlowTable() {
for (int i = 0; i < SDN_WISE_RLS_MAX; i++) {
flowTable.add(i, new FlowTableEntry());
}
flowTable.get(0).addWindow(new Window()
.setOperator(SDN_WISE_EQUAL)
.setSize(SDN_WISE_SIZE_2)
.setLhsLocation(SDN_WISE_PACKET)
.setLhs(SDN_WISE_DST_H)
.setRhsLocation(SDN_WISE_CONST)
.setRhs(0));
flowTable.get(0).addWindow(Window.fromString("P.TYPE != 0"));
flowTable.get(0).addAction(ActionBuilder.build("FORWARD_U 0"));
flowTable.get(0).setStats(new Stats());
}
public final void rxReport(ReportPacket packet) {
controllerTX(packet);
}
@Override
public final void run() {
try {
DatagramPacket packet = new DatagramPacket(buf, buf.length);
socket = new DatagramSocket(port);
new Timer().schedule(new Task(), 1000, 1000);
// Enable for extensive logging
if (logFilePath != null) {
try {
Files.deleteIfExists(FileSystems.getDefault()
.getPath("", logFilePath));
} catch (IOException ex) {
// File permission problems are caught here.
LOGGER.log(Level.SEVERE, null, ex);
}
new Timer().schedule(new TaskLogger(), 1000, 1000);
}
new Thread(new PacketManager()).start();
new Thread(new PacketSender()).start();
while (true) {
socket.receive(packet);
NetworkPacket np = new NetworkPacket(packet.getData());
flowTableQueue.put(np);
}
} catch (IOException | InterruptedException ex) {
LOGGER.log(Level.SEVERE, null, ex);
}
}
public final void radioTX(NetworkPacket np, boolean sdn_wise_mac_send_unicast) {
sentBytes += np.getLen();
battery.transmitRadio(np.getLen());
np.decrementTtl();
LOGGER.log(Level.FINE,
"[{0}]: RTX {1}", new Object[]{addr.toString(), np});
NodeAddress tmpNxHop = np.getNxhop();
NodeAddress tmpDst = np.getDst();
if (tmpDst.isBroadcast()) {
for (FakeInfo isa : neighbourList.values()) {
DatagramPacket pck = new DatagramPacket(np.toByteArray(),
np.getLen(), isa.inetAddress);
try {
socket.send(pck);
} catch (IOException ex) {
LOGGER.log(Level.SEVERE, null, ex);
}
}
} else {
FakeInfo isa = neighbourList.get(tmpNxHop);
if (isa != null) {
try {
DatagramPacket pck = new DatagramPacket(np.toByteArray(),
np.getLen(), isa.inetAddress);
socket.send(pck);
} catch (IOException ex) {
LOGGER.log(Level.SEVERE, null, ex);
}
}
}
}
public final FunctionInterface createServiceInterface(byte[] classFile) {
CustomClassLoader cl = new CustomClassLoader();
FunctionInterface srvI = null;
Class service = cl.defClass(classFile, classFile.length);
try {
srvI = (FunctionInterface) service.newInstance();
} catch (InstantiationException | IllegalAccessException ex) {
LOGGER.log(Level.SEVERE, null, ex);
}
return srvI;
}
public final NodeAddress NxHopVsSink() {
return ((AbstractForwardAction) (flowTable.get(0).getActions().get(0))).getNextHop();
}
public final void rxData(DataPacket packet) {
if (isAcceptedIdPacket(packet)) {
SDN_WISE_Callback(packet);
} else if (isAcceptedIdAddress(packet.getNxhop())) {
runFlowMatch(packet);
}
}
public void rxBeacon(BeaconPacket bp, int rssi) {
int index = getNeighborIndex(bp.getSrc());
if (index != (SDN_WISE_NEIGHBORS_MAX + 1)) {
if (index != -1) {
neighborTable.get(index).setRssi(rssi);
neighborTable.get(index).setBatt(bp.getBatt());
} else {
neighborTable.get(neighbors_number).setAddr(bp.getSrc());
neighborTable.get(neighbors_number).setRssi(rssi);
neighborTable.get(neighbors_number).setBatt(bp.getBatt());
neighbors_number++;
}
}
}
public void rxResponse(ResponsePacket rp) {
if (isAcceptedIdPacket(rp)) {
rp.getRule().setStats(new Stats());
insertRule(rp.getRule(), searchRule(rp.getRule()));
} else {
runFlowMatch(rp);
}
}
public void rxOpenPath(OpenPathPacket opp) {
if (isAcceptedIdPacket(opp)) {
List path = opp.getPath();
for (int i = 0; i < path.size(); i++) {
NodeAddress actual = path.get(i);
if (isAcceptedIdAddress(actual)) {
if (i != 0) {
FlowTableEntry rule = new FlowTableEntry();
rule.addWindow(new Window()
.setOperator(SDN_WISE_EQUAL)
.setSize(SDN_WISE_SIZE_2)
.setLhsLocation(SDN_WISE_PACKET)
.setLhs(SDN_WISE_SRC_H)
.setRhsLocation(SDN_WISE_CONST)
.setRhs(path.get(path.size() - 1).intValue()));
rule.addWindow(new Window()
.setOperator(SDN_WISE_EQUAL)
.setSize(SDN_WISE_SIZE_2)
.setLhsLocation(SDN_WISE_PACKET)
.setLhs(SDN_WISE_DST_H)
.setRhsLocation(SDN_WISE_CONST)
.setRhs(this.getActualSinkAddress().intValue()));
rule.getWindows().addAll(opp.getOptionalWindows());
rule.addAction(new ForwardUnicastAction()
.setNextHop(path.get(i - 1))
);
int p = searchRule(rule);
insertRule(rule, p);
}
if (i != (path.size() - 1)) {
FlowTableEntry rule = new FlowTableEntry();
rule.addWindow(new Window()
.setOperator(SDN_WISE_EQUAL)
.setSize(SDN_WISE_SIZE_2)
.setLhsLocation(SDN_WISE_PACKET)
.setLhs(SDN_WISE_DST_H)
.setRhsLocation(SDN_WISE_CONST)
.setRhs(path.get(path.size() - 1).intValue()));
rule.addWindow(new Window()
.setOperator(SDN_WISE_EQUAL)
.setSize(SDN_WISE_SIZE_2)
.setLhsLocation(SDN_WISE_PACKET)
.setLhs(SDN_WISE_SRC_H)
.setRhsLocation(SDN_WISE_CONST)
.setRhs(this.getActualSinkAddress().intValue()));
rule.getWindows().addAll(opp.getOptionalWindows());
rule.addAction(new ForwardUnicastAction()
.setNextHop(path.get(i + 1))
);
int p = searchRule(rule);
insertRule(rule, p);
opp.setDst(path.get(i + 1));
opp.setNxhop(path.get(i + 1));
radioTX(opp, SDN_WISE_MAC_SEND_UNICAST);
break;
}
}
}
} else {
runFlowMatch(opp);
}
}
public final void runFlowMatch(NetworkPacket packet) {
int j, i, found = 0;
for (j = 0; j < SDN_WISE_RLS_MAX; j++) {
i = getActualFlowIndex(j);
if (matchRule(flowTable.get(i), packet) == 1) {
LOGGER.log(Level.INFO, "[{0}]: Matched Rule #{1} {2}",
new Object[]{addr, j, flowTable.get(i).toString()});
found = 1;
for (AbstractAction a : flowTable.get(i).getActions()) {
runAction(a, packet);
}
flowTable.get(i).getStats()
.setCounter(flowTable.get(i).getStats().getCounter() + 1);
break;
}
}
if (found == 0) { //!found
// It's necessary to send a rule/request if we have done the lookup
// I must modify the source address with myself,
packet.setSrc(addr)
.setRequestFlag()
.setTtl(SDN_WISE_DFLT_TTL_MAX);
controllerTX(packet);
}
}
public abstract void rxConfig(ConfigPacket packet);
public final void insertRule(FlowTableEntry rule, int pos) {
if (pos >= SDN_WISE_RLS_MAX) {
pos = flow_table_free_pos;
flow_table_free_pos++;
if (flow_table_free_pos >= SDN_WISE_RLS_MAX) {
flow_table_free_pos = 1;
}
}
LOGGER.log(Level.INFO, "[{0}]: Inserting rule {1} at position {2}",
new Object[]{addr, rule, pos});
flowTable.set(pos, rule);
}
public final int searchRule(FlowTableEntry rule) {
int i, j, sum, target;
for (i = 0; i < SDN_WISE_RLS_MAX; i++) {
sum = 0;
target = rule.getWindows().size();
if (flowTable.get(i).getWindows().size() == target) {
for (j = 0; j < rule.getWindows().size(); j++) {
if (flowTable.get(i).getWindows().get(j).equals(rule.getWindows().get(j))) {
sum++;
}
}
}
if (sum == target) {
return i;
}
}
return SDN_WISE_RLS_MAX + 1;
}
public final boolean isAcceptedIdAddress(NodeAddress addrP) {
return (addrP.equals(addr)
|| addrP.isBroadcast()
|| (searchAcceptedId(addrP)
!= SDN_WISE_ACCEPTED_ID_MAX + 1));
}
public final boolean isAcceptedIdPacket(NetworkPacket packet) {
return isAcceptedIdAddress(packet.getDst());
}
public final NodeAddress getActualAddress() {
return addr;
}
public final int getActualNetId() {
return net_id;
}
public NodeAddress getActualSinkAddress() {
return new NodeAddress(flowTable.get(0).getWindows().get(0).getRhs());
}
public abstract void SDN_WISE_Callback(DataPacket packet);
public abstract void controllerTX(NetworkPacket pck);
public int marshalPacket(ConfigPacket packet) {
int toBeSent = 0;
int pos;
boolean isWrite = packet.isWrite();
int id = packet.getConfigId();
int value = packet.getPayloadAt(1) * 256 + packet.getPayloadAt(2);
if (isWrite) {
switch (id) {
case SDN_WISE_CNF_ID_ADDR:
addr = new NodeAddress(value);
break;
case SDN_WISE_CNF_ID_NET_ID:
net_id = packet.getPayloadAt(2);
break;
case SDN_WISE_CNF_ID_CNT_BEACON_MAX:
cnt_beacon_max = value;
break;
case SDN_WISE_CNF_ID_CNT_REPORT_MAX:
cnt_report_max = value;
break;
case SDN_WISE_CNF_ID_CNT_UPDTABLE_MAX:
cnt_updtable_max = value;
break;
case SDN_WISE_CNF_ID_CNT_SLEEP_MAX:
cnt_sleep_max = value;
break;
case SDN_WISE_CNF_ID_TTL_MAX:
ttl_max = packet.getPayloadAt(2);
break;
case SDN_WISE_CNF_ID_RSSI_MIN:
rssi_min = packet.getPayloadAt(2);
break;
case SDN_WISE_CNF_ADD_ACCEPTED:
pos = searchAcceptedId(new NodeAddress(value));
if (pos == (SDN_WISE_ACCEPTED_ID_MAX + 1)) {
pos = searchAcceptedId(new NodeAddress(65535));
acceptedId.set(pos, new NodeAddress(value));
}
break;
case SDN_WISE_CNF_REMOVE_ACCEPTED:
pos = searchAcceptedId(new NodeAddress(value));
if (pos != (SDN_WISE_ACCEPTED_ID_MAX + 1)) {
acceptedId.set(pos, new NodeAddress(65535));
}
break;
case SDN_WISE_CNF_REMOVE_RULE_INDEX:
if (value != 0) {
flowTable.set(getActualFlowIndex(value), new FlowTableEntry());
}
break;
case SDN_WISE_CNF_REMOVE_RULE:
//TODO
break;
case SDN_WISE_CNF_ADD_FUNCTION:
if (functionBuffer.get(value) == null) {
functionBuffer.put(value, new LinkedList());
}
functionBuffer.get(value).add(Arrays.copyOfRange(
packet.toIntArray(), SDN_WISE_DFLT_HDR_LEN + 5,
packet.getLen()));
if (functionBuffer.get(value).size() == packet.getPayloadAt(4)) {
int total = 0;
for (int[] n : functionBuffer.get(value)) {
total += (n.length);
}
int pointer = 0;
byte[] func = new byte[total];
for (int[] n : functionBuffer.get(value)) {
for (int j = 0; j < n.length; j++) {
func[pointer] = (byte) n[j];
pointer++;
}
}
functions.put(value, createServiceInterface(func));
LOGGER.log(Level.INFO, "[{0}]: New Function Added - {1}",
new Object[]{addr.toString(), value});
functionBuffer.remove(value);
}
break;
case SDN_WISE_CNF_REMOVE_FUNCTION:
functions.remove(value);
break;
default:
break;
}
} else {
toBeSent = 1;
switch (id) {
case SDN_WISE_CNF_ID_ADDR:
packet.setPayloadAt(addr.getHigh(), 1);
packet.setPayloadAt(addr.getLow(), 2);
break;
case SDN_WISE_CNF_ID_NET_ID:
packet.setPayloadAt((byte) net_id, 2);
break;
case SDN_WISE_CNF_ID_CNT_BEACON_MAX:
packet.setPayloadAt((byte) (cnt_beacon_max >> 8), 1);
packet.setPayloadAt((byte) (cnt_beacon_max), 2);
break;
case SDN_WISE_CNF_ID_CNT_REPORT_MAX:
packet.setPayloadAt((byte) (cnt_report_max >> 8), 1);
packet.setPayloadAt((byte) (cnt_report_max), 2);
break;
case SDN_WISE_CNF_ID_CNT_UPDTABLE_MAX:
packet.setPayloadAt((byte) (cnt_updtable_max >> 8), 1);
packet.setPayloadAt((byte) (cnt_updtable_max), 2);
break;
case SDN_WISE_CNF_ID_CNT_SLEEP_MAX:
packet.setPayloadAt((byte) (cnt_sleep_max >> 8), 1);
packet.setPayloadAt((byte) (cnt_sleep_max), 2);
break;
case SDN_WISE_CNF_ID_TTL_MAX:
packet.setPayloadAt((byte) ttl_max, 2);
break;
case SDN_WISE_CNF_ID_RSSI_MIN:
packet.setPayloadAt((byte) rssi_min, 2);
break;
case SDN_WISE_CNF_LIST_ACCEPTED:
toBeSent = 0;
ConfigAcceptedIdPacket packetList
= new ConfigAcceptedIdPacket(
net_id,
packet.getDst(),
packet.getSrc());
packetList.setReadAcceptedAddressesValue();
int ii = 1;
for (int jj = 0; jj < SDN_WISE_ACCEPTED_ID_MAX; jj++) {
if (!acceptedId.get(jj).equals(new NodeAddress(65535))) {
packetList.setPayloadAt((acceptedId.get(jj)
.getHigh()), ii);
ii++;
packetList.setPayloadAt((acceptedId.get(jj)
.getLow()), ii);
ii++;
}
}
controllerTX(packetList);
break;
case SDN_WISE_CNF_GET_RULE_INDEX:
toBeSent = 0;
ConfigRulePacket packetRule = new ConfigRulePacket(
net_id,
packet.getDst(),
packet.getSrc()
);
int jj = getActualFlowIndex(value);
packetRule.setRule(flowTable.get(jj))
.setPayloadAt(SDN_WISE_CNF_GET_RULE_INDEX, 0)
.setPayloadAt(packet.getPayloadAt(1), 1)
.setPayloadAt(packet.getPayloadAt(2), 2);
controllerTX(packetRule);
break;
default:
break;
}
}
return toBeSent;
}
public void rxHandler(NetworkPacket packet, int rssi) throws InterruptedException {
LOGGER.log(Level.FINE, "[{0}]: RRX {1}",
new Object[]{addr.toString(), packet});
if (packet.getLen() > SDN_WISE_DFLT_HDR_LEN
&& packet.getNetId() == net_id
&& packet.getTtl() != 0) {
switch (packet.getType()) {
case SDN_WISE_DATA:
rxData(new DataPacket(packet));
break;
case SDN_WISE_BEACON:
rxBeacon(new BeaconPacket(packet), rssi);
break;
case SDN_WISE_REPORT:
rxReport(new ReportPacket(packet));
break;
case SDN_WISE_RESPONSE:
rxResponse(new ResponsePacket(packet));
break;
case SDN_WISE_OPEN_PATH:
rxOpenPath(new OpenPathPacket(packet));
break;
case SDN_WISE_CONFIG:
rxConfig(new ConfigPacket(packet));
break;
default:
runFlowMatch(packet);
break;
}
}
}
private void initNeighborTable() {
int i;
for (i = 0; i < SDN_WISE_NEIGHBORS_MAX; i++) {
neighborTable.add(i, new Neighbor());
}
neighbors_number = 0;
}
private void initStatusRegister() {
for (int i = 0; i < SDN_WISE_STATUS_LEN; i++) {
statusRegister.add(0);
}
}
private void initAcceptedId() {
for (int i = 0; i < SDN_WISE_ACCEPTED_ID_MAX; i++) {
acceptedId.add(i, new NodeAddress(65535));
}
}
private void setup() {
initSdnWise();
initFlowTable();
initNeighborTable();
initAcceptedId();
initStatusRegister();
}
private int getOperand(NetworkPacket packet, int size, int location, int value) {
int[] intPacket = packet.toIntArray();
switch (location) {
case SDN_WISE_NULL:
return 0;
case SDN_WISE_CONST:
return value;
case SDN_WISE_PACKET:
if (size == SDN_WISE_SIZE_1) {
if (value >= intPacket.length) {
LOGGER.log(Level.INFO, "{0} {1}", new Object[]{value, packet.toString()});
LOGGER.log(Level.WARNING, "Checking out of bounds");
return -1;
}
return intPacket[value];
}
if (size == SDN_WISE_SIZE_2) {
if (value + 1 >= intPacket.length) {
LOGGER.log(Level.INFO, "{0} {1}", new Object[]{value, packet.toString()});
LOGGER.log(Level.WARNING, "Checking out of bounds");
return -1;
}
return Utils.mergeBytes(intPacket[value], intPacket[value + 1]);
}
case SDN_WISE_STATUS:
if (size == SDN_WISE_SIZE_1) {
if (value >= statusRegister.size()) {
LOGGER.log(Level.INFO, "Checking status at position {0}", value);
LOGGER.log(Level.WARNING, "Checking out of bounds");
return -1;
}
return statusRegister.get(value);
}
if (size == SDN_WISE_SIZE_2) {
if (value + 1 >= statusRegister.size()) {
LOGGER.log(Level.INFO, "Checking out of bounds");
LOGGER.log(Level.WARNING, "Checking out of bounds");
return -1;
}
return Utils.mergeBytes(
statusRegister.get(value),
statusRegister.get(value + 1));
}
}
return -1;
}
// Verifica che una condizione di una finestra di una regola è soddisfatta
private int matchWindow(Window window, NetworkPacket packet) {
int operator = window.getOperator();
int size = window.getSize();
int lhs = getOperand(
packet, size, window.getLhsLocation(), window.getLhs());
int rhs = getOperand(
packet, size, window.getRhsLocation(), window.getRhs());
return compare(operator, lhs, rhs);
}
// Verifica che un pacchetto corrisponda a una regola
private int matchRule(FlowTableEntry rule, NetworkPacket packet) {
if (rule.getWindows().isEmpty()) {
return 0;
}
int target = rule.getWindows().size();
int actual = 0;
for (Window w : rule.getWindows()) {
actual = actual + matchWindow(w, packet);
}
return (actual == target ? 1 : 0);
}
// Esegue l'azione alla posizione r della tabella
private void runAction(AbstractAction action, NetworkPacket np) {
try {
int action_type = action.getType();
switch (action_type) {
case SDN_WISE_FORWARD_U:
case SDN_WISE_FORWARD_B:
np.setNxhop(((AbstractForwardAction) action).getNextHop());
radioTX(np, action_type == SDN_WISE_FORWARD_B);
break;
case SDN_WISE_DROP:
break;
//case 2
case SDN_WISE_SET:
SetAction ftam = (SetAction) action;
int operator = ftam.getOperator();
int lhs = getOperand(
np, SDN_WISE_SIZE_1, ftam.getLhsLocation(), ftam.getLhs());
int rhs = getOperand(
np, SDN_WISE_SIZE_1, ftam.getRhsLocation(), ftam.getRhs());
if (lhs == -1 || rhs == -1) {
throw new IllegalArgumentException("Operators out of bound");
}
int res = doOperation(operator, lhs, rhs);
if (ftam.getResLocation() == SDN_WISE_PACKET) {
int[] packet = np.toIntArray();
if (ftam.getRes() >= packet.length) {
throw new IllegalArgumentException("Result out of bound");
}
packet[ftam.getRes()] = res;
np.setArray(packet);
} else {
statusRegister.set(ftam.getRes(), res);
}
break;
case SDN_WISE_FUNCTION:
FunctionAction ftac = (FunctionAction) action;
FunctionInterface srvI = functions.get(ftac.getCallbackId());
if (srvI != null) {
LOGGER.log(Level.INFO, "[{0}]: function called", addr);
srvI.function(adcRegister,
flowTable,
neighborTable,
statusRegister,
acceptedId,
flowTableQueue,
txQueue,
ftac.getArg0(),
ftac.getArg1(),
ftac.getArg2(),
np
);
}
break;
case SDN_WISE_ASK:
np.setSrc(addr)
.setRequestFlag()
.setTtl(NetworkPacket.SDN_WISE_DFLT_TTL_MAX);
controllerTX(np);
break;
case SDN_WISE_MATCH:
flowTableQueue.add(np);
break;
case SDN_WISE_TO_UDP:
ToUdpAction tua = (ToUdpAction) action;
DatagramSocket sUDP = new DatagramSocket();
DatagramPacket pck = new DatagramPacket(np.toByteArray(),
np.getLen(), tua.getInetSocketAddress());
sUDP.send(pck);
break;
default:
break;
}//switch
} catch (IOException ex) {
LOGGER.log(Level.SEVERE, null, ex);
}
}
private int doOperation(int operatore, int item1, int item2) {
switch (operatore) {
case SDN_WISE_ADD:
return item1 + item2;
case SDN_WISE_SUB:
return item1 - item2;
case SDN_WISE_DIV:
return item1 / item2;
case SDN_WISE_MUL:
return item1 * item2;
case SDN_WISE_MOD:
return item1 % item2;
default:
return 0;
}
}
private int compare(int operatore, int item1, int item2) {
if (item1 == -1 || item2 == -1) {
return 0;
}
switch (operatore) {
case SDN_WISE_EQUAL:
return item1 == item2 ? 1 : 0;
case SDN_WISE_NOT_EQUAL:
return item1 != item2 ? 1 : 0;
case SDN_WISE_BIGGER:
return item1 > item2 ? 1 : 0;
case SDN_WISE_LESS:
return item1 < item2 ? 1 : 0;
case SDN_WISE_EQUAL_OR_BIGGER:
return item1 >= item2 ? 1 : 0;
case SDN_WISE_EQUAL_OR_LESS:
return item1 <= item2 ? 1 : 0;
default:
return 0;
}
}
void resetSemaphore() {
}
BeaconPacket prepareBeacon() {
BeaconPacket bp = new BeaconPacket(
net_id,
addr,
getActualSinkAddress(),
distanceFromSink,
battery.getBatteryPercent());
return bp;
}
ReportPacket prepareReport() {
ReportPacket rp = new ReportPacket(
net_id,
addr,
getActualSinkAddress(),
distanceFromSink,
battery.getBatteryPercent());
rp.setNeigh(neighbors_number)
.setNxhop(NxHopVsSink());
for (int j = 0; j < neighbors_number; j++) {
rp.setNeighbourAddressAt(neighborTable.get(j).getAddr(), j)
.setNeighbourWeightAt((byte) neighborTable.get(j).getRssi(), j);
}
initNeighborTable();
return rp;
}
final void updateTable() {
for (int i = 0; i < SDN_WISE_RLS_MAX; i++) {
FlowTableEntry tmp = flowTable.get(i);
if (tmp.getWindows().size() > 1) {
int ttl = tmp.getStats().getTtl();
if (ttl != SDN_WISE_RL_TTL_PERMANENT) {
if (ttl >= SDN_WISE_RL_TTL_DECR) {
tmp.getStats().decrementTtl(SDN_WISE_RL_TTL_DECR);
} else {
flowTable.set(i, new FlowTableEntry());
LOGGER.log(Level.INFO,
"[{0}]: Removing rule at position {1}", new Object[]{addr, i});
if (i == 0) {
resetSemaphore();
}
}
}
}
}
}
final int getNeighborIndex(NodeAddress addr) {
int i;
for (i = 0; i < SDN_WISE_NEIGHBORS_MAX; i++) {
if (neighborTable.get(i).getAddr().equals(addr)) {
return i;
}
if (neighborTable.get(i).getAddr().isBroadcast()) {
return -1;
}
}
return SDN_WISE_NEIGHBORS_MAX + 1;
}
final int searchAcceptedId(NodeAddress addr) {
int i;
for (i = 0; i < SDN_WISE_ACCEPTED_ID_MAX; i++) {
if (acceptedId.get(i).equals(addr)) {
return i;
}
}
return SDN_WISE_ACCEPTED_ID_MAX + 1;
}
final int getActualFlowIndex(int j) {
//j = j % SDN_WISE_RLS_MAX;
int i;
if (j == 0) {
i = 0;
} else {
i = flow_table_free_pos - j;
if (i == 0) {
i = SDN_WISE_RLS_MAX - 1;
} else if (i < 0) {
i = SDN_WISE_RLS_MAX - 1 + i;
}
}
return i;
}
private class FakeInfo {
InetSocketAddress inetAddress;
int rssi;
FakeInfo(InetSocketAddress inetAddress, int rssi) {
this.inetAddress = inetAddress;
this.rssi = rssi;
}
}
private class Task extends TimerTask {
private int cntBeacon;
private int cntReport;
private int cntUpdTable;
@Override
public void run() {
if (semaphore == 1 && battery.getBatteryLevel() > 0) {
battery.keepAlive(1);
cntBeacon++;
cntReport++;
//cntUpdTable++; // TODO will be enabled again in the future
if ((cntBeacon) >= cnt_beacon_max) {
cntBeacon = 0;
radioTX(prepareBeacon(), SDN_WISE_MAC_SEND_BROADCAST);
}
if ((cntReport) >= cnt_report_max) {
cntReport = 0;
controllerTX(prepareReport());
}
if ((cntUpdTable) >= cnt_updtable_max) {
cntUpdTable = 0;
updateTable();
}
}
}
}
private class TaskLogger extends TimerTask {
@Override
public void run() {
try (PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(logFilePath, true)))) {
out.println((int) battery.getBatteryLevel() + ","
+ battery.getBatteryPercent() + ","
+ flow_table_free_pos + ","
+ sentBytes + ","
+ receivedBytes);
} catch (IOException ex) {
LOGGER.log(Level.SEVERE, null, ex);
}
}
}
private class PacketSender implements Runnable {
@Override
public void run() {
try {
while (true) {
radioTX(txQueue.take(), SDN_WISE_MAC_SEND_UNICAST);
}
} catch (InterruptedException ex) {
LOGGER.log(Level.SEVERE, null, ex);
}
}
}
private class PacketManager implements Runnable {
@Override
public void run() {
try {
while (battery.getBatteryLevel() > 0) {
int rssi;
NetworkPacket tmpPacket = flowTableQueue.take();
FakeInfo fk = neighbourList.get(tmpPacket.getSrc());
if (fk != null) {
rssi = fk.rssi;
} else {
rssi = 255;
}
battery.receiveRadio(tmpPacket.getLen());
receivedBytes += tmpPacket.getLen();
rxHandler(tmpPacket, rssi);
}
} catch (InterruptedException ex) {
LOGGER.log(Level.SEVERE, null, ex);
}
}
}
private class CustomClassLoader extends ClassLoader {
public Class defClass(byte[] data, int len) {
return defineClass(null, data, 0, len);
}
}
}