use of org.onlab.packet.IPv4 in project onos by opennetworkinglab.
the class DhcpManagerTest method constructDhcpPacket.
/**
* Constructs an Ethernet packet containing a DHCP Payload.
* @param packetType DHCP Message Type
* @return Ethernet packet
*/
private Ethernet constructDhcpPacket(DHCP.MsgType packetType) {
// Ethernet Frame.
Ethernet ethReply = new Ethernet();
ethReply.setSourceMACAddress(CLIENT1_HOST.mac());
ethReply.setDestinationMACAddress(MacAddress.BROADCAST);
ethReply.setEtherType(Ethernet.TYPE_IPV4);
ethReply.setVlanID((short) 2);
// IP Packet
IPv4 ipv4Reply = new IPv4();
ipv4Reply.setSourceAddress(0);
ipv4Reply.setDestinationAddress(BROADCAST.toInt());
ipv4Reply.setTtl((byte) 127);
// UDP Datagram.
UDP udpReply = new UDP();
udpReply.setSourcePort((byte) UDP.DHCP_CLIENT_PORT);
udpReply.setDestinationPort((byte) UDP.DHCP_SERVER_PORT);
// DHCP Payload.
DHCP dhcpReply = new DHCP();
dhcpReply.setOpCode(DHCP.OPCODE_REQUEST);
dhcpReply.setYourIPAddress(0);
dhcpReply.setServerIPAddress(0);
dhcpReply.setTransactionId(TRANSACTION_ID);
dhcpReply.setClientHardwareAddress(CLIENT1_HOST.mac().toBytes());
dhcpReply.setHardwareType(DHCP.HWTYPE_ETHERNET);
dhcpReply.setHardwareAddressLength((byte) 6);
// DHCP Options.
DhcpOption option = new DhcpOption();
List<DhcpOption> optionList = new ArrayList<>();
// DHCP Message Type.
option.setCode(DHCP.DHCPOptionCode.OptionCode_MessageType.getValue());
option.setLength((byte) 1);
byte[] optionData = { (byte) packetType.getValue() };
option.setData(optionData);
optionList.add(option);
// DHCP Requested IP.
option = new DhcpOption();
option.setCode(DHCP.DHCPOptionCode.OptionCode_RequestedIP.getValue());
option.setLength((byte) 4);
optionData = Ip4Address.valueOf(EXPECTED_IP).toOctets();
option.setData(optionData);
optionList.add(option);
// End Option.
option = new DhcpOption();
option.setCode(DHCP.DHCPOptionCode.OptionCode_END.getValue());
option.setLength((byte) 1);
optionList.add(option);
dhcpReply.setOptions(optionList);
udpReply.setPayload(dhcpReply);
ipv4Reply.setPayload(udpReply);
ethReply.setPayload(ipv4Reply);
return ethReply;
}
use of org.onlab.packet.IPv4 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());
}
use of org.onlab.packet.IPv4 in project onos by opennetworkinglab.
the class Dhcp4HandlerImpl method processLeaseQueryFromAgent.
/**
* Do a basic routing for a packet from client (used for LQ processing).
*
* @param context the packet context
* @param ethernetPacket the ethernet payload to process
* @return processed packet
*/
private List<InternalPacket> processLeaseQueryFromAgent(PacketContext context, Ethernet ethernetPacket) {
ConnectPoint receivedFrom = context.inPacket().receivedFrom();
DeviceId receivedFromDevice = receivedFrom.deviceId();
// get dhcp header.
Ethernet etherReply = (Ethernet) ethernetPacket.clone();
IPv4 ipv4Packet = (IPv4) etherReply.getPayload();
UDP udpPacket = (UDP) ipv4Packet.getPayload();
DHCP dhcpPacket = (DHCP) udpPacket.getPayload();
Ip4Address relayAgentIp;
Ip4Address clientInterfaceIp = interfaceService.getInterfacesByPort(context.inPacket().receivedFrom()).stream().map(Interface::ipAddressesList).flatMap(Collection::stream).map(InterfaceIpAddress::ipAddress).filter(IpAddress::isIp4).map(IpAddress::getIp4Address).findFirst().orElse(null);
if (clientInterfaceIp == null) {
log.warn("Can't find interface IP for client interface for port {}", context.inPacket().receivedFrom());
return null;
}
boolean isDirectlyConnected = directlyConnected(dhcpPacket);
boolean directConnFlag = directlyConnected(dhcpPacket);
// Multi DHCP Start
List<InternalPacket> internalPackets = new ArrayList<>();
List<DhcpServerInfo> serverInfoList = findValidServerInfo(directConnFlag);
List<DhcpServerInfo> copyServerInfoList = new ArrayList<>(serverInfoList);
for (DhcpServerInfo serverInfo : copyServerInfoList) {
// get dhcp header.
etherReply = (Ethernet) ethernetPacket.clone();
ipv4Packet = (IPv4) etherReply.getPayload();
udpPacket = (UDP) ipv4Packet.getPayload();
dhcpPacket = (DHCP) udpPacket.getPayload();
if (!checkDhcpServerConnPt(directConnFlag, serverInfo)) {
log.warn("Can't get server connect point, ignore");
continue;
}
DhcpServerInfo newServerInfo = getHostInfoForServerInfo(serverInfo, serverInfoList);
if (newServerInfo == null) {
log.warn("Can't get server interface with host info resolved, ignore");
continue;
}
Interface serverInterface = getServerInterface(newServerInfo);
if (serverInterface == null) {
log.warn("Can't get server interface, ignore");
continue;
}
Ip4Address ipFacingServer = getFirstIpFromInterface(serverInterface);
MacAddress macFacingServer = serverInterface.mac();
if (ipFacingServer == null || macFacingServer == null) {
log.warn("No IP address for server Interface {}", serverInterface);
continue;
}
etherReply.setSourceMACAddress(macFacingServer);
etherReply.setDestinationMACAddress(newServerInfo.getDhcpConnectMac().get());
etherReply.setVlanID(newServerInfo.getDhcpConnectVlan().get().toShort());
ipv4Packet.setSourceAddress(ipFacingServer.toInt());
ipv4Packet.setDestinationAddress(newServerInfo.getDhcpServerIp4().get().toInt());
if (isDirectlyConnected) {
// set default info and replace with indirect if available later on.
if (newServerInfo.getDhcpConnectMac().isPresent()) {
etherReply.setDestinationMACAddress(newServerInfo.getDhcpConnectMac().get());
}
if (newServerInfo.getDhcpConnectVlan().isPresent()) {
etherReply.setVlanID(serverInfo.getDhcpConnectVlan().get().toShort());
}
if (learnRouteFromLeasequery) {
relayAgentIp = newServerInfo.getRelayAgentIp4(receivedFromDevice).orElse(null);
// Sets relay agent IP
int effectiveRelayAgentIp = relayAgentIp != null ? relayAgentIp.toInt() : clientInterfaceIp.toInt();
dhcpPacket.setGatewayIPAddress(effectiveRelayAgentIp);
}
} else {
if (!newServerInfo.getDhcpServerIp4().isPresent()) {
// do nothing
} else if (!newServerInfo.getDhcpConnectMac().isPresent()) {
continue;
} else if (learnRouteFromLeasequery) {
relayAgentIp = newServerInfo.getRelayAgentIp4(receivedFromDevice).orElse(null);
// Sets relay agent IP
int effectiveRelayAgentIp = relayAgentIp != null ? relayAgentIp.toInt() : clientInterfaceIp.toInt();
dhcpPacket.setGatewayIPAddress(effectiveRelayAgentIp);
log.debug("Relay Agent IP {}", relayAgentIp);
}
log.trace("Indirect");
}
// Remove broadcast flag
dhcpPacket.setFlags((short) 0);
udpPacket.setPayload(dhcpPacket);
// As a DHCP relay, the source port should be server port( instead
// of client port.
udpPacket.setSourcePort(UDP.DHCP_SERVER_PORT);
udpPacket.setDestinationPort(UDP.DHCP_SERVER_PORT);
ipv4Packet.setPayload(udpPacket);
ipv4Packet.setTtl((byte) 64);
etherReply.setPayload(ipv4Packet);
udpPacket.resetChecksum();
// //return etherReply;
InternalPacket internalPacket = InternalPacket.internalPacket(etherReply, newServerInfo.getDhcpServerConnectPoint().get());
internalPackets.add(internalPacket);
}
log.debug("num of processLeaseQueryFromAgent packets to send is: {}", internalPackets.size());
return internalPackets;
}
use of org.onlab.packet.IPv4 in project onos by opennetworkinglab.
the class DhcpRelayManagerTest method testWithRelayAgentConfig.
@Test
public void testWithRelayAgentConfig() throws DeserializationException {
manager.v4Handler.setDefaultDhcpServerConfigs(ImmutableList.of(new MockDhcpServerConfig(RELAY_AGENT_IP)));
manager.v4Handler.setIndirectDhcpServerConfigs(ImmutableList.of(new MockDhcpServerConfig(RELAY_AGENT_IP)));
packetService.processPacket(new TestDhcpRequestPacketContext(CLIENT2_MAC, CLIENT2_VLAN, CLIENT2_CP, INTERFACE_IP.ipAddress().getIp4Address(), true));
assertAfter(PKT_PROCESSING_MS, () -> assertNotNull(packetService.emittedPacket));
OutboundPacket outPacket = packetService.emittedPacket;
byte[] outData = outPacket.data().array();
Ethernet eth = Ethernet.deserializer().deserialize(outData, 0, outData.length);
IPv4 ip = (IPv4) eth.getPayload();
UDP udp = (UDP) ip.getPayload();
DHCP dhcp = (DHCP) udp.getPayload();
assertAfter(PKT_PROCESSING_MS, () -> assertEquals(RELAY_AGENT_IP.toInt(), dhcp.getGatewayIPAddress()));
}
use of org.onlab.packet.IPv4 in project trellis-control by opennetworkinglab.
the class IcmpHandlerTest method testPing4RemoteGatewaySamePair.
// Ping to a gateway attached only to the pair leaf (routing through spine)
@Test
public void testPing4RemoteGatewaySamePair() {
// Expected behavior
expect(segmentRoutingManager.deviceService.isAvailable(LOCAL_LEAF1)).andReturn(true).times(1);
expect(segmentRoutingManager.deviceService.isAvailable(LOCAL_LEAF2)).andReturn(true).times(1);
replay(segmentRoutingManager.deviceService);
// Process
icmpHandler.processIcmp(ETH_REQ_IPV4_SAME, CP2025);
// Verify packet-out
Ethernet ethernet = packetService.getEthernetPacket(ETH_REQ_IPV4_SAME.getSourceMAC());
assertNotNull(ethernet);
assertThat(ethernet.getSourceMAC(), is(ETH_REQ_IPV4_SAME.getDestinationMAC()));
assertThat(ethernet.getDestinationMAC(), is(ETH_REQ_IPV4_SAME.getSourceMAC()));
assertTrue(ethernet.getPayload() instanceof MPLS);
MPLS mpls = (MPLS) ethernet.getPayload();
assertThat(mpls.getLabel(), is(LOCAL_LEAF1_SID4));
assertTrue(mpls.getPayload() instanceof IPv4);
IPv4 ip = (IPv4) mpls.getPayload();
assertThat(ip.getSourceAddress(), is(DST_IPV4_SAME.toInt()));
assertThat(ip.getDestinationAddress(), is(SRC_IPV41.toInt()));
assertTrue(ip.getPayload() instanceof ICMP);
ICMP icmp = (ICMP) ip.getPayload();
assertThat(icmp.getIcmpType(), is(TYPE_ECHO_REPLY));
assertThat(icmp.getIcmpCode(), is(CODE_ECHO_REPLY));
// Verify behavior
verify(segmentRoutingManager.deviceService);
}
Aggregations