/*_########################################################################## _## _## Copyright (C) 2012 Kaito Yamada _## _########################################################################## */ package com.github.kaitoy.sneo.network; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import org.pcap4j.core.PacketListener; import org.pcap4j.packet.Packet; import org.pcap4j.util.MacAddress; import org.snmp4j.log.LogAdapter; import org.snmp4j.log.LogFactory; import com.github.kaitoy.sneo.network.protocol.EthernetHelper; public class LagInterface implements NetworkInterface { private static final LogAdapter logger = LogFactory.getLogger(LagInterface.class); private final String name; private final MacAddress macAddress; private final List<NifIpAddress> ipAddresses = Collections.synchronizedList(new ArrayList<NifIpAddress>()); private final int channelGroupNumber; private final Map<String, PhysicalNetworkInterface> aggregatedNifs = new ConcurrentHashMap<String, PhysicalNetworkInterface>(); private final PacketListener host; private final List<PacketListener> users = Collections.synchronizedList(new ArrayList<PacketListener>()); private volatile boolean running = false; public LagInterface( String name, MacAddress macAddress, int channelGroupNumber, PacketListener host ) { this.name = name; this.macAddress = macAddress; this.channelGroupNumber = channelGroupNumber; this.host = host; } public String getName() { return name; } public MacAddress getMacAddress() { return macAddress; } public boolean isTrunk() { for (PhysicalNetworkInterface pnif: aggregatedNifs.values()) { return pnif.isTrunk(); } return false; } public List<NifIpAddress> getIpAddresses() { return new ArrayList<NifIpAddress>(ipAddresses); } public void addIpAddress(NifIpAddress addr) { ipAddresses.add(addr); } public void addUser(PacketListener user) { users.add(user); } public int getChannelGroupNumber() { return channelGroupNumber; } public void start() { running = true; } public void stop() { running = false; } public void shutdown() { stop(); } public boolean isRunning() { return running; } public void addNif(String ifName, PhysicalNetworkInterface nif) { nif.addUser(new PacketListenerImpl(ifName)); aggregatedNifs.put(ifName, nif); } public void sendPacket(Packet packet) throws SendPacketException { if (!running) { if (logger.isDebugEnabled()) { logger.warn("Not running. Can't send a packet: " + packet); throw new SendPacketException(); } } boolean packetIsSent = false; for (NetworkInterface nif: aggregatedNifs.values()) { if (nif.isRunning()) { if (logger.isDebugEnabled()) { StringBuilder sb = new StringBuilder(); sb.append("Sending a packet via ") .append(nif.getName()) .append(": ") .append(packet); logger.debug(sb.toString()); } try { nif.sendPacket(packet); packetIsSent = true; break; } catch (SendPacketException e) { logger.error("Failed to send a packet: " + packet, e); } } } if (packetIsSent) { logger.debug("Succeeded in sending the packet."); } else { throw new SendPacketException(); } } private final class PacketListenerImpl implements PacketListener { private final String ifName; private PacketListenerImpl(String ifName) { this.ifName = ifName; } public void gotPacket(Packet packet) { for (PacketListener user: users) { user.gotPacket(packet); } if (EthernetHelper.matchesDestination(packet, macAddress)) { host.gotPacket(packet); } else { if (logger.isDebugEnabled()) { StringBuilder sb = new StringBuilder(); sb.append("Dropped a packet not to me(") .append(macAddress) .append("): ") .append(packet); logger.debug(sb.toString()); } } } } // @Override String toString() { // // } }