use of org.onlab.packet.MacAddress in project onos by opennetworkinglab.
the class Dhcp6HandlerImpl method removeHostOrRoute.
/**
* remove host or route and update dhcp relay record attributes.
*
* @param directConnFlag flag to show that packet is from directly connected client
* @param location client side connect point
* @param dhcp6Packet the dhcp6 payload
* @param clientPacket client's ethernet packet
* @param clientIpv6 client's Ipv6 packet
* @param clientInterface client interfaces
*/
private void removeHostOrRoute(boolean directConnFlag, ConnectPoint location, DHCP6 dhcp6Packet, Ethernet clientPacket, IPv6 clientIpv6, Interface clientInterface) {
log.debug("removeHostOrRoute enters {}", dhcp6Packet);
VlanId vlanId = clientInterface.vlan();
// could be gw or host
MacAddress srcMac = clientPacket.getSourceMAC();
MacAddress leafClientMac;
byte leafMsgType;
log.debug("client mac {} client vlan {}", HexString.toHexString(srcMac.toBytes(), ":"), vlanId);
Dhcp6ClientIdOption clientIdOption = Dhcp6HandlerUtil.extractClientId(directConnFlag, dhcp6Packet);
if (clientIdOption != null) {
if ((clientIdOption.getDuid().getDuidType() == Dhcp6Duid.DuidType.DUID_LLT) || (clientIdOption.getDuid().getDuidType() == Dhcp6Duid.DuidType.DUID_LL)) {
leafClientMac = MacAddress.valueOf(clientIdOption.getDuid().getLinkLayerAddress());
} else {
log.warn("Link-Layer Address not supported in CLIENTID option. No DhcpRelay Record created.");
// dhcpRelayCountersStore.incrementCounter(gCount, DhcpRelayCounters.NO_LINKLOCAL_FAIL);
return;
}
} else {
log.warn("CLIENTID option NOT found. Don't create DhcpRelay Record.");
// dhcpRelayCountersStore.incrementCounter(gCount, DhcpRelayCounters.NO_CLIENTID_FAIL);
return;
}
HostId leafHostId = HostId.hostId(leafClientMac, vlanId);
DhcpRecord record = dhcpRelayStore.getDhcpRecord(leafHostId).orElse(null);
if (record == null) {
record = new DhcpRecord(leafHostId);
} else {
record = record.clone();
}
Boolean isMsgRelease = Dhcp6HandlerUtil.isDhcp6Release(dhcp6Packet);
IpAddressInfo ipInfo;
PdPrefixInfo pdInfo = null;
if (directConnFlag) {
// Add to host store if it is connected to network directly
ipInfo = extractIpAddress(dhcp6Packet);
if (ipInfo != null) {
if (isMsgRelease) {
HostId hostId = HostId.hostId(srcMac, vlanId);
log.debug("remove Host {} ip for directly connected.", hostId.toString());
providerService.removeIpFromHost(hostId, ipInfo.ip6Address);
}
} else {
log.debug("ipAddress not found. Do not remove Host {} for directly connected.", HostId.hostId(srcMac, vlanId).toString());
}
leafMsgType = dhcp6Packet.getMsgType();
} else {
// Remove from route store if it is not connected to network directly
// pick out the first link-local ip address
IpAddress nextHopIp = getFirstIpByHost(directConnFlag, srcMac, vlanId);
if (nextHopIp == null) {
log.warn("Can't find link-local IP address of gateway mac {} vlanId {}", srcMac, vlanId);
// dhcpRelayCountersStore.incrementCounter(gCount, DhcpRelayCounters.NO_LINKLOCAL_GW);
return;
}
DHCP6 leafDhcp = Dhcp6HandlerUtil.getDhcp6Leaf(dhcp6Packet);
ipInfo = extractIpAddress(leafDhcp);
if (ipInfo == null) {
log.debug("ip is null");
} else {
if (isMsgRelease) {
Route routeForIP = new Route(Route.Source.DHCP, ipInfo.ip6Address.toIpPrefix(), nextHopIp);
log.debug("removing route of 128 address for indirectly connected.");
log.debug("128 ip {}, nexthop {}", HexString.toHexString(ipInfo.ip6Address.toOctets(), ":"), HexString.toHexString(nextHopIp.toOctets(), ":"));
routeStore.removeRoute(routeForIP);
}
}
pdInfo = extractPrefix(leafDhcp);
if (pdInfo == null) {
log.debug("ipPrefix is null ");
} else {
if (isMsgRelease) {
Route routeForPrefix = new Route(Route.Source.DHCP, pdInfo.pdPrefix, nextHopIp);
log.debug("removing route of PD for indirectly connected.");
log.debug("pd ip {}, nexthop {}", HexString.toHexString(pdInfo.pdPrefix.address().toOctets(), ":"), HexString.toHexString(nextHopIp.toOctets(), ":"));
routeStore.removeRoute(routeForPrefix);
if (this.dhcpFpmEnabled) {
dhcpFpmPrefixStore.removeFpmRecord(pdInfo.pdPrefix);
}
}
}
leafMsgType = leafDhcp.getMsgType();
}
if (isMsgRelease) {
log.debug("DHCP6 RELEASE msg.");
if (record != null) {
if (ipInfo != null) {
log.debug("DhcpRelay Record ip6Address is set to null.");
record.ip6Address(null);
}
if (pdInfo != null) {
log.debug("DhcpRelay Record pdPrefix is set to null.");
}
if (!record.ip6Address().isPresent() && !record.pdPrefix().isPresent()) {
log.warn("IP6 address and IP6 PD both are null. Remove record.");
// do not remove a record. Let timer task handler it.
// dhcpRelayStore.removeDhcpRecord(HostId.hostId(leafClientMac, vlanId));
}
}
}
if (record != null) {
record.getV6Counters().incrementCounter(Dhcp6HandlerUtil.getMsgTypeStr(leafMsgType));
record.addLocation(new HostLocation(location, System.currentTimeMillis()));
record.ip6Status(DHCP6.MsgType.getType(leafMsgType));
record.setDirectlyConnected(directConnFlag);
if (!directConnFlag) {
// Update gateway mac address if the host is not directly connected
record.nextHop(srcMac);
}
record.updateLastSeen();
}
dhcpRelayStore.updateDhcpRecord(leafHostId, record);
/*
// TODO Use AtomicInteger for the counters
try {
recordSemaphore.acquire();
try {
dhcpRelayCountersStore.incrementCounter(gCount, Dhcp6HandlerUtil.getMsgTypeStr(leafMsgType));
} finally {
// calling release() after a successful acquire()
recordSemaphore.release();
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
*/
}
use of org.onlab.packet.MacAddress in project onos by opennetworkinglab.
the class Dhcp6HandlerImpl method findNextHopIp6FromRelayStore.
public Ip6Address findNextHopIp6FromRelayStore(Ip6Address clientAddress) {
DhcpRecord dr = getDhcpRelayRecordFor(clientAddress);
if (dr != null) {
Optional<MacAddress> nextHopMac = dr.nextHop();
if (nextHopMac.isPresent()) {
// find the local ip6 from the host store
HostId gwHostId = HostId.hostId(nextHopMac.get(), dr.vlanId());
Host gwHost = hostService.getHost(gwHostId);
if (gwHost == null) {
log.warn("Can't find next hop host ID {}", gwHostId);
return null;
}
Ip6Address nextHopIp = gwHost.ipAddresses().stream().filter(IpAddress::isIp6).filter(IpAddress::isLinkLocal).map(IpAddress::getIp6Address).findFirst().orElse(null);
log.info("findNextHopIp6FromRelayStore " + clientAddress + " got mac " + nextHopMac.toString() + " ip6 " + nextHopIp);
return nextHopIp;
}
} else {
log.warn("findNextHopIp6FromRelayStore could NOT find next hop for " + clientAddress);
return null;
}
return null;
}
use of org.onlab.packet.MacAddress in project onos by opennetworkinglab.
the class Dhcp6HandlerImpl method timeTick.
/**
* Find lease-expired ipaddresses and pd prefixes.
* Removing host/route/fpm entries.
*/
public void timeTick() {
long currentTime = System.currentTimeMillis();
Collection<DhcpRecord> records = dhcpRelayStore.getDhcpRecords();
log.debug("timeTick called currenttime {} records num {} ", currentTime, records.size());
records.forEach(record -> {
boolean addrOrPdRemoved = false;
DHCP6.MsgType ip6Status = record.ip6Status().orElse(null);
if (ip6Status == null) {
log.debug("record is not valid v6 record.");
return;
}
if ((currentTime - record.getLastIp6Update()) > ((record.addrPrefTime() + getDhcp6PollInterval() / 2) * 1000)) {
// remove ipaddress from host/route table
IpAddress ip = record.ip6Address().orElse(null);
if (ip != null) {
if (record.directlyConnected()) {
providerService.removeIpFromHost(HostId.hostId(record.macAddress(), record.vlanId()), ip);
} else {
MacAddress gwMac = record.nextHop().orElse(null);
if (gwMac == null) {
log.warn("Can't find gateway mac address from record {} for ip6Addr", record);
return;
}
IpAddress nextHopIp = getFirstIpByHost(record.directlyConnected(), gwMac, record.vlanId());
Route route = new Route(Route.Source.DHCP, ip.toIpPrefix(), nextHopIp);
routeStore.removeRoute(route);
}
record.updateAddrPrefTime(0);
record.ip6Address(null);
addrOrPdRemoved = true;
dhcpRelayStore.updateDhcpRecord(HostId.hostId(record.macAddress(), record.vlanId()), record);
log.warn("IP6 address is set to null. delta {} lastUpdate {} addrPrefTime {}", (currentTime - record.getLastIp6Update()), record.getLastIp6Update(), record.addrPrefTime());
}
}
if ((currentTime - record.getLastPdUpdate()) > ((record.pdPrefTime() + getDhcp6PollInterval() / 2) * 1000)) {
// remove PD from route/fpm table
IpPrefix pdIpPrefix = record.pdPrefix().orElse(null);
if (pdIpPrefix != null) {
if (record.directlyConnected()) {
providerService.removeIpFromHost(HostId.hostId(record.macAddress(), record.vlanId()), pdIpPrefix.address().getIp6Address());
} else {
MacAddress gwMac = record.nextHop().orElse(null);
if (gwMac == null) {
log.warn("Can't find gateway mac address from record {} for PD prefix", record);
return;
}
IpAddress nextHopIp = getFirstIpByHost(record.directlyConnected(), gwMac, record.vlanId());
Route route = new Route(Route.Source.DHCP, pdIpPrefix, nextHopIp);
routeStore.removeRoute(route);
if (this.dhcpFpmEnabled) {
dhcpFpmPrefixStore.removeFpmRecord(pdIpPrefix);
}
}
record.updatePdPrefTime(0);
record.pdPrefix(null);
addrOrPdRemoved = true;
dhcpRelayStore.updateDhcpRecord(HostId.hostId(record.macAddress(), record.vlanId()), record);
log.warn("PD prefix is set to null.delta {} pdPrefTime {}", (currentTime - record.getLastPdUpdate()), record.pdPrefTime());
}
}
if (addrOrPdRemoved && !record.ip6Address().isPresent() && !record.pdPrefix().isPresent()) {
log.warn("ip6Status {} IP6 address and IP6 PD both are null. Remove record.", ip6Status);
dhcpRelayStore.removeDhcpRecord(HostId.hostId(record.macAddress(), record.vlanId()));
}
});
}
use of org.onlab.packet.MacAddress in project onos by opennetworkinglab.
the class Dhcp6HandlerUtil method processLQ6PacketFromServer.
/**
* process the LQ reply packet from dhcp server.
*
* @param defaultServerInfoList default server list
* @param indirectServerInfoList default indirect server list
* @param serverInterface server interface
* @param interfaceService interface service
* @param hostService host service
* @param context packet context
* @param receivedPacket server ethernet packet
* @param recevingInterfaces set of server side interfaces
* @return a packet ready to be sent to relevant output interface
*/
public static InternalPacket processLQ6PacketFromServer(List<DhcpServerInfo> defaultServerInfoList, List<DhcpServerInfo> indirectServerInfoList, Interface serverInterface, InterfaceService interfaceService, HostService hostService, PacketContext context, Ethernet receivedPacket, Set<Interface> recevingInterfaces) {
// get dhcp6 header.
Ethernet etherReply = (Ethernet) receivedPacket.clone();
IPv6 ipv6Packet = (IPv6) etherReply.getPayload();
UDP udpPacket = (UDP) ipv6Packet.getPayload();
DHCP6 lq6Reply = (DHCP6) udpPacket.getPayload();
// TODO: refactor
ConnectPoint receivedFrom = context.inPacket().receivedFrom();
DeviceId receivedFromDevice = receivedFrom.deviceId();
DhcpServerInfo serverInfo;
Ip6Address dhcpServerIp = null;
ConnectPoint dhcpServerConnectPoint = null;
MacAddress dhcpConnectMac = null;
VlanId dhcpConnectVlan = null;
Ip6Address dhcpGatewayIp = null;
// todo: refactor
Ip6Address indirectDhcpServerIp = null;
ConnectPoint indirectDhcpServerConnectPoint = null;
MacAddress indirectDhcpConnectMac = null;
VlanId indirectDhcpConnectVlan = null;
Ip6Address indirectDhcpGatewayIp = null;
Ip6Address indirectRelayAgentIpFromCfg = null;
if (!defaultServerInfoList.isEmpty()) {
serverInfo = defaultServerInfoList.get(0);
dhcpConnectMac = serverInfo.getDhcpConnectMac().orElse(null);
dhcpGatewayIp = serverInfo.getDhcpGatewayIp6().orElse(null);
dhcpServerIp = serverInfo.getDhcpServerIp6().orElse(null);
dhcpServerConnectPoint = serverInfo.getDhcpServerConnectPoint().orElse(null);
dhcpConnectVlan = serverInfo.getDhcpConnectVlan().orElse(null);
}
if (!indirectServerInfoList.isEmpty()) {
serverInfo = indirectServerInfoList.get(0);
indirectDhcpConnectMac = serverInfo.getDhcpConnectMac().orElse(null);
indirectDhcpGatewayIp = serverInfo.getDhcpGatewayIp6().orElse(null);
indirectDhcpServerIp = serverInfo.getDhcpServerIp6().orElse(null);
indirectDhcpServerConnectPoint = serverInfo.getDhcpServerConnectPoint().orElse(null);
indirectDhcpConnectVlan = serverInfo.getDhcpConnectVlan().orElse(null);
indirectRelayAgentIpFromCfg = serverInfo.getRelayAgentIp6(receivedFromDevice).orElse(null);
}
Boolean directConnFlag = directlyConnected(lq6Reply);
ConnectPoint inPort = context.inPacket().receivedFrom();
if ((directConnFlag || indirectDhcpServerIp == null) && !inPort.equals(dhcpServerConnectPoint)) {
log.warn("Receiving port {} is not the same as server connect point {} for direct or indirect-null", inPort, dhcpServerConnectPoint);
return null;
}
if (!directConnFlag && indirectDhcpServerIp != null && !inPort.equals(indirectDhcpServerConnectPoint)) {
log.warn("Receiving port {} is not the same as server connect point {} for indirect", inPort, indirectDhcpServerConnectPoint);
return null;
}
Ip6Address nextHopIP = Ip6Address.valueOf(ipv6Packet.getDestinationAddress());
// use hosts store to find out the next hop mac and connection point
Set<Host> hosts = hostService.getHostsByIp(nextHopIP);
Host host;
if (!hosts.isEmpty()) {
host = hosts.iterator().next();
} else {
log.warn("Host {} is not in store", nextHopIP);
return null;
}
HostLocation hl = host.location();
// iterator().next());
String clientConnectionPointStr = hl.toString();
ConnectPoint clientConnectionPoint = ConnectPoint.deviceConnectPoint(clientConnectionPointStr);
VlanId originalPacketVlanId = VlanId.vlanId(etherReply.getVlanID());
Interface iface;
iface = interfaceService.getInterfacesByPort(clientConnectionPoint).stream().filter(iface1 -> interfaceContainsVlan(iface1, originalPacketVlanId)).findFirst().orElse(null);
etherReply.setSourceMACAddress(iface.mac());
etherReply.setDestinationMACAddress(host.mac());
// workaround for a bug where core sends src port as 547 (server)
udpPacket.setDestinationPort(UDP.DHCP_V6_SERVER_PORT);
udpPacket.setPayload(lq6Reply);
udpPacket.resetChecksum();
ipv6Packet.setPayload(udpPacket);
etherReply.setPayload(ipv6Packet);
return InternalPacket.internalPacket(etherReply, clientConnectionPoint);
}
use of org.onlab.packet.MacAddress in project onos by opennetworkinglab.
the class Dhcp6HandlerUtil method buildDhcp6PacketFromClient.
/**
* build the DHCP6 solicit/request packet with gatewayip.
*
* @param context packet context
* @param clientPacket client ethernet packet
* @param clientInterfaces set of client side interfaces
* @param serverInfo target server which a packet is generated for
* @param serverInterface target server interface
* @return ethernet packet with dhcp6 packet info
*/
public static Ethernet buildDhcp6PacketFromClient(PacketContext context, Ethernet clientPacket, Set<Interface> clientInterfaces, DhcpServerInfo serverInfo, Interface serverInterface) {
ConnectPoint receivedFrom = context.inPacket().receivedFrom();
DeviceId receivedFromDevice = receivedFrom.deviceId();
Ip6Address relayAgentIp = getRelayAgentIPv6Address(clientInterfaces);
MacAddress relayAgentMac = clientInterfaces.iterator().next().mac();
if (relayAgentIp == null || relayAgentMac == null) {
log.warn("Missing DHCP relay agent interface Ipv6 addr config for " + "packet from client on port: {}. Aborting packet processing", clientInterfaces.iterator().next().connectPoint());
return null;
}
IPv6 clientIpv6 = (IPv6) clientPacket.getPayload();
UDP clientUdp = (UDP) clientIpv6.getPayload();
DHCP6 clientDhcp6 = (DHCP6) clientUdp.getPayload();
boolean directConnFlag = directlyConnected(clientDhcp6);
Ip6Address serverIpFacing = getFirstIpFromInterface(serverInterface);
if (serverIpFacing == null || serverInterface.mac() == null) {
log.warn("No IP v6 address for server Interface {}", serverInterface);
return null;
}
Ethernet etherReply = clientPacket.duplicate();
etherReply.setSourceMACAddress(serverInterface.mac());
// set default info and replace with indirect if available later on.
if (serverInfo.getDhcpConnectMac().isPresent()) {
etherReply.setDestinationMACAddress(serverInfo.getDhcpConnectMac().get());
}
if (serverInfo.getDhcpConnectVlan().isPresent()) {
etherReply.setVlanID(serverInfo.getDhcpConnectVlan().get().toShort());
}
IPv6 ipv6Packet = (IPv6) etherReply.getPayload();
byte[] peerAddress = clientIpv6.getSourceAddress();
ipv6Packet.setSourceAddress(serverIpFacing.toOctets());
ipv6Packet.setDestinationAddress(serverInfo.getDhcpServerIp6().get().toOctets());
UDP udpPacket = (UDP) ipv6Packet.getPayload();
udpPacket.setSourcePort(UDP.DHCP_V6_SERVER_PORT);
DHCP6 dhcp6Packet = (DHCP6) udpPacket.getPayload();
byte[] dhcp6PacketByte = dhcp6Packet.serialize();
DHCP6 dhcp6Relay = new DHCP6();
dhcp6Relay.setMsgType(DHCP6.MsgType.RELAY_FORW.value());
if (directConnFlag) {
dhcp6Relay.setLinkAddress(relayAgentIp.toOctets());
} else {
if (isServerIpEmpty(serverInfo)) {
log.warn("indirect DhcpServerIp empty... use default server ");
} else {
// Check if mac is obtained for valid server ip
if (isConnectMacEmpty(serverInfo, clientInterfaces)) {
log.warn("indirect Dhcp ConnectMac empty ...");
return null;
}
etherReply.setDestinationMACAddress(serverInfo.getDhcpConnectMac().get());
etherReply.setVlanID(serverInfo.getDhcpConnectVlan().get().toShort());
ipv6Packet.setDestinationAddress(serverInfo.getDhcpServerIp6().get().toOctets());
}
if (!serverInfo.getRelayAgentIp6(receivedFromDevice).isPresent()) {
log.debug("indirect connection: relayAgentIp NOT availale from config file! Use dynamic. {}", HexString.toHexString(relayAgentIp.toOctets(), ":"));
serverIpFacing = relayAgentIp;
} else {
serverIpFacing = serverInfo.getRelayAgentIp6(receivedFromDevice).get();
}
log.debug("Source IP address set as relay agent IP with value: {}", serverIpFacing);
dhcp6Relay.setLinkAddress(serverIpFacing.toOctets());
ipv6Packet.setSourceAddress(serverIpFacing.toOctets());
}
// peer address: address of the client or relay agent from which the message to be relayed was received.
dhcp6Relay.setPeerAddress(peerAddress);
// directly connected case, hop count is zero; otherwise, hop count + 1
if (directConnFlag) {
dhcp6Relay.setHopCount((byte) 0);
} else {
dhcp6Relay.setHopCount((byte) (dhcp6Packet.getHopCount() + 1));
}
List<Dhcp6Option> options = new ArrayList<>();
addDhcp6OptionsFromClient(options, dhcp6PacketByte, context, clientPacket);
dhcp6Relay.setOptions(options);
udpPacket.setPayload(dhcp6Relay);
udpPacket.resetChecksum();
ipv6Packet.setPayload(udpPacket);
ipv6Packet.setHopLimit((byte) 64);
etherReply.setPayload(ipv6Packet);
return etherReply;
}
Aggregations