ADD/REMOVE Option82
Change-Id: I51cfb92f4b2d07c5b588fd96ceb6a37afc6f8f38
diff --git a/src/main/java/org/opencord/dhcpl2relay/DhcpL2Relay.java b/src/main/java/org/opencord/dhcpl2relay/DhcpL2Relay.java
index a224b6d..cdffe4e 100755
--- a/src/main/java/org/opencord/dhcpl2relay/DhcpL2Relay.java
+++ b/src/main/java/org/opencord/dhcpl2relay/DhcpL2Relay.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2017-present Open Networking Laboratory
+ * 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.
@@ -16,6 +16,8 @@
package org.opencord.dhcpl2relay;
import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Lists;
+
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Deactivate;
@@ -23,17 +25,19 @@
import org.apache.felix.scr.annotations.Property;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.ReferenceCardinality;
-import org.onlab.packet.Ethernet;
-import org.onlab.packet.MacAddress;
+import org.onlab.packet.DeserializationException;
import org.onlab.packet.DHCP;
import org.onlab.packet.DHCPOption;
import org.onlab.packet.DHCPPacketType;
-import org.onlab.packet.Ip4Address;
+import org.onlab.packet.Ethernet;
import org.onlab.packet.IPv4;
+import org.onlab.packet.Ip4Address;
+import org.onlab.packet.MacAddress;
import org.onlab.packet.TpPort;
import org.onlab.packet.UDP;
import org.onlab.packet.VlanId;
-
+import org.opencord.dhcpl2relay.packet.DhcpEthernet;
+import org.opencord.dhcpl2relay.packet.DhcpOption82;
import org.onlab.util.Tools;
import org.onosproject.cfg.ComponentConfigService;
import org.onosproject.core.ApplicationId;
@@ -61,15 +65,16 @@
import org.opencord.sadis.SubscriberAndDeviceInformation;
import org.opencord.sadis.SubscriberAndDeviceInformationService;
-
import org.osgi.service.component.ComponentContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.nio.ByteBuffer;
import java.util.Dictionary;
-import java.util.Set;
+import java.util.List;
import java.util.Optional;
+import java.util.Set;
+import java.util.stream.Collectors;
import static org.onlab.packet.DHCP.DHCPOptionCode.OptionCode_MessageType;
import static org.onlab.packet.MacAddress.valueOf;
@@ -144,7 +149,9 @@
packetService.addProcessor(dhcpRelayPacketProcessor,
PacketProcessor.director(0));
requestDhcpPackets();
- modified(context);
+ if (context != null) {
+ modified(context);
+ }
log.info("DHCP-L2-RELAY Started");
}
@@ -163,6 +170,7 @@
@Modified
protected void modified(ComponentContext context) {
+
Dictionary<?, ?> properties = context.getProperties();
Boolean o = Tools.isPropertyEnabled(properties, "option82");
@@ -186,8 +194,15 @@
log.warn("Dhcp Server info not available");
return;
}
+ if (dhcpServerConnectPoint == null) {
+ dhcpServerConnectPoint = cfg.getDhcpServerConnectPoint();
+ requestDhcpPackets();
+ } else {
+ cancelDhcpPackets();
+ dhcpServerConnectPoint = cfg.getDhcpServerConnectPoint();
+ requestDhcpPackets();
+ }
- dhcpServerConnectPoint = cfg.getDhcpServerConnectPoint();
log.info("dhcp server connect point: " + dhcpServerConnectPoint);
}
@@ -224,16 +239,14 @@
.matchIPProtocol(IPv4.PROTOCOL_UDP)
.matchUdpSrc(TpPort.tpPort(UDP.DHCP_SERVER_PORT));
packetService.cancelPackets(selectorServer.build(),
- PacketPriority.CONTROL, appId,
- Optional.of(dhcpServerConnectPoint.deviceId()));
+ PacketPriority.CONTROL, appId, Optional.of(dhcpServerConnectPoint.deviceId()));
TrafficSelector.Builder selectorClient = DefaultTrafficSelector.builder()
.matchEthType(Ethernet.TYPE_IPV4)
.matchIPProtocol(IPv4.PROTOCOL_UDP)
.matchUdpSrc(TpPort.tpPort(UDP.DHCP_CLIENT_PORT));
packetService.cancelPackets(selectorClient.build(),
- PacketPriority.CONTROL, appId,
- Optional.of(dhcpServerConnectPoint.deviceId()));
+ PacketPriority.CONTROL, appId, Optional.of(dhcpServerConnectPoint.deviceId()));
}
}
@@ -263,7 +276,7 @@
private MacAddress relayAgentMacAddress(PacketContext context) {
- SubscriberAndDeviceInformation device = getDevice(context);
+ SubscriberAndDeviceInformation device = this.getDevice(context);
if (device == null) {
log.warn("Device not found for {}", context.inPacket().
receivedFrom());
@@ -275,12 +288,10 @@
private String nasPortId(PacketContext context) {
Port p = deviceService.getPort(context.inPacket().receivedFrom());
-
return p.annotations().value(AnnotationKeys.PORT_NAME);
}
private SubscriberAndDeviceInformation getSubscriber(PacketContext context) {
-
return subsService.get(nasPortId(context));
}
@@ -314,21 +325,28 @@
}
// process the packet and get the payload
- Ethernet packet = context.inPacket().parsed();
+ DhcpEthernet packet = null;
+ ByteBuffer byteBuffer = context.inPacket().unparsed();
+ try {
+ packet = DhcpEthernet.deserializer().deserialize(byteBuffer.array(), 0, byteBuffer.array().length);
+ } catch (DeserializationException e) {
+ log.warn("Unable to deserialize packet");
+ }
+
if (packet == null) {
log.warn("Packet is null");
return;
}
- //log.info("Got a packet of type {}", packet.getEtherType());
+ log.debug("Got a packet ", packet);
- if (packet.getEtherType() == Ethernet.TYPE_IPV4) {
+ if (packet.getEtherType() == DhcpEthernet.TYPE_IPV4) {
IPv4 ipv4Packet = (IPv4) packet.getPayload();
if (ipv4Packet.getProtocol() == IPv4.PROTOCOL_UDP) {
UDP udpPacket = (UDP) ipv4Packet.getPayload();
if (udpPacket.getSourcePort() == UDP.DHCP_CLIENT_PORT ||
- udpPacket.getSourcePort() == UDP.DHCP_SERVER_PORT) {
+ udpPacket.getSourcePort() == UDP.DHCP_SERVER_PORT) {
DHCP dhcpPayload = (DHCP) udpPacket.getPayload();
//This packet is dhcp.
processDhcpPacket(context, packet, dhcpPayload);
@@ -338,7 +356,7 @@
}
//forward the packet to ConnectPoint where the DHCP server is attached.
- private void forwardPacket(Ethernet packet) {
+ private void forwardPacket(DhcpEthernet packet) {
if (dhcpServerConnectPoint != null) {
TrafficTreatment t = DefaultTrafficTreatment.builder()
@@ -347,8 +365,8 @@
dhcpServerConnectPoint.deviceId(), t,
ByteBuffer.wrap(packet.serialize()));
if (log.isTraceEnabled()) {
- log.trace("Relaying packet to dhcp server {} at {}",
- packet, dhcpServerConnectPoint);
+ log.trace("Relaying packet to dhcp server {} at {}",
+ packet, dhcpServerConnectPoint);
}
packetService.emit(o);
} else {
@@ -357,7 +375,7 @@
}
//process the dhcp packet before sending to server
- private void processDhcpPacket(PacketContext context, Ethernet packet,
+ private void processDhcpPacket(PacketContext context, DhcpEthernet packet,
DHCP dhcpPayload) {
if (dhcpPayload == null) {
log.warn("DHCP payload is null");
@@ -365,6 +383,7 @@
}
DHCPPacketType incomingPacketType = null;
+
for (DHCPOption option : dhcpPayload.getOptions()) {
if (option.getCode() == OptionCode_MessageType.getValue()) {
byte[] data = option.getData();
@@ -372,75 +391,86 @@
}
}
log.info("Received DHCP Packet of type {}", incomingPacketType);
- log.trace("Processing Packet {}", packet);
switch (incomingPacketType) {
- case DHCPDISCOVER:
- Ethernet ethernetPacketDiscover =
- processDhcpPacketFromClient(context, packet);
- if (ethernetPacketDiscover != null) {
- forwardPacket(ethernetPacketDiscover);
- }
- break;
- case DHCPOFFER:
- //reply to dhcp client.
- Ethernet ethernetPacketOffer = processDhcpPacketFromServer(packet);
- if (ethernetPacketOffer != null) {
- sendReply(ethernetPacketOffer, dhcpPayload);
- }
- break;
- case DHCPREQUEST:
- Ethernet ethernetPacketRequest =
- processDhcpPacketFromClient(context, packet);
- if (ethernetPacketRequest != null) {
- forwardPacket(ethernetPacketRequest);
- }
- break;
- case DHCPACK:
- //reply to dhcp client.
- Ethernet ethernetPacketAck = processDhcpPacketFromServer(packet);
- if (ethernetPacketAck != null) {
- sendReply(ethernetPacketAck, dhcpPayload);
- }
- break;
- default:
- break;
+ case DHCPDISCOVER:
+ DhcpEthernet ethernetPacketDiscover =
+ processDhcpPacketFromClient(context, packet);
+ if (ethernetPacketDiscover != null) {
+ forwardPacket(ethernetPacketDiscover);
+ }
+ break;
+ case DHCPOFFER:
+ //reply to dhcp client.
+ DhcpEthernet ethernetPacketOffer = processDhcpPacketFromServer(packet);
+ if (ethernetPacketOffer != null) {
+ sendReply(ethernetPacketOffer, dhcpPayload);
+ }
+ break;
+ case DHCPREQUEST:
+ DhcpEthernet ethernetPacketRequest =
+ processDhcpPacketFromClient(context, packet);
+ if (ethernetPacketRequest != null) {
+ forwardPacket(ethernetPacketRequest);
+ }
+ break;
+ case DHCPACK:
+ //reply to dhcp client.
+ DhcpEthernet ethernetPacketAck = processDhcpPacketFromServer(packet);
+ if (ethernetPacketAck != null) {
+ sendReply(ethernetPacketAck, dhcpPayload);
+ }
+ break;
+ default:
+ break;
}
}
- private Ethernet processDhcpPacketFromClient(PacketContext context,
- Ethernet ethernetPacket) {
+ private DhcpEthernet processDhcpPacketFromClient(PacketContext context,
+ DhcpEthernet ethernetPacket) {
log.info("Processing packet from client");
MacAddress relayAgentMac = relayAgentMacAddress(context);
if (relayAgentMac == null) {
log.warn("RelayAgent MAC not found ");
-
return null;
}
- Ethernet etherReply = ethernetPacket;
+ DhcpEthernet etherReply = ethernetPacket;
IPv4 ipv4Packet = (IPv4) etherReply.getPayload();
UDP udpPacket = (UDP) ipv4Packet.getPayload();
DHCP dhcpPacket = (DHCP) udpPacket.getPayload();
- etherReply.setSourceMACAddress(relayAgentMac);
- etherReply.setDestinationMACAddress(dhcpConnectMac);
+ if (option82) {
+ SubscriberAndDeviceInformation entry = getSubscriber(context);
+ if (entry == null) {
+ log.info("Dropping packet as subscriber entry is not available");
+ return null;
+ }
+
+ DHCP dhcpPacketWithOption82 = addOption82(dhcpPacket, entry);
+ udpPacket.setPayload(dhcpPacketWithOption82);
+ }
+
+ ipv4Packet.setPayload(udpPacket);
+ etherReply.setPayload(ipv4Packet);
+ etherReply.setSourceMacAddress(relayAgentMac);
+ etherReply.setDestinationMacAddress(dhcpConnectMac);
etherReply.setVlanID(cTag(context).toShort());
- etherReply.setQinQTPID(Ethernet.TYPE_VLAN);
- etherReply.setQinQVID(sTag(context).toShort());
+ etherReply.setQinQtpid(DhcpEthernet.TYPE_QINQ);
+ etherReply.setQinQVid(sTag(context).toShort());
- log.info("Finished processing");
+ log.info("Finished processing packet");
return etherReply;
}
//build the DHCP offer/ack with proper client port.
- private Ethernet processDhcpPacketFromServer(Ethernet ethernetPacket) {
- log.warn("Processing DHCP packet from server");
+ private DhcpEthernet processDhcpPacketFromServer(DhcpEthernet ethernetPacket) {
+ log.info("Processing DHCP packet from server");
// get dhcp header.
- Ethernet etherReply = (Ethernet) ethernetPacket.clone();
+ DhcpEthernet etherReply = (DhcpEthernet) ethernetPacket.clone();
IPv4 ipv4Packet = (IPv4) etherReply.getPayload();
UDP udpPacket = (UDP) ipv4Packet.getPayload();
DHCP dhcpPayload = (DHCP) udpPacket.getPayload();
@@ -450,8 +480,8 @@
Set<Host> hosts = hostService.getHostsByMac(dstMac);
if (hosts == null || hosts.isEmpty()) {
log.warn("Cannot determine host for DHCP client: {}. Aborting "
- + "relay for dhcp packet from server {}",
- dstMac, ethernetPacket);
+ + "relay for dhcp packet from server {}",
+ dstMac, ethernetPacket);
return null;
} else if (hosts.size() > 1) {
// XXX redo to send reply to all hosts found
@@ -460,8 +490,8 @@
}
Host host = hosts.iterator().next();
- etherReply.setDestinationMACAddress(dstMac);
- etherReply.setQinQVID(Ethernet.VLAN_UNTAGGED);
+ etherReply.setDestinationMacAddress(dstMac);
+ etherReply.setQinQVid(Ethernet.VLAN_UNTAGGED);
etherReply.setPriorityCode(ethernetPacket.getPriorityCode());
etherReply.setVlanID((short) 0);
@@ -473,7 +503,7 @@
host.location().port()));
if (relayAgentIP == null) {
log.warn("Cannot determine relay agent Ipv4 addr for host {}. "
- + "Aborting relay for dhcp packet from server {}",
+ + "Aborting relay for dhcp packet from server {}",
host, ethernetPacket);
return null;
}
@@ -482,7 +512,11 @@
ipv4Packet.setDestinationAddress(dhcpPayload.getYourIPAddress());
udpPacket.setDestinationPort(UDP.DHCP_CLIENT_PORT);
- udpPacket.setPayload(dhcpPayload);
+ if (option82) {
+ udpPacket.setPayload(removeOption82(dhcpPayload));
+ } else {
+ udpPacket.setPayload(dhcpPayload);
+ }
ipv4Packet.setPayload(udpPacket);
etherReply.setPayload(ipv4Packet);
@@ -491,7 +525,7 @@
}
//send the response to the requester host.
- private void sendReply(Ethernet ethPacket, DHCP dhcpPayload) {
+ private void sendReply(DhcpEthernet ethPacket, DHCP dhcpPayload) {
MacAddress descMac = valueOf(dhcpPayload.getClientHardwareAddress());
Host host = hostService.getHostsByMac(descMac).stream().findFirst().orElse(null);
@@ -506,13 +540,39 @@
log.trace("Relaying packet to dhcp client {}", ethPacket);
}
packetService.emit(o);
- log.error("DHCP Packet sent to {}", host.location());
+ log.info("DHCP Packet sent to {}", host.location());
} else {
- log.info("Dropping DHCP packet because can't find host for {}", descMac);
+ log.error("Dropping DHCP packet because can't find host for {}", descMac);
}
}
}
+ private DHCP addOption82(DHCP dhcpPacket, SubscriberAndDeviceInformation entry) {
+ log.debug("option82data {} ", entry);
+
+ List<DHCPOption> options = Lists.newArrayList(dhcpPacket.getOptions());
+ DhcpOption82 option82 = new DhcpOption82();
+ option82.setAgentCircuitId(entry.circuitId());
+ option82.setAgentRemoteId(entry.remoteId());
+ DHCPOption option = new DHCPOption()
+ .setCode(DHCP.DHCPOptionCode.OptionCode_CircuitID.getValue())
+ .setData(option82.toByteArray())
+ .setLength(option82.length());
+
+ options.add(options.size() - 1, option);
+ dhcpPacket.setOptions(options);
+ return dhcpPacket;
+
+ }
+
+ private DHCP removeOption82(DHCP dhcpPacket) {
+ List<DHCPOption> options = dhcpPacket.getOptions();
+ List<DHCPOption> newoptions = options.stream()
+ .filter(option -> option.getCode() != DHCP.DHCPOptionCode.OptionCode_CircuitID.getValue())
+ .collect(Collectors.toList());
+
+ return dhcpPacket.setOptions(newoptions);
+ }
/**
* Listener for network config events.
*/
@@ -529,4 +589,7 @@
}
}
}
+
+
+
}