// Set the network layer header
skbuf.setNetworkLayerHeader(hdr);
// The destination address must have been set, check it
if (hdr.getDestination() == null) {
throw new NetworkException("The destination address must have been set");
}
stat.opackets.inc();
// The device we will use to transmit the packet
final Device dev;
final NetDeviceAPI api;
// The hardware address we will be sending to
final HardwareAddress hwDstAddr;
// Has the destination device been given?
if (skbuf.getDevice() == null) {
// The device has not been send, figure out the route ourselves.
// First lets try to find a route
final IPv4Route route;
route = findRoute(hdr, skbuf);
route.incUseCount();
// Get the device
dev = route.getDevice();
api = route.getDeviceAPI();
// Get my source address if not already set
if (hdr.getSource() == null) {
hdr.setSource(getSourceAddress(route, hdr, skbuf));
}
// Get the hardware address for this device
hwDstAddr = findDstHWAddress(route, hdr, skbuf);
} else {
// The device has been given, use it
dev = skbuf.getDevice();
try {
api = dev.getAPI(NetDeviceAPI.class);
} catch (ApiNotFoundException ex) {
throw new NetworkException("Device is not a network device", ex);
}
// The source address must have been set, check it
if (hdr.getSource() == null) {
throw new NetworkException("The source address must have been set");
}
// Find the HW destination address
hwDstAddr = findDstHWAddress(hdr.getDestination(), dev, hdr, skbuf);
}
// Set the datalength (if not set)
if (hdr.getDataLength() == 0) {
hdr.setDataLength(skbuf.getSize());
}
// Set the identification number, if not set before
if (hdr.getIdentification() == 0) {
hdr.setIdentification(getNextID());
}
// Should we fragment?
final int mtu = api.getMTU();
if (hdr.getTotalLength() <= mtu) {
// We can send the complete packet
hdr.setMoreFragments(false);
hdr.setFragmentOffset(0);
sendPacket(api, hwDstAddr, hdr, skbuf);
} else if (hdr.isDontFragment()) {
// This packet cannot be send of this device
throw new NetworkException("Packet is too large, mtu=" + mtu);
} else {
// Fragment the packet and send the fragments
fragmentPacket(api, hwDstAddr, hdr, skbuf, mtu);
}
}