*/
package org.opendaylight.vpnservice.dhcpservice;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.math.BigInteger;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.List;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+import org.apache.commons.lang3.tuple.ImmutablePair;
+import org.apache.commons.net.util.SubnetUtils;
+import org.apache.commons.net.util.SubnetUtils.SubnetInfo;
+import org.opendaylight.controller.liblldp.EtherTypes;
+import org.opendaylight.controller.liblldp.NetUtils;
+import org.opendaylight.controller.liblldp.PacketException;
import org.opendaylight.controller.md.sal.binding.api.DataBroker;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.PacketReceived;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.vpnservice.dhcpservice.api.DHCP;
+import org.opendaylight.vpnservice.dhcpservice.api.DHCPConstants;
+import org.opendaylight.vpnservice.dhcpservice.api.DHCPMConstants;
+import org.opendaylight.vpnservice.dhcpservice.api.DHCPUtils;
+import org.opendaylight.vpnservice.mdsalutil.MDSALUtil;
+import org.opendaylight.vpnservice.mdsalutil.MetaDataUtil;
+import org.opendaylight.vpnservice.mdsalutil.NwConstants;
+import org.opendaylight.vpnservice.mdsalutil.packet.Ethernet;
+import org.opendaylight.vpnservice.mdsalutil.packet.IEEE8021Q;
+import org.opendaylight.vpnservice.mdsalutil.packet.IPProtocols;
+import org.opendaylight.vpnservice.mdsalutil.packet.IPv4;
+import org.opendaylight.vpnservice.mdsalutil.packet.UDP;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.InterfacesState;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.Port;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnet.attributes.HostRoutes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.subnets.Subnet;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.PacketInReason;
import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.PacketProcessingListener;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.PacketProcessingService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.PacketReceived;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.SendToController;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.TransmitPacketInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rpcs.rev151003.GetEgressActionsForInterfaceInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rpcs.rev151003.GetEgressActionsForInterfaceOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rpcs.rev151003.GetInterfaceFromIfIndexInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rpcs.rev151003.GetInterfaceFromIfIndexInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rpcs.rev151003.GetInterfaceFromIfIndexOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rpcs.rev151003.OdlInterfaceRpcService;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Optional;
public class DhcpPktHandler implements AutoCloseable, PacketProcessingListener {
-
+
private static final Logger LOG = LoggerFactory.getLogger(DhcpPktHandler.class);
private final DataBroker dataBroker;
+ private final DhcpManager dhcpMgr;
+ private OdlInterfaceRpcService interfaceManagerRpc;
+ private boolean computeUdpChecksum = true;
+ private PacketProcessingService pktService;
+ private DhcpExternalTunnelManager dhcpExternalTunnelManager;
- public DhcpPktHandler(final DataBroker broker) {
+ public DhcpPktHandler(final DataBroker broker, final DhcpManager dhcpManager, final DhcpExternalTunnelManager dhcpExternalTunnelManager) {
+ this.dhcpExternalTunnelManager = dhcpExternalTunnelManager;
this.dataBroker = broker;
+ dhcpMgr = dhcpManager;
}
+ //TODO: Handle this in a separate thread
@Override
- public void onPacketReceived(PacketReceived pktReceived) {
- LOG.info("Pkt received: {}",pktReceived);
+ public void onPacketReceived(PacketReceived packet) {
+ Class<? extends PacketInReason> pktInReason = packet.getPacketInReason();
+ if (isPktInReasonSendtoCtrl(pktInReason)) {
+ byte[] inPayload = packet.getPayload();
+ Ethernet ethPkt = new Ethernet();
+ try {
+ ethPkt.deserialize(inPayload, 0, inPayload.length * NetUtils.NumBitsInAByte);
+ } catch (Exception e) {
+ LOG.warn("Failed to decode DHCP Packet {}", e);
+ LOG.trace("Received packet {}", packet);
+ return;
+ }
+ try {
+ DHCP pktIn;
+ pktIn = getDhcpPktIn(ethPkt);
+ if (pktIn != null) {
+ LOG.trace("DHCPPkt received: {}", pktIn);
+ LOG.trace("Received Packet: {}", packet);
+ BigInteger metadata = packet.getMatch().getMetadata().getMetadata();
+ long portTag = MetaDataUtil.getLportFromMetadata(metadata).intValue();
+ String macAddress = DHCPUtils.byteArrayToString(ethPkt.getSourceMACAddress());
+ BigInteger tunnelId = packet.getMatch().getTunnel() == null ? null : packet.getMatch().getTunnel().getTunnelId();
+ String interfaceName = getInterfaceNameFromTag(portTag);
+ ImmutablePair<BigInteger, String> pair = getDpnIdPhysicalAddressFromInterfaceName(interfaceName);
+ DHCP replyPkt = handleDhcpPacket(pktIn, interfaceName, macAddress, tunnelId);
+ byte[] pktOut = getDhcpPacketOut(replyPkt, ethPkt, pair.getRight());
+ sendPacketOut(pktOut, pair.getLeft(), interfaceName, tunnelId);
+ }
+ } catch (Exception e) {
+ LOG.warn("Failed to get DHCP Reply");
+ LOG.trace("Reason for failure {}", e);
+ }
+ }
+ }
+
+ private void sendPacketOut(byte[] pktOut, BigInteger dpnId, String interfaceName, BigInteger tunnelId) {
+ LOG.trace("Sending packet out DpId {}, portId {}, vlanId {}, interfaceName {}", dpnId, interfaceName);
+ List<Action> action = getEgressAction(interfaceName, tunnelId);
+ TransmitPacketInput output = MDSALUtil.getPacketOut(action, pktOut, dpnId);
+ LOG.trace("Transmitting packet: {}",output);
+ this.pktService.transmitPacket(output);
+ }
+
+ private DHCP handleDhcpPacket(DHCP dhcpPkt, String interfaceName, String macAddress, BigInteger tunnelId) {
+ LOG.debug("DHCP pkt rcvd {}", dhcpPkt);
+ byte msgType = dhcpPkt.getMsgType();
+ if (msgType == DHCPConstants.MSG_DECLINE) {
+ LOG.debug("DHCPDECLINE received");
+ return null;
+ } else if (msgType == DHCPConstants.MSG_RELEASE) {
+ LOG.debug("DHCPRELEASE received");
+ return null;
+ }
+ Port nPort;
+ if (tunnelId != null) {
+ nPort = dhcpExternalTunnelManager.readVniMacToPortCache(tunnelId, macAddress);
+ } else {
+ nPort = getNeutronPort(interfaceName);
+ }
+ Subnet nSubnet = getNeutronSubnet(nPort);
+ DhcpInfo dhcpInfo = getDhcpInfo(nPort, nSubnet);
+ LOG.trace("NeutronPort: {} \n NeutronSubnet: {}, dhcpInfo{}",nPort, nSubnet, dhcpInfo);
+ DHCP reply = null;
+ if (dhcpInfo != null) {
+ if (msgType == DHCPConstants.MSG_DISCOVER) {
+ reply = getReplyToDiscover(dhcpPkt, dhcpInfo);
+ } else if (msgType == DHCPConstants.MSG_REQUEST) {
+ reply = getReplyToRequest(dhcpPkt, dhcpInfo);
+ }
+ }
+
+ return reply;
+ }
+
+ private DhcpInfo getDhcpInfo(Port nPort, Subnet nSubnet) {
+ DhcpInfo dhcpInfo = null;
+ if( (nPort != null) && (nSubnet != null) ) {
+ String clientIp = nPort.getFixedIps().get(0).getIpAddress().getIpv4Address().getValue();
+ String serverIp = nSubnet.getGatewayIp().getIpv4Address().getValue();
+ List<IpAddress> dnsServers = nSubnet.getDnsNameservers();
+ dhcpInfo = new DhcpInfo();
+ dhcpInfo.setClientIp(clientIp).setServerIp(serverIp)
+ .setCidr(String.valueOf(nSubnet.getCidr().getValue()))
+ .setHostRoutes(nSubnet.getHostRoutes())
+ .setDnsServersIpAddrs(dnsServers).setGatewayIp(serverIp);
+ }
+ return dhcpInfo;
+ }
+
+ private Subnet getNeutronSubnet(Port nPort) {
+ return dhcpMgr.getNeutronSubnet(nPort);
+ }
+
+ private Port getNeutronPort(String interfaceName) {
+ return dhcpMgr.getNeutronPort(interfaceName);
+ }
+
+ private DHCP getDhcpPktIn(Ethernet actualEthernetPacket) {
+ Ethernet ethPkt = actualEthernetPacket;
+ if (ethPkt.getEtherType() == (short)NwConstants.ETHTYPE_802_1Q) {
+ ethPkt = (Ethernet)ethPkt.getPayload();
+ }
+ if (ethPkt.getPayload() instanceof IPv4) {
+ IPv4 ipPkt = (IPv4) ethPkt.getPayload();
+ if (ipPkt.getPayload() instanceof UDP) {
+ UDP udpPkt = (UDP) ipPkt.getPayload();
+ if ((udpPkt.getSourcePort() == DHCPMConstants.dhcpClientPort)
+ && (udpPkt.getDestinationPort() == DHCPMConstants.dhcpServerPort)) {
+ LOG.trace("Matched dhcpClientPort and dhcpServerPort");
+ byte[] rawDhcpPayload = udpPkt.getRawPayload();
+ DHCP reply = new DHCP();
+ try {
+ reply.deserialize(rawDhcpPayload, 0, rawDhcpPayload.length);
+ } catch (PacketException e) {
+ LOG.warn("Failed to deserialize DHCP pkt");
+ LOG.trace("Reason for failure {}", e);
+ return null;
+ }
+ return reply;
+ }
+ }
+ }
+ return null;
+ }
+
+ DHCP getReplyToDiscover(DHCP dhcpPkt, DhcpInfo dhcpInfo) {
+ DHCP reply = new DHCP();
+ reply.setOp(DHCPConstants.BOOTREPLY);
+ reply.setHtype(dhcpPkt.getHtype());
+ reply.setHlen(dhcpPkt.getHlen());
+ reply.setHops((byte) 0);
+ reply.setXid(dhcpPkt.getXid());
+ reply.setSecs((short) 0);
+
+ reply.setYiaddr(dhcpInfo.getClientIp());
+ reply.setSiaddr(dhcpInfo.getServerIp());
+
+ reply.setFlags(dhcpPkt.getFlags());
+ reply.setGiaddr(dhcpPkt.getGiaddr());
+ reply.setChaddr(dhcpPkt.getChaddr());
+
+ reply.setMsgType(DHCPConstants.MSG_OFFER);
+ if(dhcpPkt.containsOption(DHCPConstants.OPT_PARAMETER_REQUEST_LIST)) {
+ setParameterListOptions(dhcpPkt, reply, dhcpInfo);
+ }
+ setCommonOptions(reply, dhcpInfo);
+ return reply;
+ }
+
+ DHCP getReplyToRequest(DHCP dhcpPkt, DhcpInfo dhcpInfo) {
+ boolean sendAck = false;
+ byte[] requestedIp = null;
+ DHCP reply = new DHCP();
+ reply.setOp(DHCPConstants.BOOTREPLY);
+ reply.setHtype(dhcpPkt.getHtype());
+ reply.setHlen(dhcpPkt.getHlen());
+ reply.setHops((byte) 0);
+ reply.setXid(dhcpPkt.getXid());
+ reply.setSecs((short) 0);
+
+ reply.setFlags(dhcpPkt.getFlags());
+ reply.setGiaddr(dhcpPkt.getGiaddr());
+ reply.setChaddr(dhcpPkt.getChaddr());
+ byte[] allocatedIp = DHCPUtils.strAddrToByteArray(dhcpInfo.getClientIp());
+ if(Arrays.equals(allocatedIp, dhcpPkt.getCiaddr())) {
+ //This means a renew request
+ sendAck = true;
+ } else {
+ requestedIp = dhcpPkt.getOptionBytes(DHCPConstants.OPT_REQUESTED_ADDRESS);
+ sendAck = Arrays.equals(allocatedIp, requestedIp);
+ }
+
+ if (sendAck) {
+ reply.setCiaddr(dhcpPkt.getCiaddr());
+ reply.setYiaddr(dhcpInfo.getClientIp());
+ reply.setSiaddr(dhcpInfo.getServerIp());
+ reply.setMsgType(DHCPConstants.MSG_ACK);
+ if(dhcpPkt.containsOption(DHCPConstants.OPT_PARAMETER_REQUEST_LIST)) {
+ setParameterListOptions(dhcpPkt, reply, dhcpInfo);
+ }
+ setCommonOptions(reply, dhcpInfo);
+ }
+ else {
+ reply.setMsgType(DHCPConstants.MSG_NAK);
+ }
+ return reply;
+ }
+
+ protected byte[] getDhcpPacketOut(DHCP reply, Ethernet etherPkt, String phyAddrees) {
+ if (reply == null) {
+ /*
+ * DECLINE or RELEASE don't result in reply packet
+ */
+ return null;
+ }
+ LOG.debug("Sending DHCP Pkt {}", reply);
+ // create UDP pkt
+ UDP udpPkt = new UDP();
+ byte[] rawPkt;
+ try {
+ rawPkt = reply.serialize();
+ } catch (PacketException e2) {
+ // TODO Auto-generated catch block
+ e2.printStackTrace();
+ return null;
+ }
+ udpPkt.setRawPayload(rawPkt);
+ udpPkt.setDestinationPort(DHCPMConstants.dhcpClientPort);
+ udpPkt.setSourcePort(DHCPMConstants.dhcpServerPort);
+ udpPkt.setLength((short) (rawPkt.length + 8));
+ //Create IP Pkt
+ IPv4 ip4Reply = new IPv4();
+ try {
+ rawPkt = udpPkt.serialize();
+ } catch (PacketException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ return null;
+ }
+ short checkSum = 0;
+ if(this.computeUdpChecksum) {
+ checkSum = computeChecksum(rawPkt, reply.getSiaddr(),
+ NetUtils.intToByteArray4(DHCPMConstants.BCAST_IP));
+ }
+ udpPkt.setChecksum(checkSum);
+ ip4Reply.setPayload(udpPkt);
+ ip4Reply.setProtocol(IPProtocols.UDP.byteValue());
+ ip4Reply.setSourceAddress(reply.getSiaddrAsInetAddr());
+ ip4Reply.setDestinationAddress(DHCPMConstants.BCAST_IP);
+ ip4Reply.setTotalLength((short) (rawPkt.length+20));
+ ip4Reply.setTtl((byte) 32);
+ // create Ethernet Frame
+ Ethernet ether = new Ethernet();
+ if (etherPkt.getEtherType() == (short)NwConstants.ETHTYPE_802_1Q) {
+ IEEE8021Q vlanPacket = (IEEE8021Q) etherPkt.getPayload();
+ IEEE8021Q vlanTagged = new IEEE8021Q();
+ vlanTagged.setCFI(vlanPacket.getCfi());
+ vlanTagged.setPriority(vlanPacket.getPriority());
+ vlanTagged.setVlanId(vlanPacket.getVlanId());
+ vlanTagged.setPayload(ip4Reply);
+ vlanTagged.setEtherType(EtherTypes.IPv4.shortValue());
+ ether.setPayload(vlanTagged);
+ ether.setEtherType((short) NwConstants.ETHTYPE_802_1Q);
+ } else {
+ ether.setEtherType(EtherTypes.IPv4.shortValue());
+ ether.setPayload(ip4Reply);
+ }
+ ether.setSourceMACAddress(getServerMacAddress(phyAddrees));
+ ether.setDestinationMACAddress(etherPkt.getSourceMACAddress());
+
+ try {
+ rawPkt = ether.serialize();
+ } catch (PacketException e) {
+ LOG.warn("Failed to serialize ethernet reply",e);
+ return null;
+ }
+ return rawPkt;
+ }
+
+ private byte[] getServerMacAddress(String phyAddress) {
+ // Should we return ControllerMac instead?
+ return DHCPUtils.strMacAddrtoByteArray(phyAddress);
+ }
+
+ public short computeChecksum(byte[] inData, byte[] srcAddr, byte[] destAddr) {
+ short checkSum = (short) 0;
+ int sum = 0, carry = 0;
+ int wordData, i;
+
+ for (i = 0; i < inData.length - 1; i = i + 2) {
+ // Skip, if the current bytes are checkSum bytes
+ wordData = ((inData[i] << 8) & 0xFF00) + (inData[i + 1] & 0xFF);
+ sum = sum + wordData;
+ }
+
+ if (i < inData.length) {
+ wordData = ((inData[i] << 8) & 0xFF00) + (0 & 0xFF);
+ sum = sum + wordData;
+ }
+
+ for (i = 0; i < 4; i = i + 2) {
+ wordData = ((srcAddr[i] << 8) & 0xFF00) + (srcAddr[i + 1] & 0xFF);
+ sum = sum + wordData;
+ }
+
+ for (i = 0; i < 4; i = i + 2) {
+ wordData = ((destAddr[i] << 8) & 0xFF00) + (destAddr[i + 1] & 0xFF);
+ sum = sum + wordData;
+ }
+ sum = sum + 17 + inData.length;
+
+ while((sum >> 16) != 0) {
+ carry = (sum >> 16);
+ sum = (sum & 0xFFFF)+ carry;
+ }
+ checkSum = (short) ~((short) sum & 0xFFFF);
+ if(checkSum == 0) {
+ checkSum = (short)0xffff;
+ }
+ return checkSum;
+ }
+
+ private void setCommonOptions(DHCP pkt, DhcpInfo dhcpInfo) {
+ pkt.setOptionInt(DHCPConstants.OPT_LEASE_TIME, dhcpMgr.getDhcpLeaseTime());
+ if (dhcpMgr.getDhcpDefDomain() != null) {
+ pkt.setOptionString(DHCPConstants.OPT_DOMAIN_NAME, dhcpMgr.getDhcpDefDomain());
+ }
+ if(dhcpMgr.getDhcpLeaseTime() > 0) {
+ pkt.setOptionInt(DHCPConstants.OPT_REBINDING_TIME, dhcpMgr.getDhcpRebindingTime());
+ pkt.setOptionInt(DHCPConstants.OPT_RENEWAL_TIME, dhcpMgr.getDhcpRenewalTime());
+ }
+ SubnetUtils util = null;
+ SubnetInfo info = null;
+ util = new SubnetUtils(dhcpInfo.getCidr());
+ info = util.getInfo();
+ String gwIp = dhcpInfo.getGatewayIp();
+ List<String> dnServers = dhcpInfo.getDnsServers();
+ try {
+ /*
+ * setParameterListOptions may have initialized some of these
+ * options to maintain order. If we can't fill them, unset to avoid
+ * sending wrong information in reply.
+ */
+ if (gwIp != null) {
+ pkt.setOptionInetAddr(DHCPConstants.OPT_SERVER_IDENTIFIER, gwIp);
+ pkt.setOptionInetAddr(DHCPConstants.OPT_ROUTERS, gwIp);
+ } else {
+ pkt.unsetOption(DHCPConstants.OPT_SERVER_IDENTIFIER);
+ pkt.unsetOption(DHCPConstants.OPT_ROUTERS);
+ }
+ if (info != null) {
+ pkt.setOptionInetAddr(DHCPConstants.OPT_SUBNET_MASK, info.getNetmask());
+ pkt.setOptionInetAddr(DHCPConstants.OPT_BROADCAST_ADDRESS, info.getBroadcastAddress());
+ } else {
+ pkt.unsetOption(DHCPConstants.OPT_SUBNET_MASK);
+ pkt.unsetOption(DHCPConstants.OPT_BROADCAST_ADDRESS);
+ }
+ if ((dnServers != null) && (dnServers.size() > 0)) {
+ pkt.setOptionStrAddrs(DHCPConstants.OPT_DOMAIN_NAME_SERVERS, dnServers);
+ } else {
+ pkt.unsetOption(DHCPConstants.OPT_DOMAIN_NAME_SERVERS);
+ }
+ } catch (UnknownHostException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+
+ private void setParameterListOptions(DHCP req, DHCP reply, DhcpInfo dhcpInfo) {
+ byte[] paramList = req.getOptionBytes(DHCPConstants.OPT_PARAMETER_REQUEST_LIST);
+ for(int i = 0; i < paramList.length; i++) {
+ switch (paramList[i]) {
+ case DHCPConstants.OPT_SUBNET_MASK:
+ case DHCPConstants.OPT_ROUTERS:
+ case DHCPConstants.OPT_SERVER_IDENTIFIER:
+ case DHCPConstants.OPT_DOMAIN_NAME_SERVERS:
+ case DHCPConstants.OPT_BROADCAST_ADDRESS:
+ case DHCPConstants.OPT_LEASE_TIME:
+ case DHCPConstants.OPT_RENEWAL_TIME:
+ case DHCPConstants.OPT_REBINDING_TIME:
+ /* These values will be filled in setCommonOptions
+ * Setting these just to preserve order as
+ * specified in PARAMETER_REQUEST_LIST.
+ */
+ reply.setOptionInt(paramList[i], 0);
+ break;
+ case DHCPConstants.OPT_DOMAIN_NAME:
+ reply.setOptionString(paramList[i], " ");
+ break;
+ case DHCPConstants.OPT_CLASSLESS_ROUTE:
+ setOptionClasslessRoute(reply, dhcpInfo);
+ break;
+ default:
+ LOG.debug("DHCP Option code {} not supported yet", paramList[i]);
+ break;
+ }
+ }
+ }
+ private void setOptionClasslessRoute(DHCP reply, DhcpInfo dhcpInfo) {
+ List<HostRoutes> hostRoutes = dhcpInfo.getHostRoutes();
+ if(hostRoutes == null) {
+ //we can't set this option, so return
+ return;
+ }
+ ByteArrayOutputStream result = new ByteArrayOutputStream();
+ Iterator<HostRoutes> iter = hostRoutes.iterator();
+ while(iter.hasNext()) {
+ HostRoutes hostRoute = iter.next();
+ if(hostRoute.getNexthop().getIpv4Address() == null ||
+ hostRoute.getDestination().getIpv4Prefix() == null ) {
+ // we only deal with IPv4 addresses
+ return;
+ }
+ String router = hostRoute.getNexthop().getIpv4Address().getValue();
+ String dest = hostRoute.getDestination().getIpv4Prefix().getValue();
+ try {
+ result.write(convertToClasslessRouteOption(dest, router));
+ } catch (IOException | NullPointerException e) {
+ LOG.debug("Exception {}",e.getMessage());
+ }
+ }
+ if (result.size() > 0) {
+ reply.setOptionBytes(DHCPConstants.OPT_CLASSLESS_ROUTE , result.toByteArray());
+ }
+ }
+
+ protected byte[] convertToClasslessRouteOption(String dest, String router) {
+ ByteArrayOutputStream bArr = new ByteArrayOutputStream();
+ if((dest == null ||
+ router == null)) {
+ return null;
+ }
+
+ //get prefix
+ Short prefix = null;
+ String[] parts = dest.split("/");
+ if (parts.length < 2) {
+ prefix = new Short((short)0);
+ } else {
+ prefix = Short.valueOf(parts[1]);
+ }
+
+ bArr.write(prefix.byteValue());
+ SubnetUtils util = new SubnetUtils(dest);
+ SubnetInfo info = util.getInfo();
+ String strNetAddr = info.getNetworkAddress();
+ try {
+ byte[] netAddr = InetAddress.getByName(strNetAddr).getAddress();
+ //Strip any trailing 0s from netAddr
+ for(int i = 0; i < netAddr.length;i++) {
+ if(netAddr[i] != 0) {
+ bArr.write(netAddr,i,1);
+ }
+ }
+ bArr.write(InetAddress.getByName(router).getAddress());
+ } catch (IOException e) {
+ return null;
+ }
+ return bArr.toByteArray();
+ }
+
+ private boolean isPktInReasonSendtoCtrl(Class<? extends PacketInReason> pktInReason) {
+ return (pktInReason == SendToController.class);
}
@Override
public void close() throws Exception {
// TODO Auto-generated method stub
-
}
+ public void setPacketProcessingService(PacketProcessingService packetService) {
+ this.pktService = packetService;
+ }
+
+ public void setInterfaceManagerRpc(OdlInterfaceRpcService interfaceManagerRpc) {
+ LOG.trace("Registered interfaceManager successfully");;
+ this.interfaceManagerRpc = interfaceManagerRpc;
+ }
+
+ private String getInterfaceNameFromTag(long portTag) {
+ String interfaceName = null;
+ GetInterfaceFromIfIndexInput input = new GetInterfaceFromIfIndexInputBuilder().setIfIndex(new Integer((int)portTag)).build();
+ Future<RpcResult<GetInterfaceFromIfIndexOutput>> futureOutput = interfaceManagerRpc.getInterfaceFromIfIndex(input);
+ try {
+ GetInterfaceFromIfIndexOutput output = futureOutput.get().getResult();
+ interfaceName = output.getInterfaceName();
+ } catch (InterruptedException | ExecutionException e) {
+ LOG.error("Error while retrieving the interfaceName from tag using getInterfaceFromIfIndex RPC");
+ }
+ LOG.trace("Returning interfaceName {} for tag {} form getInterfaceNameFromTag", interfaceName, portTag);
+ return interfaceName;
+ }
+
+ private org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface getInterfaceStateFromOperDS(String interfaceName) {
+ InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> ifStateId =
+ buildStateInterfaceId(interfaceName);
+ Optional<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> ifStateOptional =
+ MDSALUtil.read(LogicalDatastoreType.OPERATIONAL, ifStateId, dataBroker);
+ if (!ifStateOptional.isPresent()) {
+ return null;
+ }
+
+ return ifStateOptional.get();
+ }
+
+ private InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> buildStateInterfaceId(String interfaceName) {
+ InstanceIdentifierBuilder<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> idBuilder =
+ InstanceIdentifier.builder(InterfacesState.class)
+ .child(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.class,
+ new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceKey(interfaceName));
+ InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> id = idBuilder.build();
+ return id;
+ }
+
+ private List<Action> getEgressAction(String interfaceName, BigInteger tunnelId) {
+ List<Action> actions = null;
+ try {
+ GetEgressActionsForInterfaceInputBuilder egressAction = new GetEgressActionsForInterfaceInputBuilder().setIntfName(interfaceName);
+ if (tunnelId != null) {
+ egressAction.setTunnelKey(tunnelId.longValue());
+ }
+ Future<RpcResult<GetEgressActionsForInterfaceOutput>> result =
+ interfaceManagerRpc.getEgressActionsForInterface(egressAction.build());
+ RpcResult<GetEgressActionsForInterfaceOutput> rpcResult = result.get();
+ if(!rpcResult.isSuccessful()) {
+ LOG.warn("RPC Call to Get egress actions for interface {} returned with Errors {}", interfaceName, rpcResult.getErrors());
+ } else {
+ actions = rpcResult.getResult().getAction();
+ }
+ } catch (InterruptedException | ExecutionException e) {
+ LOG.warn("Exception when egress actions for interface {}", interfaceName, e);
+ }
+ return actions;
+ }
+
+ private ImmutablePair<BigInteger, String> getDpnIdPhysicalAddressFromInterfaceName(String interfaceName) {
+ ImmutablePair<BigInteger, String> pair = dhcpMgr.getInterfaceCache(interfaceName);
+ if (pair!=null && pair.getLeft() != null && pair.getRight() != null) {
+ return pair;
+ }
+ NodeConnectorId nodeConnectorId = null;
+ org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface interfaceState = getInterfaceStateFromOperDS(interfaceName);
+ if(interfaceState != null) {
+ List<String> ofportIds = interfaceState.getLowerLayerIf();
+ nodeConnectorId = new NodeConnectorId(ofportIds.get(0));
+ }
+ BigInteger dpId = BigInteger.valueOf(MDSALUtil.getDpnIdFromPortName(nodeConnectorId));
+ String phyAddress = interfaceState==null ? "":interfaceState.getPhysAddress().getValue();
+ pair = new ImmutablePair<BigInteger, String>(dpId, phyAddress);
+ dhcpMgr.updateInterfaceCache(interfaceName, pair);
+ return pair;
+ }
}