package net.floodlightcontroller.dhcpserver;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import net.floodlightcontroller.core.types.NodePortTuple;
import org.projectfloodlight.openflow.types.IPv4Address;
import org.projectfloodlight.openflow.types.MacAddress;
import org.projectfloodlight.openflow.types.VlanVid;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class DHCPInstance {
private static final Logger log = LoggerFactory.getLogger(DHCPInstance.class);
private String name = null;
private volatile DHCPPool pool = null;
private Set<NodePortTuple> memberPorts = null;
private Set<VlanVid> memberVlans = null;
private IPv4Address serverIp = IPv4Address.NONE;
private MacAddress serverMac = MacAddress.NONE;
private IPv4Address subnetMask = IPv4Address.NONE;
private IPv4Address broadcastIp = IPv4Address.NONE;
private IPv4Address routerIp = IPv4Address.NONE;
private List<IPv4Address> ntpIps = null;
private List<IPv4Address> dnsIps = null;
private String domainName = null;
private boolean ipForwarding = false;
private int leaseTimeSec = 0;
public static final int HOLD_LEASE_TIME_SEC = 10;
/* Computed */
private int rebindTimeSec = 0;
private int renewalTimeSec = 0;
private DHCPInstance() {
ipForwarding = false;
}
public static DHCPInstanceBuilder createBuilder() {
return new DHCPInstanceBuilder();
}
public String getName() {
return name;
}
public IPv4Address getServerIp() {
return serverIp;
}
public MacAddress getServerMac() {
return serverMac;
}
public IPv4Address getSubnetMask() {
return subnetMask;
}
public IPv4Address getBroadcastIp() {
return broadcastIp;
}
public IPv4Address getRouterIp() {
return routerIp;
}
public List<IPv4Address> getNtpIps() {
return Collections.unmodifiableList(ntpIps);
}
public List<IPv4Address> getDnsIps() {
return Collections.unmodifiableList(dnsIps);
}
public String getDomainName() {
return domainName;
}
public boolean getIpForwarding() {
return ipForwarding;
}
public int getLeaseTimeSec() {
return leaseTimeSec;
}
public int getRenewalTimeSec() {
return renewalTimeSec;
}
public int getRebindTimeSec() {
return rebindTimeSec;
}
public int getHoldTimeSec() {
return HOLD_LEASE_TIME_SEC;
}
public DHCPPool getPool() {
return pool;
}
public Set<NodePortTuple> getMemberPorts() {
return Collections.unmodifiableSet(memberPorts);
}
public Set<VlanVid> getMemberVlans() {
return Collections.unmodifiableSet(memberVlans);
}
public static class DHCPInstanceBuilder {
private DHCPInstance tempInstance = null;
private Map<MacAddress, IPv4Address> tempStaticAddresses = null;
private IPv4Address tempStart = IPv4Address.NONE;
private IPv4Address tempStop = IPv4Address.NONE;
private DHCPInstanceBuilder() {
tempInstance = new DHCPInstance();
tempStaticAddresses = new HashMap<MacAddress, IPv4Address>();
}
public DHCPInstanceBuilder setName(String name) {
if (name == null || name.isEmpty()) {
throw new IllegalArgumentException("DHCP server name cannot be null or empty");
}
tempInstance.name = name;
return this;
}
public DHCPInstanceBuilder setServer(MacAddress mac, IPv4Address ip) {
if (ip == null || mac == null) {
throw new IllegalArgumentException("DHCP server IP/Mac cannot be null");
}
tempInstance.serverIp = ip;
tempInstance.serverMac = mac;
return this;
}
public DHCPInstanceBuilder setSubnetMask(IPv4Address mask) {
if (mask == null) {
throw new IllegalArgumentException("DHCP server subnet mask cannot be null");
}
tempInstance.subnetMask = mask;
return this;
}
public DHCPInstanceBuilder setBroadcastIp(IPv4Address bcast) {
if (bcast == null) {
throw new IllegalArgumentException("DHCP server broadcast IP cannot be null");
}
tempInstance.broadcastIp = bcast;
return this;
}
public DHCPInstanceBuilder setStartIp(IPv4Address start) {
if (start == null) {
throw new IllegalArgumentException("DHCP pool start IP cannot be null");
}
tempStart = start;
return this;
}
public DHCPInstanceBuilder setStopIp(IPv4Address stop) {
if (stop == null) {
throw new IllegalArgumentException("DHCP pool stop IP cannot be null");
}
tempStop = stop;
return this;
}
public DHCPInstanceBuilder setRouterIp(IPv4Address router) {
if (router == null) {
throw new IllegalArgumentException("DHCP server router/gateway IP cannot be null");
}
tempInstance.routerIp = router;
return this;
}
public DHCPInstanceBuilder setNtpIps(List<IPv4Address> ntps) {
if (ntps == null) {
throw new IllegalArgumentException("DHCP server NTP IP list cannot be null");
}
tempInstance.ntpIps = ntps;
return this;
}
public DHCPInstanceBuilder setDnsIps(List<IPv4Address> dnss) {
if (dnss == null) {
throw new IllegalArgumentException("DHCP server DNS IP list cannot be null");
}
tempInstance.dnsIps = dnss;
return this;
}
public DHCPInstanceBuilder setDomainName(String dn) {
if (dn == null) {
throw new IllegalArgumentException("DHCP server domain name cannot be null");
}
tempInstance.domainName = dn;
return this;
}
public DHCPInstanceBuilder setIpForwarding(boolean on) {
tempInstance.ipForwarding = on;
return this;
}
public DHCPInstanceBuilder setLeaseTimeSec(int s) {
if (s <= 0) {
throw new IllegalArgumentException("DHCP server lease time must be > 0");
}
if (s < 3600) {
log.warn("DHCP server lease time set less than one hour at {} seconds", s);
}
tempInstance.leaseTimeSec = s;
return this;
}
public DHCPInstanceBuilder addReservedStaticAddress(MacAddress rsvMac, IPv4Address rsvIp) {
tempStaticAddresses.put(rsvMac, rsvIp);
return this;
}
public DHCPInstanceBuilder setMemberPorts(Set<NodePortTuple> ports) {
if (ports == null) {
throw new IllegalArgumentException("DHCP server member ports cannot be null");
}
tempInstance.memberPorts = ports;
return this;
}
public DHCPInstanceBuilder setMemberVlans(Set<VlanVid> vlans) {
if (vlans == null) {
throw new IllegalArgumentException("DHCP server member VLANs cannot be null");
}
tempInstance.memberVlans = vlans;
return this;
}
public DHCPInstance build() {
DHCPInstance instanceToReturn = new DHCPInstance();
if (tempStart.compareTo(tempStop) > 0) {
throw new IllegalArgumentException("Start IP must be less than stop IP");
}
instanceToReturn.pool = new DHCPPool(tempStart, tempStop.getInt() - tempStart.getInt() + 1);
for (Entry<MacAddress, IPv4Address> entry : tempStaticAddresses.entrySet()) {
instanceToReturn.pool.configureFixedIPLease(entry.getValue(), entry.getKey());
}
if (tempInstance.leaseTimeSec <= 0) {
throw new IllegalArgumentException("DHCP server lease time must be > 0");
}
instanceToReturn.leaseTimeSec = tempInstance.leaseTimeSec;
instanceToReturn.rebindTimeSec = (int) (instanceToReturn.leaseTimeSec / 0.875);
instanceToReturn.renewalTimeSec = instanceToReturn.leaseTimeSec / 2;
// TODO check to make sure these are in the same subnet
instanceToReturn.broadcastIp = tempInstance.broadcastIp; /* IPv4/MacAddress are immutable */
instanceToReturn.serverMac = tempInstance.serverMac;
instanceToReturn.serverIp = tempInstance.serverIp;
instanceToReturn.routerIp = tempInstance.routerIp;
instanceToReturn.subnetMask = tempInstance.subnetMask;
instanceToReturn.domainName = tempInstance.domainName;
if (tempInstance.dnsIps == null) {
instanceToReturn.dnsIps = new ArrayList<IPv4Address>();
} else {
instanceToReturn.dnsIps = new ArrayList<IPv4Address>(tempInstance.dnsIps);
}
if (tempInstance.ntpIps == null) {
instanceToReturn.ntpIps = new ArrayList<IPv4Address>();
} else {
instanceToReturn.ntpIps = new ArrayList<IPv4Address>(tempInstance.ntpIps);
}
if (tempInstance.memberPorts == null) {
instanceToReturn.memberPorts = new HashSet<NodePortTuple>();
} else {
instanceToReturn.memberPorts = new HashSet<NodePortTuple>(tempInstance.memberPorts);
}
if (tempInstance.memberVlans == null) {
instanceToReturn.memberVlans = new HashSet<VlanVid>();
} else {
instanceToReturn.memberVlans = new HashSet<VlanVid>(tempInstance.memberVlans);
}
instanceToReturn.ipForwarding = tempInstance.ipForwarding;
return instanceToReturn;
}
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result
+ ((broadcastIp == null) ? 0 : broadcastIp.hashCode());
result = prime * result + ((dnsIps == null) ? 0 : dnsIps.hashCode());
result = prime * result
+ ((domainName == null) ? 0 : domainName.hashCode());
result = prime * result + (ipForwarding ? 1231 : 1237);
result = prime * result + leaseTimeSec;
result = prime * result
+ ((memberPorts == null) ? 0 : memberPorts.hashCode());
result = prime * result
+ ((memberVlans == null) ? 0 : memberVlans.hashCode());
result = prime * result + ((name == null) ? 0 : name.hashCode());
result = prime * result + ((ntpIps == null) ? 0 : ntpIps.hashCode());
result = prime * result + ((pool == null) ? 0 : pool.hashCode());
result = prime * result + rebindTimeSec;
result = prime * result + renewalTimeSec;
result = prime * result
+ ((routerIp == null) ? 0 : routerIp.hashCode());
result = prime * result
+ ((serverIp == null) ? 0 : serverIp.hashCode());
result = prime * result
+ ((serverMac == null) ? 0 : serverMac.hashCode());
result = prime * result
+ ((subnetMask == null) ? 0 : subnetMask.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
DHCPInstance other = (DHCPInstance) obj;
if (broadcastIp == null) {
if (other.broadcastIp != null)
return false;
} else if (!broadcastIp.equals(other.broadcastIp))
return false;
if (dnsIps == null) {
if (other.dnsIps != null)
return false;
} else if (!dnsIps.equals(other.dnsIps))
return false;
if (domainName == null) {
if (other.domainName != null)
return false;
} else if (!domainName.equals(other.domainName))
return false;
if (ipForwarding != other.ipForwarding)
return false;
if (leaseTimeSec != other.leaseTimeSec)
return false;
if (memberPorts == null) {
if (other.memberPorts != null)
return false;
} else if (!memberPorts.equals(other.memberPorts))
return false;
if (memberVlans == null) {
if (other.memberVlans != null)
return false;
} else if (!memberVlans.equals(other.memberVlans))
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
if (ntpIps == null) {
if (other.ntpIps != null)
return false;
} else if (!ntpIps.equals(other.ntpIps))
return false;
if (pool == null) {
if (other.pool != null)
return false;
} else if (!pool.equals(other.pool))
return false;
if (rebindTimeSec != other.rebindTimeSec)
return false;
if (renewalTimeSec != other.renewalTimeSec)
return false;
if (routerIp == null) {
if (other.routerIp != null)
return false;
} else if (!routerIp.equals(other.routerIp))
return false;
if (serverIp == null) {
if (other.serverIp != null)
return false;
} else if (!serverIp.equals(other.serverIp))
return false;
if (serverMac == null) {
if (other.serverMac != null)
return false;
} else if (!serverMac.equals(other.serverMac))
return false;
if (subnetMask == null) {
if (other.subnetMask != null)
return false;
} else if (!subnetMask.equals(other.subnetMask))
return false;
return true;
}
@Override
public String toString() {
return "DHCPInstance [name=" + name + ", pool=" + pool
+ ", memberPorts=" + memberPorts + ", memberVlans="
+ memberVlans + ", serverIp=" + serverIp + ", serverMac="
+ serverMac + ", subnetMask=" + subnetMask + ", broadcastIp="
+ broadcastIp + ", routerIp=" + routerIp + ", ntpIps=" + ntpIps
+ ", dnsIps=" + dnsIps + ", domainName=" + domainName
+ ", ipForwarding=" + ipForwarding + ", leaseTimeSec="
+ leaseTimeSec + ", rebindTimeSec=" + rebindTimeSec
+ ", renewalTimeSec=" + renewalTimeSec + "]";
}
}