Search in sources :

Example 11 with DhcpRecord

use of org.onosproject.dhcprelay.store.DhcpRecord in project onos by opennetworkinglab.

the class Dhcp4HandlerImpl method processDhcpPacketFromServer.

/**
 * Build the DHCP offer/ack with proper client port.
 *
 * @param ethernetPacket the original packet comes from server
 * @return new packet which will send to the client
 */
private InternalPacket processDhcpPacketFromServer(PacketContext context, Ethernet ethernetPacket) {
    // get dhcp header.
    Ethernet etherReply = (Ethernet) ethernetPacket.clone();
    IPv4 ipv4Packet = (IPv4) etherReply.getPayload();
    UDP udpPacket = (UDP) ipv4Packet.getPayload();
    DHCP dhcpPayload = (DHCP) udpPacket.getPayload();
    // determine the vlanId of the client host - note that this vlan id
    // could be different from the vlan in the packet from the server
    Interface clientInterface = getClientInterface(ethernetPacket, dhcpPayload).orElse(null);
    if (clientInterface == null) {
        log.warn("Cannot find the interface for the DHCP {}", dhcpPayload);
        return null;
    }
    VlanId vlanId;
    ConnectPoint inPort = context.inPacket().receivedFrom();
    boolean directConnFlag = directlyConnected(dhcpPayload);
    DhcpServerInfo foundServerInfo = findServerInfoFromServer(directConnFlag, inPort);
    if (foundServerInfo == null) {
        log.warn("Cannot find server info for {} server, inPort {}", directConnFlag ? "direct" : "indirect", inPort);
        return null;
    } else {
        if (Dhcp4HandlerUtil.isServerIpEmpty(foundServerInfo)) {
            log.warn("Cannot find server info's ipaddress");
            return null;
        }
    }
    if (clientInterface.vlanTagged().isEmpty()) {
        vlanId = clientInterface.vlan();
    } else {
        // might be multiple vlan in same interface
        vlanId = getVlanIdFromRelayAgentOption(dhcpPayload);
    }
    if (vlanId == null) {
        vlanId = VlanId.NONE;
    }
    etherReply.setVlanID(vlanId.toShort());
    etherReply.setSourceMACAddress(clientInterface.mac());
    if (!directlyConnected(dhcpPayload)) {
        // if client is indirectly connected, try use next hop mac address
        MacAddress macAddress = MacAddress.valueOf(dhcpPayload.getClientHardwareAddress());
        HostId hostId = HostId.hostId(macAddress, vlanId);
        if (((int) dhcpPayload.getFlags() & 0x8000) == 0x0000) {
            DhcpRecord record = dhcpRelayStore.getDhcpRecord(hostId).orElse(null);
            if (record != null) {
                // if next hop can be found, use mac address of next hop
                record.nextHop().ifPresent(etherReply::setDestinationMACAddress);
            } else {
                // otherwise, discard the packet
                log.warn("Can't find record for host id {}, discard packet", hostId);
                return null;
            }
        } else {
            etherReply.setDestinationMACAddress(MacAddress.BROADCAST);
        }
    } else {
        etherReply.setDestinationMACAddress(dhcpPayload.getClientHardwareAddress());
    }
    Ip4Address ipFacingClient = getFirstIpFromInterface(clientInterface);
    if (directlyConnected(dhcpPayload)) {
        // figure out the relay agent IP corresponding to the original request
        if (ipFacingClient == null) {
            log.warn("Cannot determine relay agent interface Ipv4 addr for host {}/{}. " + "Aborting relay for dhcp packet from server {}", etherReply.getDestinationMAC(), clientInterface.vlan(), ethernetPacket);
            return null;
        }
        // SRC_IP: IP facing client
        ipv4Packet.setSourceAddress(ipFacingClient.toInt());
    } else {
        // Get the IP address of the relay agent
        Ip4Address relayAgentIp = foundServerInfo.getRelayAgentIp4(clientInterface.connectPoint().deviceId()).orElse(null);
        if (relayAgentIp == null) {
            if (ipFacingClient == null) {
                log.warn("Cannot determine relay agent interface Ipv4 addr for host {}/{}. " + "Aborting relay for dhcp packet from server for indirect host {}", etherReply.getDestinationMAC(), clientInterface.vlan(), ethernetPacket);
                return null;
            } else {
                // SRC_IP: IP facing client
                ipv4Packet.setSourceAddress(ipFacingClient.toInt());
            }
        } else {
            // SRC_IP: relay agent IP
            ipv4Packet.setSourceAddress(relayAgentIp.toInt());
        }
    }
    // DST_IP: offered IP
    if (((int) dhcpPayload.getFlags() & 0x8000) == 0x0000) {
        ipv4Packet.setDestinationAddress(dhcpPayload.getYourIPAddress());
    } else {
        ipv4Packet.setDestinationAddress(BROADCAST_IP);
    }
    udpPacket.setSourcePort(UDP.DHCP_SERVER_PORT);
    if (directlyConnected(dhcpPayload)) {
        udpPacket.setDestinationPort(UDP.DHCP_CLIENT_PORT);
    } else {
        // TODO Implement component config to support for both L2 and L3 relay
        // L2 relay expects destination port to be CLIENT_PORT while L3 relay expects SERVER_PORT
        // Currently we only support L2 relay for DHCPv4
        udpPacket.setDestinationPort(UDP.DHCP_CLIENT_PORT);
    }
    udpPacket.setPayload(dhcpPayload);
    ipv4Packet.setPayload(udpPacket);
    etherReply.setPayload(ipv4Packet);
    return InternalPacket.internalPacket(etherReply, clientInterface.connectPoint());
}
Also used : UDP(org.onlab.packet.UDP) IPv4(org.onlab.packet.IPv4) Ip4Address(org.onlab.packet.Ip4Address) DhcpRecord(org.onosproject.dhcprelay.store.DhcpRecord) MacAddress(org.onlab.packet.MacAddress) HostId(org.onosproject.net.HostId) ConnectPoint(org.onosproject.net.ConnectPoint) DHCP(org.onlab.packet.DHCP) Ethernet(org.onlab.packet.Ethernet) Interface(org.onosproject.net.intf.Interface) VlanId(org.onlab.packet.VlanId) DhcpServerInfo(org.onosproject.dhcprelay.api.DhcpServerInfo)

Example 12 with DhcpRecord

use of org.onosproject.dhcprelay.store.DhcpRecord in project onos by opennetworkinglab.

the class Dhcp4HandlerImpl method writeRequestDhcpRecord.

/**
 * Writes DHCP record to the store according to the request DHCP packet (Discover, Request).
 *
 * @param location the location which DHCP packet comes from
 * @param ethernet the DHCP packet
 * @param dhcpPayload the DHCP payload
 */
private void writeRequestDhcpRecord(ConnectPoint location, Ethernet ethernet, DHCP dhcpPayload) {
    VlanId vlanId = VlanId.vlanId(ethernet.getVlanID());
    MacAddress macAddress = MacAddress.valueOf(dhcpPayload.getClientHardwareAddress());
    HostId hostId = HostId.hostId(macAddress, vlanId);
    DhcpRecord record = dhcpRelayStore.getDhcpRecord(hostId).orElse(null);
    if (record == null) {
        record = new DhcpRecord(HostId.hostId(macAddress, vlanId));
    } else {
        record = record.clone();
    }
    record.addLocation(new HostLocation(location, System.currentTimeMillis()));
    record.ip4Status(dhcpPayload.getPacketType());
    record.setDirectlyConnected(directlyConnected(dhcpPayload));
    if (!directlyConnected(dhcpPayload)) {
        // Update gateway mac address if the host is not directly connected
        record.nextHop(ethernet.getSourceMAC());
    }
    record.updateLastSeen();
    dhcpRelayStore.updateDhcpRecord(HostId.hostId(macAddress, vlanId), record);
}
Also used : HostLocation(org.onosproject.net.HostLocation) DhcpRecord(org.onosproject.dhcprelay.store.DhcpRecord) MacAddress(org.onlab.packet.MacAddress) HostId(org.onosproject.net.HostId) VlanId(org.onlab.packet.VlanId)

Example 13 with DhcpRecord

use of org.onosproject.dhcprelay.store.DhcpRecord in project onos by opennetworkinglab.

the class Dhcp4HandlerImpl method writeResponseDhcpRecord.

/**
 * Writes DHCP record to the store according to the response DHCP packet (Offer, Ack).
 *
 * @param ethernet the DHCP packet
 * @param dhcpPayload the DHCP payload
 */
private void writeResponseDhcpRecord(Ethernet ethernet, DHCP dhcpPayload) {
    Optional<Interface> outInterface = getClientInterface(ethernet, dhcpPayload);
    if (!outInterface.isPresent()) {
        log.warn("Failed to determine where to send {}", dhcpPayload.getPacketType());
        return;
    }
    Interface outIface = outInterface.get();
    ConnectPoint location = outIface.connectPoint();
    if (!location.port().hasName()) {
        location = translateSwitchPort(location);
    }
    VlanId vlanId = getVlanIdFromRelayAgentOption(dhcpPayload);
    if (vlanId == null) {
        vlanId = outIface.vlan();
    }
    MacAddress macAddress = MacAddress.valueOf(dhcpPayload.getClientHardwareAddress());
    HostId hostId = HostId.hostId(macAddress, vlanId);
    DhcpRecord record = dhcpRelayStore.getDhcpRecord(hostId).orElse(null);
    if (record == null) {
        record = new DhcpRecord(HostId.hostId(macAddress, vlanId));
    } else {
        record = record.clone();
    }
    record.addLocation(new HostLocation(location, System.currentTimeMillis()));
    if (dhcpPayload.getPacketType() == DHCP.MsgType.DHCPACK) {
        record.ip4Address(Ip4Address.valueOf(dhcpPayload.getYourIPAddress()));
    }
    record.ip4Status(dhcpPayload.getPacketType());
    record.setDirectlyConnected(directlyConnected(dhcpPayload));
    record.updateLastSeen();
    dhcpRelayStore.updateDhcpRecord(HostId.hostId(macAddress, vlanId), record);
}
Also used : HostLocation(org.onosproject.net.HostLocation) DhcpRecord(org.onosproject.dhcprelay.store.DhcpRecord) MacAddress(org.onlab.packet.MacAddress) HostId(org.onosproject.net.HostId) ConnectPoint(org.onosproject.net.ConnectPoint) Interface(org.onosproject.net.intf.Interface) VlanId(org.onlab.packet.VlanId)

Example 14 with DhcpRecord

use of org.onosproject.dhcprelay.store.DhcpRecord in project onos by opennetworkinglab.

the class Dhcp4HandlerImpl method handleLeaseQueryActivateMsg.

private void handleLeaseQueryActivateMsg(Ethernet packet, DHCP dhcpPayload) {
    log.debug("LQ: Got DHCPLEASEACTIVE packet!");
    if (learnRouteFromLeasequery) {
        // TODO: release the ip address from client
        MacAddress clientMacAddress = MacAddress.valueOf(dhcpPayload.getClientHardwareAddress());
        VlanId vlanId = VlanId.vlanId(packet.getVlanID());
        HostId hostId = HostId.hostId(clientMacAddress, vlanId);
        DhcpRecord record = dhcpRelayStore.getDhcpRecord(hostId).orElse(null);
        if (record == null) {
            log.warn("Can't find record for host {} when processing DHCPLEASEACTIVE", hostId);
            return;
        }
        // need to update routes
        log.debug("Lease Query for Client results in DHCPLEASEACTIVE - route needs to be modified");
        // get current route
        // find the ip of that client with the DhcpRelay store
        Ip4Address clientIP = record.ip4Address().orElse(null);
        log.debug("LQ: IP of host is " + clientIP.getIp4Address());
        MacAddress nextHopMac = record.nextHop().orElse(null);
        log.debug("LQ: MAC of resulting *OLD* NH for that host is " + nextHopMac.toString());
        // find the new NH by looking at the src MAC of the dhcp request
        // from the LQ store
        MacAddress newNextHopMac = record.nextHopTemp().orElse(null);
        log.debug("LQ: MAC of resulting *NEW* NH for that host is " + newNextHopMac.toString());
        log.debug("LQ: updating dhcp relay record with new NH");
        record.nextHop(newNextHopMac);
        // find the next hop IP from its mac
        HostId gwHostId = HostId.hostId(newNextHopMac, vlanId);
        Host gwHost = hostService.getHost(gwHostId);
        if (gwHost == null) {
            log.warn("Can't find gateway for new NH host " + gwHostId);
            return;
        }
        Ip4Address nextHopIp = gwHost.ipAddresses().stream().filter(IpAddress::isIp4).map(IpAddress::getIp4Address).findFirst().orElse(null);
        if (nextHopIp == null) {
            log.warn("Can't find IP address of gateway " + gwHost);
            return;
        }
        log.debug("LQ: *NEW* NH IP for host is " + nextHopIp.getIp4Address());
        Route route = new Route(Route.Source.DHCP, clientIP.toIpPrefix(), nextHopIp);
        routeStore.updateRoute(route);
    }
    // and forward to client
    InternalPacket ethernetPacket = processLeaseQueryFromServer(packet);
    if (ethernetPacket != null) {
        sendResponseToClient(ethernetPacket, dhcpPayload);
    }
}
Also used : Ip4Address(org.onlab.packet.Ip4Address) DhcpRecord(org.onosproject.dhcprelay.store.DhcpRecord) Host(org.onosproject.net.Host) InterfaceIpAddress(org.onosproject.net.host.InterfaceIpAddress) IpAddress(org.onlab.packet.IpAddress) MacAddress(org.onlab.packet.MacAddress) HostId(org.onosproject.net.HostId) VlanId(org.onlab.packet.VlanId) Route(org.onosproject.routeservice.Route)

Example 15 with DhcpRecord

use of org.onosproject.dhcprelay.store.DhcpRecord in project onos by opennetworkinglab.

the class Dhcp4HandlerImpl method getVlanIdFromDhcpRecord.

/**
 * Get the required vlanId in case the DCHP record has more than one vlanId for a given MAC.
 *
 * @param mac MAC address of the DHCP client
 * @param vlan Expected vlan of the DHCP client
 */
private VlanId getVlanIdFromDhcpRecord(MacAddress mac, VlanId vlan) {
    // Get all the DHCP records matching with the mac address
    // If only one entry is present then pick the vlan of that entry
    // If more then one entry is present then look for an entry with matching vlan
    // else return null
    Collection<DhcpRecord> records = dhcpRelayStore.getDhcpRecords();
    List<DhcpRecord> filteredRecords = new ArrayList<>();
    for (DhcpRecord e : records) {
        if (e.macAddress().equals(mac)) {
            filteredRecords.add(e);
        }
    }
    log.debug("getVlanIdFromDhcpRecord mac: {} vlan: {}", mac, vlan);
    log.debug("filteredRecords are: {}", filteredRecords);
    if (filteredRecords.size() == 1) {
        log.debug("Only one DHCP record entry. Returning back the vlan of that DHCP record: {}", filteredRecords);
        return filteredRecords.get(0).vlanId();
    }
    // Check in the DHCP filtered record for matching vlan
    for (DhcpRecord e : filteredRecords) {
        if (e.vlanId().equals(vlan)) {
            log.debug("Found a matching vlan entry in the DHCP record:{}", e);
            return vlan;
        }
    }
    // Found nothing return null
    log.debug("Returning null as no matching or more than one matching entry found");
    return null;
}
Also used : CopyOnWriteArrayList(java.util.concurrent.CopyOnWriteArrayList) ArrayList(java.util.ArrayList) DhcpRecord(org.onosproject.dhcprelay.store.DhcpRecord)

Aggregations

DhcpRecord (org.onosproject.dhcprelay.store.DhcpRecord)20 MacAddress (org.onlab.packet.MacAddress)13 HostId (org.onosproject.net.HostId)12 VlanId (org.onlab.packet.VlanId)11 IpAddress (org.onlab.packet.IpAddress)9 Route (org.onosproject.routeservice.Route)8 Host (org.onosproject.net.Host)7 HostLocation (org.onosproject.net.HostLocation)7 Ip4Address (org.onlab.packet.Ip4Address)6 ConnectPoint (org.onosproject.net.ConnectPoint)6 InterfaceIpAddress (org.onosproject.net.host.InterfaceIpAddress)5 Interface (org.onosproject.net.intf.Interface)5 DefaultHostDescription (org.onosproject.net.host.DefaultHostDescription)4 HostDescription (org.onosproject.net.host.HostDescription)4 ArrayList (java.util.ArrayList)3 CopyOnWriteArrayList (java.util.concurrent.CopyOnWriteArrayList)3 DhcpServerInfo (org.onosproject.dhcprelay.api.DhcpServerInfo)3 ArrayNode (com.fasterxml.jackson.databind.node.ArrayNode)2 ObjectNode (com.fasterxml.jackson.databind.node.ObjectNode)2 Preconditions.checkNotNull (com.google.common.base.Preconditions.checkNotNull)2