use of org.onlab.packet.Ethernet in project onos by opennetworkinglab.
the class K8sRoutingArpHandler method processArpPacket.
private void processArpPacket(PacketContext context, Ethernet ethernet) {
DeviceId deviceId = context.inPacket().receivedFrom().deviceId();
if (!allK8sDevices(k8sNodeService, k8sHostService).contains(deviceId)) {
return;
}
ARP arp = (ARP) ethernet.getPayload();
if (arp.getOpCode() == ARP.OP_REPLY) {
IpAddress spa = Ip4Address.valueOf(arp.getSenderProtocolAddress());
MacAddress sha = MacAddress.valueOf(arp.getSenderHardwareAddress());
log.info("ARP reply from ip: {}, mac: {}", spa, sha);
Set<IpAddress> gatewayIps = k8sNodeService.completeNodes().stream().map(K8sNode::extGatewayIp).collect(Collectors.toSet());
if (!gatewayIps.contains(spa)) {
return;
}
log.info("ARP reply from external gateway ip: {}, mac: {}", spa, sha);
k8sNodeService.completeNodes().stream().filter(n -> n.extGatewayMac() == null).forEach(n -> {
K8sNode updated = n.updateExtGatewayMac(sha);
k8sNodeService.updateNode(updated);
});
}
}
use of org.onlab.packet.Ethernet in project onos by opennetworkinglab.
the class K8sSwitchingArpHandler method processArpRequest.
private void processArpRequest(PacketContext context, Ethernet ethPacket) {
ARP arpPacket = (ARP) ethPacket.getPayload();
K8sPort srcK8sPort = k8sNetworkService.ports().stream().filter(p -> p.macAddress().equals(ethPacket.getSourceMAC())).findAny().orElse(null);
PortNumber srcPortNum = context.inPacket().receivedFrom().port();
DeviceId srcDeviceId = context.inPacket().receivedFrom().deviceId();
boolean isEntryPort = false;
for (K8sNode node : k8sNodeService.completeNodes()) {
if (srcDeviceId.equals(node.intgBridge()) && srcPortNum.equals(node.intgEntryPortNum())) {
isEntryPort = true;
}
}
// integration bridge entry port, we simply ignore the ARP request...
if (srcK8sPort == null && !isEntryPort) {
log.warn("Failed to find source port(MAC:{})", ethPacket.getSourceMAC());
return;
}
IpAddress targetIp = Ip4Address.valueOf(arpPacket.getTargetProtocolAddress());
// look up the MAC address from regular k8s ports
MacAddress replyMac = k8sNetworkService.ports().stream().filter(p -> p.ipAddress().equals(targetIp)).map(K8sPort::macAddress).findAny().orElse(null);
// look up the MAC address from special integration entry port (e.g., LOCAL, k8s-int-os)
for (K8sNetwork network : k8sNetworkService.networks()) {
if (network.gatewayIp().equals(targetIp)) {
K8sNode node = k8sNodeService.node(network.name());
replyMac = node.intgEntryPortMac();
}
}
if (replyMac == null) {
String cidr = k8sNetworkService.networks().stream().map(K8sNetwork::cidr).findAny().orElse(null);
if (cidr != null) {
String unshiftedIp = unshiftIpDomain(targetIp.toString(), SHIFTED_IP_PREFIX, cidr);
replyMac = k8sNetworkService.ports().stream().filter(p -> p.ipAddress().equals(IpAddress.valueOf(unshiftedIp))).map(K8sPort::macAddress).findAny().orElse(null);
}
}
if (replyMac == null) {
Set<String> serviceIps = k8sServiceService.services().stream().map(s -> s.getSpec().getClusterIP()).collect(Collectors.toSet());
if (serviceIps.contains(targetIp.toString())) {
replyMac = MacAddress.valueOf(SERVICE_FAKE_MAC_STR);
}
}
if (replyMac == null) {
if (targetIp.toString().startsWith(NODE_IP_PREFIX)) {
String targetIpPrefix = targetIp.toString().split("\\.")[1];
String nodePrefix = NODE_IP_PREFIX + "." + targetIpPrefix;
String origNodeCidr = k8sNodeService.completeNodes().stream().map(n -> n.nodeIp().toString()).findAny().orElse(null);
if (origNodeCidr != null) {
String origNodeIp = unshiftIpDomain(targetIp.toString(), nodePrefix, origNodeCidr);
IpPrefix k8sNodeIpCidr = IpPrefix.valueOf(IpAddress.valueOf(origNodeCidr), 24);
SubnetUtils k8sNodeSubnet = new SubnetUtils(k8sNodeIpCidr.toString());
String k8sNodeGateway = getGatewayIp(k8sNodeIpCidr.toString()).toString();
String seekIp = "";
if (!k8sNodeSubnet.getInfo().isInRange(origNodeIp)) {
replyMac = extHostMacStore.asJavaMap().get(IpAddress.valueOf(k8sNodeGateway));
seekIp = k8sNodeGateway;
} else {
replyMac = extHostMacStore.asJavaMap().get(IpAddress.valueOf(origNodeIp));
seekIp = origNodeIp;
}
// we need to manually learn their MAC addresses
if (replyMac == null) {
ConnectPoint cp = context.inPacket().receivedFrom();
K8sNode k8sNode = k8sNodeService.node(cp.deviceId());
if (k8sNode != null) {
// we use fake IP and MAC address as a source to
// query destination MAC address
setArpRequest(MacAddress.valueOf(NODE_FAKE_MAC_STR).toBytes(), IpAddress.valueOf(NODE_FAKE_IP_STR).toOctets(), IpAddress.valueOf(seekIp).toOctets(), k8sNode);
context.block();
return;
}
}
}
}
}
if (replyMac == null) {
replyMac = MacAddress.valueOf(gatewayMac);
}
Ethernet ethReply = ARP.buildArpReply(targetIp.getIp4Address(), replyMac, ethPacket);
TrafficTreatment treatment = DefaultTrafficTreatment.builder().setOutput(context.inPacket().receivedFrom().port()).build();
packetService.emit(new DefaultOutboundPacket(context.inPacket().receivedFrom().deviceId(), treatment, ByteBuffer.wrap(ethReply.serialize())));
context.block();
}
use of org.onlab.packet.Ethernet in project onos by opennetworkinglab.
the class DhcpManagerTest method testRequest.
/**
* Tests the response to a DHCP Request Packet.
*/
@Test
public void testRequest() {
Ethernet reply = constructDhcpPacket(DHCP.MsgType.DHCPREQUEST);
sendPacket(reply);
}
use of org.onlab.packet.Ethernet in project onos by opennetworkinglab.
the class Dhcp4HandlerImpl method processLeaseQueryFromServer.
/**
* 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 processLeaseQueryFromServer(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 = null;
MacAddress destinationMac = MacAddress.valueOf(dhcpPayload.getClientHardwareAddress());
if (!learnRouteFromLeasequery) {
int giaddr = ipv4Packet.getDestinationAddress();
IpAddress destinationAddress = Ip4Address.valueOf(giaddr);
log.debug("DHCPLEASEQUERYRESP giaddr: {}({})", giaddr, destinationAddress);
Host destinationHost = hostService.getHostsByIp(destinationAddress).stream().findFirst().orElse(null);
if (destinationHost != null) {
destinationMac = destinationHost.mac();
log.trace("DHCPLEASEQUERYRESP destination mac is: {}", destinationMac);
ConnectPoint destinationLocation = destinationHost.location();
log.trace("Lookup for client interface by destination location {}", destinationLocation);
clientInterface = interfaceService.getInterfacesByPort(destinationLocation).stream().filter(iface -> interfaceContainsVlan(iface, VlanId.vlanId(etherReply.getVlanID()))).findFirst().orElse(null);
log.trace("Found Host {} by ip {}", destinationHost, destinationAddress);
log.debug("DHCPLEASEQUERYRESP Client interface: {}", (clientInterface != null ? clientInterface : "not resolved"));
}
} else {
clientInterface = getClientInterface(ethernetPacket, dhcpPayload).orElse(null);
}
if (clientInterface == null) {
log.warn("Cannot find the interface for the DHCP {}", dhcpPayload);
return null;
}
VlanId vlanId;
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) && learnRouteFromLeasequery) {
// if client is indirectly connected, try use next hop mac address
MacAddress macAddress = MacAddress.valueOf(dhcpPayload.getClientHardwareAddress());
HostId hostId = HostId.hostId(macAddress, vlanId);
DhcpRecord record = dhcpRelayStore.getDhcpRecord(hostId).orElse(null);
if (record != null) {
// if next hop can be found, use mac address of next hop
Optional<MacAddress> nextHop = record.nextHopTemp();
if (!nextHop.isPresent()) {
nextHop = record.nextHop();
}
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(destinationMac);
}
udpPacket.setSourcePort(UDP.DHCP_SERVER_PORT);
if (directlyConnected(dhcpPayload)) {
udpPacket.setDestinationPort(UDP.DHCP_CLIENT_PORT);
} else {
udpPacket.setDestinationPort(UDP.DHCP_SERVER_PORT);
}
udpPacket.setPayload(dhcpPayload);
ipv4Packet.setPayload(udpPacket);
etherReply.setPayload(ipv4Packet);
udpPacket.resetChecksum();
return InternalPacket.internalPacket(etherReply, clientInterface.connectPoint());
}
use of org.onlab.packet.Ethernet in project onos by opennetworkinglab.
the class Dhcp4HandlerImpl method processDhcpPacketFromClient.
/**
* Build the DHCP discover/request packet with gateway IP(unicast packet).
*
* @param context the packet context
* @param ethernetPacket the ethernet payload to process
* @return processed packet
*/
private List<InternalPacket> processDhcpPacketFromClient(PacketContext context, Ethernet ethernetPacket, Set<Interface> clientInterfaces) {
ConnectPoint receivedFrom = context.inPacket().receivedFrom();
DeviceId receivedFromDevice = receivedFrom.deviceId();
Ip4Address relayAgentIp = null;
relayAgentIp = Dhcp4HandlerUtil.getRelayAgentIPv4Address(clientInterfaces);
MacAddress relayAgentMac = clientInterfaces.iterator().next().mac();
if (relayAgentIp == null || relayAgentMac == null) {
log.warn("Missing DHCP relay agent interface Ipv4 addr config for " + "packet from client on port: {}. Aborting packet processing", clientInterfaces.iterator().next().connectPoint());
return Lists.newArrayList();
}
log.debug("Multi DHCP V4 processDhcpPacketFromClient on port {}", clientInterfaces.iterator().next().connectPoint());
// get dhcp header.
Ethernet etherReply = (Ethernet) ethernetPacket.clone();
IPv4 ipv4Packet = (IPv4) etherReply.getPayload();
UDP udpPacket = (UDP) ipv4Packet.getPayload();
DHCP dhcpPacket = (DHCP) udpPacket.getPayload();
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 Lists.newArrayList();
}
boolean isDirectlyConnected = directlyConnected(dhcpPacket);
boolean directConnFlag = directlyConnected(dhcpPacket);
// Multi DHCP Start
ConnectPoint clientConnectionPoint = context.inPacket().receivedFrom();
VlanId vlanIdInUse = VlanId.vlanId(ethernetPacket.getVlanID());
Interface clientInterface = interfaceService.getInterfacesByPort(clientConnectionPoint).stream().filter(iface -> Dhcp4HandlerUtil.interfaceContainsVlan(iface, vlanIdInUse)).findFirst().orElse(null);
List<InternalPacket> internalPackets = new ArrayList<>();
List<DhcpServerInfo> serverInfoList = findValidServerInfo(directConnFlag);
List<DhcpServerInfo> copyServerInfoList = new ArrayList<DhcpServerInfo>(serverInfoList);
boolean serverFound = false;
for (DhcpServerInfo serverInfo : copyServerInfoList) {
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.debug("Can't get server interface with host info resolved, ignore serverInfo {} serverInfoList {}", serverInfo, serverInfoList);
continue;
}
Interface serverInterface = getServerInterface(newServerInfo);
if (serverInterface == null) {
log.debug("Can't get server interface, ignore for serverInfo {}, serverInfoList {}", serverInfo, serverInfoList);
continue;
}
Ip4Address ipFacingServer = getFirstIpFromInterface(serverInterface);
MacAddress macFacingServer = serverInterface.mac();
log.debug("Interfacing server {} Mac : {} ", ipFacingServer, macFacingServer);
if (ipFacingServer == null || macFacingServer == null) {
log.debug("No IP address for server Interface {}", serverInterface);
continue;
}
serverFound = true;
log.debug("Server Info Found {}", serverInfo.getDhcpConnectMac());
etherReply.setSourceMACAddress(macFacingServer);
// 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(newServerInfo.getDhcpConnectVlan().get().toShort());
}
ipv4Packet.setSourceAddress(ipFacingServer.toInt());
ipv4Packet.setDestinationAddress(newServerInfo.getDhcpServerIp4().get().toInt());
log.debug("Directly connected {}", isDirectlyConnected);
log.debug("DHCP server IP: {}", newServerInfo.getDhcpServerIp4().get());
if (isDirectlyConnected) {
log.debug("Default DHCP server IP: {}", newServerInfo.getDhcpServerIp4().get());
if (newServerInfo.getDhcpConnectMac().isPresent()) {
etherReply.setDestinationMACAddress(newServerInfo.getDhcpConnectMac().get());
}
if (newServerInfo.getDhcpConnectVlan().isPresent()) {
etherReply.setVlanID(newServerInfo.getDhcpConnectVlan().get().toShort());
}
ipv4Packet.setDestinationAddress(newServerInfo.getDhcpServerIp4().get().toInt());
ConnectPoint inPort = context.inPacket().receivedFrom();
VlanId vlanId = VlanId.vlanId(ethernetPacket.getVlanID());
// add connected in port and vlan
CircuitId cid = new CircuitId(inPort.toString(), vlanId);
byte[] circuitId = cid.serialize();
DhcpOption circuitIdSubOpt = new DhcpOption();
circuitIdSubOpt.setCode(CIRCUIT_ID.getValue()).setLength((byte) circuitId.length).setData(circuitId);
DhcpRelayAgentOption newRelayAgentOpt = new DhcpRelayAgentOption();
newRelayAgentOpt.setCode(OptionCode_CircuitID.getValue());
newRelayAgentOpt.addSubOption(circuitIdSubOpt);
// Removes END option first
List<DhcpOption> options = dhcpPacket.getOptions().stream().filter(opt -> opt.getCode() != OptionCode_END.getValue()).collect(Collectors.toList());
// push relay agent option
options.add(newRelayAgentOpt);
// make sure option 255(End) is the last option
DhcpOption endOption = new DhcpOption();
endOption.setCode(OptionCode_END.getValue());
options.add(endOption);
dhcpPacket.setOptions(options);
relayAgentIp = serverInfo.getRelayAgentIp4(receivedFromDevice).orElse(null);
// Sets relay agent IP
int effectiveRelayAgentIp = relayAgentIp != null ? relayAgentIp.toInt() : clientInterfaceIp.toInt();
dhcpPacket.setGatewayIPAddress(effectiveRelayAgentIp);
log.debug("In Default, Relay Agent IP {}", effectiveRelayAgentIp);
} else {
if (!newServerInfo.getDhcpServerIp4().isPresent()) {
// do nothing
} else if (!newServerInfo.getDhcpConnectMac().isPresent()) {
continue;
} else {
relayAgentIp = newServerInfo.getRelayAgentIp4(receivedFromDevice).orElse(null);
// Sets relay agent IP
int effectiveRelayAgentIp = relayAgentIp != null ? relayAgentIp.toInt() : clientInterfaceIp.toInt();
Ip4Address effectiveRealRealyAgentIP = relayAgentIp != null ? relayAgentIp : clientInterfaceIp;
dhcpPacket.setGatewayIPAddress(effectiveRelayAgentIp);
ipv4Packet.setSourceAddress(effectiveRealRealyAgentIP.toInt());
log.debug("Source IP address set as relay agent IP with value: {}", effectiveRealRealyAgentIP);
}
}
// 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);
InternalPacket internalPacket = InternalPacket.internalPacket(etherReply, serverInfo.getDhcpServerConnectPoint().get());
internalPackets.add(internalPacket);
}
if (!serverFound) {
log.warn("ProcessDhcp4PacketFromClient No Server Found");
}
return internalPackets;
}
Aggregations