mirror of
https://github.com/opennetworkinglab/onos.git
synced 2026-04-22 05:51:50 +02:00
[CORD-2318] Allow v6 alternative dhcp server for default and indirect dhcp server
Change-Id: Ief4027a7528db7b4e3058fce369b3e1ddc214e92
This commit is contained in:
parent
ea4b6c2649
commit
495c9b2fa9
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,510 @@
|
||||
/*
|
||||
* Copyright 2017-present Open Networking Foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
package org.onosproject.dhcprelay;
|
||||
|
||||
import org.onlab.packet.BasePacket;
|
||||
import org.onlab.packet.DHCP6;
|
||||
import org.onlab.packet.DHCP6.MsgType;
|
||||
import org.onlab.packet.Ip6Address;
|
||||
import org.onlab.packet.IpAddress;
|
||||
import org.onlab.packet.VlanId;
|
||||
import org.onlab.packet.dhcp.Dhcp6RelayOption;
|
||||
import org.onlab.packet.dhcp.Dhcp6Option;
|
||||
|
||||
import org.onlab.packet.Ethernet;
|
||||
import org.onlab.packet.IPv6;
|
||||
import org.onlab.packet.MacAddress;
|
||||
import org.onlab.packet.UDP;
|
||||
|
||||
import org.onlab.util.HexString;
|
||||
import org.onosproject.dhcprelay.api.DhcpServerInfo;
|
||||
import org.onosproject.net.ConnectPoint;
|
||||
import org.onosproject.net.host.InterfaceIpAddress;
|
||||
import org.onosproject.net.intf.Interface;
|
||||
import org.onosproject.net.packet.PacketContext;
|
||||
import org.onosproject.net.DeviceId;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import java.util.Set;
|
||||
import java.util.List;
|
||||
import java.util.ArrayList;
|
||||
|
||||
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
|
||||
|
||||
public class Dhcp6HandlerUtil {
|
||||
|
||||
private final Logger log = LoggerFactory.getLogger(getClass());
|
||||
// Returns the first v6 interface ip out of a set of interfaces or null.
|
||||
// Checks all interfaces, and ignores v6 interface ips
|
||||
public Ip6Address getRelayAgentIPv6Address(Set<Interface> intfs) {
|
||||
for (Interface intf : intfs) {
|
||||
for (InterfaceIpAddress ip : intf.ipAddressesList()) {
|
||||
Ip6Address relayAgentIp = ip.ipAddress().getIp6Address();
|
||||
if (relayAgentIp != null) {
|
||||
return relayAgentIp;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the first interface ip from interface.
|
||||
*
|
||||
* @param iface interface of one connect point
|
||||
* @return the first interface IP; null if not exists an IP address in
|
||||
* these interfaces
|
||||
*/
|
||||
public Ip6Address getFirstIpFromInterface(Interface iface) {
|
||||
checkNotNull(iface, "Interface can't be null");
|
||||
return iface.ipAddressesList().stream()
|
||||
.map(InterfaceIpAddress::ipAddress)
|
||||
.filter(IpAddress::isIp6)
|
||||
.map(IpAddress::getIp6Address)
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* extract DHCP6 payload from dhcp6 relay message within relay-forwrd/reply.
|
||||
*
|
||||
* @param dhcp6 dhcp6 relay-reply or relay-foward
|
||||
* @return dhcp6Packet dhcp6 packet extracted from relay-message
|
||||
*/
|
||||
public DHCP6 dhcp6PacketFromRelayPacket(DHCP6 dhcp6) {
|
||||
|
||||
// extract the relay message if exist
|
||||
DHCP6 dhcp6Payload = dhcp6.getOptions().stream()
|
||||
.filter(opt -> opt instanceof Dhcp6RelayOption)
|
||||
.map(BasePacket::getPayload)
|
||||
.map(pld -> (DHCP6) pld)
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
if (dhcp6Payload == null) {
|
||||
// Can't find dhcp payload
|
||||
log.debug("Can't find dhcp6 payload from relay message");
|
||||
} else {
|
||||
log.debug("dhcp6 payload found from relay message {}", dhcp6Payload);
|
||||
}
|
||||
return dhcp6Payload;
|
||||
}
|
||||
|
||||
/**
|
||||
* find the leaf DHCP6 packet from multi-level relay packet.
|
||||
*
|
||||
* @param relayPacket dhcp6 relay packet
|
||||
* @return leafPacket non-relay dhcp6 packet
|
||||
*/
|
||||
public DHCP6 getDhcp6Leaf(DHCP6 relayPacket) {
|
||||
DHCP6 dhcp6Parent = relayPacket;
|
||||
DHCP6 dhcp6Child = null;
|
||||
|
||||
log.debug("getDhcp6Leaf entered.");
|
||||
while (dhcp6Parent != null) {
|
||||
dhcp6Child = dhcp6PacketFromRelayPacket(dhcp6Parent);
|
||||
if (dhcp6Child != null) {
|
||||
if (dhcp6Child.getMsgType() != DHCP6.MsgType.RELAY_FORW.value() &&
|
||||
dhcp6Child.getMsgType() != DHCP6.MsgType.RELAY_REPL.value()) {
|
||||
log.debug("leaf dhcp6 packet found.");
|
||||
break;
|
||||
} else {
|
||||
// found another relay, go for another loop
|
||||
dhcp6Parent = dhcp6Child;
|
||||
}
|
||||
} else {
|
||||
log.debug("Expected dhcp6 within relay pkt, but no dhcp6 leaf found.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
return dhcp6Child;
|
||||
}
|
||||
|
||||
/**
|
||||
* check if DHCP6 relay-reply is reply.
|
||||
*
|
||||
* @param relayPacket dhcp6 relay-reply
|
||||
* @return boolean relay-reply contains ack
|
||||
*/
|
||||
public boolean isDhcp6Reply(DHCP6 relayPacket) {
|
||||
DHCP6 leafDhcp6 = getDhcp6Leaf(relayPacket);
|
||||
if (leafDhcp6 != null) {
|
||||
if (leafDhcp6.getMsgType() == DHCP6.MsgType.REPLY.value()) {
|
||||
log.debug("isDhcp6Reply true.");
|
||||
return true; // must be directly connected
|
||||
} else {
|
||||
log.debug("isDhcp6Reply false. leaf dhcp6 is not replay. MsgType {}", leafDhcp6.getMsgType());
|
||||
}
|
||||
} else {
|
||||
log.debug("isDhcp6Reply false. Expected dhcp6 within relay pkt but not found.");
|
||||
}
|
||||
log.debug("isDhcp6Reply false.");
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* check if DHCP6 is release or relay-forward contains release.
|
||||
*
|
||||
* @param dhcp6Payload dhcp6 packet
|
||||
* @return boolean dhcp6 contains release
|
||||
*/
|
||||
public boolean isDhcp6Release(DHCP6 dhcp6Payload) {
|
||||
if (dhcp6Payload.getMsgType() == DHCP6.MsgType.RELEASE.value()) {
|
||||
log.debug("isDhcp6Release true.");
|
||||
return true; // must be directly connected
|
||||
} else {
|
||||
DHCP6 dhcp6Leaf = getDhcp6Leaf(dhcp6Payload);
|
||||
if (dhcp6Leaf != null) {
|
||||
if (dhcp6Leaf.getMsgType() == DHCP6.MsgType.RELEASE.value()) {
|
||||
log.debug("isDhcp6Release true. indirectlry connected");
|
||||
return true;
|
||||
} else {
|
||||
log.debug("leaf dhcp6 is not release. MsgType {}", dhcp6Leaf.getMsgType());
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
log.debug("isDhcp6Release false. dhcp6 is niether relay nor release.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* convert dhcp6 msgType to String.
|
||||
*
|
||||
* @param msgTypeVal msgType byte of dhcp6 packet
|
||||
* @return String string value of dhcp6 msg type
|
||||
*/
|
||||
public String getMsgTypeStr(byte msgTypeVal) {
|
||||
MsgType msgType = DHCP6.MsgType.getType(msgTypeVal);
|
||||
return DHCP6.MsgType.getMsgTypeStr(msgType);
|
||||
}
|
||||
|
||||
/**
|
||||
* find the string of dhcp6 leaf packets's msg type.
|
||||
*
|
||||
* @param directConnFlag boolean value indicating direct/indirect connection
|
||||
* @param dhcp6Packet dhcp6 packet
|
||||
* @return String string value of dhcp6 leaf packet msg type
|
||||
*/
|
||||
public String findLeafMsgType(boolean directConnFlag, DHCP6 dhcp6Packet) {
|
||||
if (directConnFlag) {
|
||||
return getMsgTypeStr(dhcp6Packet.getMsgType());
|
||||
} else {
|
||||
DHCP6 leafDhcp = getDhcp6Leaf(dhcp6Packet);
|
||||
if (leafDhcp != null) {
|
||||
return getMsgTypeStr(leafDhcp.getMsgType());
|
||||
} else {
|
||||
return "INVALID"; //DhcpRelayCounters.INVALID_PACKET;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* find the string of dhcp6 leaf packets's msg type.
|
||||
*
|
||||
* @param fromClient indicate from what side a packet is received
|
||||
* @param directConnFlag boolean value indicating direct/indirect connection
|
||||
* @param dhcp6Packet dhcp6 packet
|
||||
* @return String string value of dhcp6 leaf packet msg type
|
||||
*/
|
||||
public String findMsgType(boolean fromClient, boolean directConnFlag, DHCP6 dhcp6Packet) {
|
||||
if (fromClient) {
|
||||
return findLeafMsgType(directConnFlag, dhcp6Packet);
|
||||
} else {
|
||||
DHCP6 embeddedDhcp6 = dhcp6Packet.getOptions().stream()
|
||||
.filter(opt -> opt instanceof Dhcp6RelayOption)
|
||||
.map(BasePacket::getPayload)
|
||||
.map(pld -> (DHCP6) pld)
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
if (embeddedDhcp6 != null) {
|
||||
return findLeafMsgType(directConnFlag, embeddedDhcp6);
|
||||
} else {
|
||||
return "INVALID"; //DhcpRelayCounters.INVALID_PACKET;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determind if an Interface contains a vlan id.
|
||||
*
|
||||
* @param iface the Interface
|
||||
* @param vlanId the vlan id
|
||||
* @return true if the Interface contains the vlan id
|
||||
*/
|
||||
public boolean interfaceContainsVlan(Interface iface, VlanId vlanId) {
|
||||
if (vlanId.equals(VlanId.NONE)) {
|
||||
// untagged packet, check if vlan untagged or vlan native is not NONE
|
||||
return !iface.vlanUntagged().equals(VlanId.NONE) ||
|
||||
!iface.vlanNative().equals(VlanId.NONE);
|
||||
}
|
||||
// tagged packet, check if the interface contains the vlan
|
||||
return iface.vlanTagged().contains(vlanId);
|
||||
}
|
||||
|
||||
/**
|
||||
* the new class the contains Ethernet packet and destination port.
|
||||
*/
|
||||
public class InternalPacket {
|
||||
Ethernet packet;
|
||||
ConnectPoint destLocation;
|
||||
public InternalPacket(Ethernet newPacket, ConnectPoint newLocation) {
|
||||
packet = newPacket;
|
||||
destLocation = newLocation;
|
||||
}
|
||||
void setLocation(ConnectPoint newLocation) {
|
||||
destLocation = newLocation;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Check if the host is directly connected to the network or not.
|
||||
*
|
||||
* @param dhcp6Payload the dhcp6 payload
|
||||
* @return true if the host is directly connected to the network; false otherwise
|
||||
*/
|
||||
public boolean directlyConnected(DHCP6 dhcp6Payload) {
|
||||
log.debug("directlyConnected enters");
|
||||
|
||||
if (dhcp6Payload.getMsgType() != DHCP6.MsgType.RELAY_FORW.value() &&
|
||||
dhcp6Payload.getMsgType() != DHCP6.MsgType.RELAY_REPL.value()) {
|
||||
log.debug("directlyConnected true. MsgType {}", dhcp6Payload.getMsgType());
|
||||
|
||||
return true;
|
||||
}
|
||||
// Regardless of relay-forward or relay-replay, check if we see another relay message
|
||||
DHCP6 dhcp6Payload2 = dhcp6PacketFromRelayPacket(dhcp6Payload);
|
||||
if (dhcp6Payload2 != null) {
|
||||
if (dhcp6Payload.getMsgType() == DHCP6.MsgType.RELAY_FORW.value()) {
|
||||
log.debug("directlyConnected false. 1st realy-foward, 2nd MsgType {}", dhcp6Payload2.getMsgType());
|
||||
return false;
|
||||
} else {
|
||||
// relay-reply
|
||||
if (dhcp6Payload2.getMsgType() != DHCP6.MsgType.RELAY_REPL.value()) {
|
||||
log.debug("directlyConnected true. 2nd MsgType {}", dhcp6Payload2.getMsgType());
|
||||
return true; // must be directly connected
|
||||
} else {
|
||||
log.debug("directlyConnected false. 1st relay-reply, 2nd relay-reply MsgType {}",
|
||||
dhcp6Payload2.getMsgType());
|
||||
return false; // must be indirectly connected
|
||||
}
|
||||
}
|
||||
} else {
|
||||
log.debug("directlyConnected true.");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Check if a given server info has v6 ipaddress.
|
||||
*
|
||||
* @param serverInfo server info to check
|
||||
* @return true if server info has v6 ip address; false otherwise
|
||||
*/
|
||||
public boolean isServerIpEmpty(DhcpServerInfo serverInfo) {
|
||||
if (!serverInfo.getDhcpServerIp6().isPresent()) {
|
||||
log.warn("DhcpServerIp not available, use default DhcpServerIp {}",
|
||||
HexString.toHexString(serverInfo.getDhcpServerIp6().get().toOctets()));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean isConnectMacEmpty(DhcpServerInfo serverInfo, Set<Interface> clientInterfaces) {
|
||||
if (!serverInfo.getDhcpConnectMac().isPresent()) {
|
||||
log.warn("DHCP6 {} not yet resolved .. Aborting DHCP "
|
||||
+ "packet processing from client on port: {}",
|
||||
!serverInfo.getDhcpGatewayIp6().isPresent() ? "server IP " + serverInfo.getDhcpServerIp6()
|
||||
: "gateway IP " + serverInfo.getDhcpGatewayIp6(),
|
||||
clientInterfaces.iterator().next().connectPoint());
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean isRelayAgentIpFromCfgEmpty(DhcpServerInfo serverInfo, DeviceId receivedFromDevice) {
|
||||
if (!serverInfo.getRelayAgentIp6(receivedFromDevice).isPresent()) {
|
||||
log.warn("indirect connection: relayAgentIp NOT availale from config file! Use dynamic.");
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private Dhcp6Option getInterfaceIdIdOption(PacketContext context, Ethernet clientPacket) {
|
||||
String inPortString = "-" + context.inPacket().receivedFrom().toString() + ":";
|
||||
Dhcp6Option interfaceId = new Dhcp6Option();
|
||||
interfaceId.setCode(DHCP6.OptionCode.INTERFACE_ID.value());
|
||||
byte[] clientSoureMacBytes = clientPacket.getSourceMACAddress();
|
||||
byte[] inPortStringBytes = inPortString.getBytes();
|
||||
byte[] vlanIdBytes = new byte[2];
|
||||
vlanIdBytes[0] = (byte) (clientPacket.getVlanID() & 0xff);
|
||||
vlanIdBytes[1] = (byte) ((clientPacket.getVlanID() >> 8) & 0xff);
|
||||
byte[] interfaceIdBytes = new byte[clientSoureMacBytes.length +
|
||||
inPortStringBytes.length + vlanIdBytes.length];
|
||||
log.debug("Length: interfaceIdBytes {} clientSoureMacBytes {} inPortStringBytes {} vlan {}",
|
||||
interfaceIdBytes.length, clientSoureMacBytes.length, inPortStringBytes.length,
|
||||
vlanIdBytes.length);
|
||||
|
||||
System.arraycopy(clientSoureMacBytes, 0, interfaceIdBytes, 0, clientSoureMacBytes.length);
|
||||
System.arraycopy(inPortStringBytes, 0, interfaceIdBytes, clientSoureMacBytes.length,
|
||||
inPortStringBytes.length);
|
||||
System.arraycopy(vlanIdBytes, 0, interfaceIdBytes,
|
||||
clientSoureMacBytes.length + inPortStringBytes.length,
|
||||
vlanIdBytes.length);
|
||||
interfaceId.setData(interfaceIdBytes);
|
||||
interfaceId.setLength((short) interfaceIdBytes.length);
|
||||
log.debug("interfaceId write srcMac {} portString {}",
|
||||
HexString.toHexString(clientSoureMacBytes, ":"), inPortString);
|
||||
return interfaceId;
|
||||
}
|
||||
|
||||
private void addDhcp6OptionsFromClient(List<Dhcp6Option> options, byte[] dhcp6PacketByte,
|
||||
PacketContext context, Ethernet clientPacket) {
|
||||
Dhcp6Option relayMessage = new Dhcp6Option();
|
||||
relayMessage.setCode(DHCP6.OptionCode.RELAY_MSG.value());
|
||||
relayMessage.setLength((short) dhcp6PacketByte.length);
|
||||
relayMessage.setData(dhcp6PacketByte);
|
||||
options.add(relayMessage);
|
||||
// create interfaceId option
|
||||
Dhcp6Option interfaceId = getInterfaceIdIdOption(context, clientPacket);
|
||||
options.add(interfaceId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 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 {
|
||||
// Indirect case, replace destination to indirect dhcp server if exist
|
||||
// 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 (isRelayAgentIpFromCfgEmpty(serverInfo, receivedFromDevice)) {
|
||||
dhcp6Relay.setLinkAddress(relayAgentIp.toOctets());
|
||||
log.debug("indirect connection: relayAgentIp NOT availale from config file! Use dynamic. {}",
|
||||
HexString.toHexString(relayAgentIp.toOctets(), ":"));
|
||||
} else {
|
||||
dhcp6Relay.setLinkAddress(serverInfo.getRelayAgentIp6(receivedFromDevice).get().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;
|
||||
}
|
||||
|
||||
/**
|
||||
* build the DHCP6 solicit/request packet with gatewayip.
|
||||
*
|
||||
* @param directConnFlag flag indicating if packet is from direct client or not
|
||||
* @param serverInfo server to check its connect point
|
||||
* @return boolean true if serverInfo is found; false otherwise
|
||||
*/
|
||||
public boolean checkDhcpServerConnPt(boolean directConnFlag,
|
||||
DhcpServerInfo serverInfo) {
|
||||
if (serverInfo.getDhcpServerConnectPoint() == null) {
|
||||
log.warn("DHCP6 server connect point for {} connPt {}",
|
||||
directConnFlag ? "direct" : "indirect", serverInfo.getDhcpServerConnectPoint());
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -54,6 +54,8 @@ import org.onlab.packet.dhcp.Dhcp6IaPdOption;
|
||||
import org.onlab.packet.dhcp.Dhcp6IaAddressOption;
|
||||
import org.onlab.packet.dhcp.Dhcp6IaPrefixOption;
|
||||
import org.onlab.packet.dhcp.Dhcp6Option;
|
||||
import org.onlab.packet.dhcp.Dhcp6ClientIdOption;
|
||||
import org.onlab.packet.dhcp.Dhcp6Duid;
|
||||
import org.onosproject.net.ConnectPoint;
|
||||
import org.onosproject.TestApplicationId;
|
||||
import org.onosproject.cfg.ComponentConfigService;
|
||||
@ -358,6 +360,7 @@ public class DhcpRelayManagerTest {
|
||||
// properties
|
||||
Dictionary<String, Object> dictionary = createNiceMock(Dictionary.class);
|
||||
expect(dictionary.get("arpEnabled")).andReturn(true).anyTimes();
|
||||
expect(dictionary.get("dhcpPollInterval")).andReturn(120).anyTimes();
|
||||
ComponentContext context = createNiceMock(ComponentContext.class);
|
||||
expect(context.getProperties()).andReturn(dictionary).anyTimes();
|
||||
|
||||
@ -1233,6 +1236,14 @@ public class DhcpRelayManagerTest {
|
||||
iaAddressOption.setValidLifetime(1200);
|
||||
iaAddressOption.setLength((short) Dhcp6IaAddressOption.DEFAULT_LEN);
|
||||
|
||||
Dhcp6ClientIdOption clientIdOption = new Dhcp6ClientIdOption();
|
||||
Dhcp6Duid dhcp6Duip = new Dhcp6Duid();
|
||||
dhcp6Duip.setDuidType(Dhcp6Duid.DuidType.DUID_LLT);
|
||||
dhcp6Duip.setHardwareType((short) 0x01); // Ethernet
|
||||
dhcp6Duip.setDuidTime(1234);
|
||||
dhcp6Duip.setLinkLayerAddress(CLIENT_MAC.toBytes());
|
||||
clientIdOption.setDuid(dhcp6Duip);
|
||||
|
||||
Dhcp6IaNaOption iaNaOption = new Dhcp6IaNaOption();
|
||||
iaNaOption.setCode(DHCP6.OptionCode.IA_NA.value());
|
||||
iaNaOption.setIaId(0);
|
||||
@ -1265,6 +1276,7 @@ public class DhcpRelayManagerTest {
|
||||
dhcp6.setMsgType(msgType);
|
||||
List<Dhcp6Option> dhcp6Options = new ArrayList<Dhcp6Option>();
|
||||
dhcp6Options.add(iaNaOption);
|
||||
dhcp6Options.add(clientIdOption);
|
||||
dhcp6Options.add(iaPdOption);
|
||||
dhcp6.setOptions(dhcp6Options);
|
||||
|
||||
|
||||
@ -111,6 +111,38 @@ public class DHCP6 extends BasePacket {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
public static String getMsgTypeStr(final MsgType msgType) {
|
||||
switch (msgType) {
|
||||
case SOLICIT:
|
||||
return "SOLICIT";
|
||||
case ADVERTISE:
|
||||
return "ADVERTISE";
|
||||
case REQUEST:
|
||||
return "REQUEST";
|
||||
case CONFIRM:
|
||||
return "CONFIRM";
|
||||
case RENEW:
|
||||
return "RENEW";
|
||||
case REBIND:
|
||||
return "REBIND";
|
||||
case REPLY:
|
||||
return "REPLY";
|
||||
case RELEASE:
|
||||
return "RELEASE";
|
||||
case DECLINE:
|
||||
return "DECLINE";
|
||||
case RECONFIGURE:
|
||||
return "RECONFIGURE";
|
||||
case INFORMATION_REQUEST:
|
||||
return "INFORMATION_REQUEST";
|
||||
case RELAY_FORW:
|
||||
return "RELAY_FORW";
|
||||
case RELAY_REPL:
|
||||
return "RELAY_REPL";
|
||||
default:
|
||||
return "NULL";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user