mirror of
https://github.com/opennetworkinglab/onos.git
synced 2025-10-21 04:12:23 +02:00
CORD-416 Implemented ARP proxy for service IPs
Added ARP proxy which sends fake ARP reply for service IPs. Change-Id: I0583ee994def2a429701c0375af5203bdfaa39c5
This commit is contained in:
parent
68c4fc4862
commit
42c7b4e684
@ -23,6 +23,7 @@ import org.apache.felix.scr.annotations.Deactivate;
|
||||
import org.apache.felix.scr.annotations.Reference;
|
||||
import org.apache.felix.scr.annotations.ReferenceCardinality;
|
||||
import org.apache.felix.scr.annotations.Service;
|
||||
import org.onlab.packet.Ethernet;
|
||||
import org.onlab.packet.Ip4Address;
|
||||
import org.onlab.util.ItemNotFoundException;
|
||||
import org.onlab.packet.IpAddress;
|
||||
@ -56,6 +57,9 @@ import org.onosproject.net.group.GroupService;
|
||||
import org.onosproject.net.host.HostEvent;
|
||||
import org.onosproject.net.host.HostListener;
|
||||
import org.onosproject.net.host.HostService;
|
||||
import org.onosproject.net.packet.PacketContext;
|
||||
import org.onosproject.net.packet.PacketProcessor;
|
||||
import org.onosproject.net.packet.PacketService;
|
||||
import org.onosproject.openstackswitching.OpenstackNetwork;
|
||||
import org.onosproject.openstackswitching.OpenstackPort;
|
||||
import org.onosproject.openstackswitching.OpenstackSubnet;
|
||||
@ -134,6 +138,9 @@ public class CordVtn implements CordVtnService {
|
||||
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
|
||||
protected FlowRuleService flowRuleService;
|
||||
|
||||
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
|
||||
protected PacketService packetService;
|
||||
|
||||
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
|
||||
protected OvsdbController controller;
|
||||
|
||||
@ -154,6 +161,7 @@ public class CordVtn implements CordVtnService {
|
||||
|
||||
private final DeviceListener deviceListener = new InternalDeviceListener();
|
||||
private final HostListener hostListener = new InternalHostListener();
|
||||
private final PacketProcessor packetProcessor = new InternalPacketProcessor();
|
||||
|
||||
private final OvsdbHandler ovsdbHandler = new OvsdbHandler();
|
||||
private final BridgeHandler bridgeHandler = new BridgeHandler();
|
||||
@ -163,6 +171,7 @@ public class CordVtn implements CordVtnService {
|
||||
private ConsistentMap<CordVtnNode, NodeState> nodeStore;
|
||||
private Map<HostId, OpenstackNetwork> hostNetMap = Maps.newHashMap();
|
||||
private CordVtnRuleInstaller ruleInstaller;
|
||||
private CordVtnArpProxy arpProxy;
|
||||
|
||||
private enum NodeState {
|
||||
|
||||
@ -223,6 +232,10 @@ public class CordVtn implements CordVtnService {
|
||||
mastershipService,
|
||||
DEFAULT_TUNNEL);
|
||||
|
||||
arpProxy = new CordVtnArpProxy(appId, packetService);
|
||||
packetService.addProcessor(packetProcessor, PacketProcessor.director(0));
|
||||
arpProxy.requestPacket();
|
||||
|
||||
deviceService.addListener(deviceListener);
|
||||
hostService.addListener(hostListener);
|
||||
|
||||
@ -233,6 +246,7 @@ public class CordVtn implements CordVtnService {
|
||||
protected void deactivate() {
|
||||
deviceService.removeListener(deviceListener);
|
||||
hostService.removeListener(hostListener);
|
||||
packetService.removeProcessor(packetProcessor);
|
||||
|
||||
eventExecutor.shutdown();
|
||||
nodeStore.clear();
|
||||
@ -920,17 +934,18 @@ public class CordVtn implements CordVtnService {
|
||||
log.info("VM {} is detected", host.id());
|
||||
hostNetMap.put(host.id(), vNet);
|
||||
|
||||
CordService service = getCordService(vNet);
|
||||
if (service != null) {
|
||||
// TODO check if the service needs an update on its group buckets after done CORD-433
|
||||
ruleInstaller.updateServiceGroup(service);
|
||||
arpProxy.addServiceIp(service.serviceIp());
|
||||
}
|
||||
|
||||
ruleInstaller.populateBasicConnectionRules(
|
||||
host,
|
||||
hostIp,
|
||||
checkNotNull(getRemoteIp(host.location().deviceId())).getIp4Address(),
|
||||
vNet);
|
||||
|
||||
CordService service = getCordService(vNet);
|
||||
// TODO check if the service needs an update on its group buckets after done CORD-433
|
||||
if (service != null) {
|
||||
ruleInstaller.updateServiceGroup(service);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -950,12 +965,37 @@ public class CordVtn implements CordVtnService {
|
||||
ruleInstaller.removeBasicConnectionRules(host);
|
||||
|
||||
CordService service = getCordService(vNet);
|
||||
// TODO check if the service needs an update on its group buckets after done CORD-433
|
||||
if (service != null) {
|
||||
// TODO check if the service needs an update on its group buckets after done CORD-433
|
||||
ruleInstaller.updateServiceGroup(service);
|
||||
|
||||
if (getHostsWithOpenstackNetwork(vNet).isEmpty()) {
|
||||
arpProxy.removeServiceIp(service.serviceIp());
|
||||
}
|
||||
}
|
||||
|
||||
hostNetMap.remove(host.id());
|
||||
}
|
||||
}
|
||||
|
||||
private class InternalPacketProcessor implements PacketProcessor {
|
||||
|
||||
@Override
|
||||
public void process(PacketContext context) {
|
||||
if (context.isHandled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
Ethernet ethPacket = context.inPacket().parsed();
|
||||
if (ethPacket == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (ethPacket.getEtherType() != Ethernet.TYPE_ARP) {
|
||||
return;
|
||||
}
|
||||
|
||||
arpProxy.processArpPacket(context, ethPacket);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,152 @@
|
||||
/*
|
||||
* Copyright 2014-2015 Open Networking Laboratory
|
||||
*
|
||||
* 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.cordvtn;
|
||||
|
||||
import com.google.common.collect.Sets;
|
||||
import org.onlab.packet.ARP;
|
||||
import org.onlab.packet.EthType;
|
||||
import org.onlab.packet.Ethernet;
|
||||
import org.onlab.packet.Ip4Address;
|
||||
import org.onlab.packet.IpAddress;
|
||||
import org.onlab.packet.MacAddress;
|
||||
import org.onosproject.core.ApplicationId;
|
||||
import org.onosproject.net.flow.DefaultTrafficSelector;
|
||||
import org.onosproject.net.flow.DefaultTrafficTreatment;
|
||||
import org.onosproject.net.flow.TrafficSelector;
|
||||
import org.onosproject.net.flow.TrafficTreatment;
|
||||
import org.onosproject.net.packet.DefaultOutboundPacket;
|
||||
import org.onosproject.net.packet.PacketContext;
|
||||
import org.onosproject.net.packet.PacketPriority;
|
||||
import org.onosproject.net.packet.PacketService;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import static org.slf4j.LoggerFactory.getLogger;
|
||||
|
||||
/**
|
||||
* Handles ARP requests for virtual network service IPs.
|
||||
*/
|
||||
public class CordVtnArpProxy {
|
||||
protected final Logger log = getLogger(getClass());
|
||||
// TODO make gateway MAC address configurable
|
||||
private static final MacAddress DEFAULT_GATEWAY_MAC = MacAddress.valueOf("00:00:00:00:00:01");
|
||||
|
||||
private final ApplicationId appId;
|
||||
private final PacketService packetService;
|
||||
|
||||
private Set<Ip4Address> serviceIPs = Sets.newHashSet();
|
||||
|
||||
/**
|
||||
* Default constructor.
|
||||
*
|
||||
* @param appId application id
|
||||
* @param packetService packet service
|
||||
*/
|
||||
public CordVtnArpProxy(ApplicationId appId, PacketService packetService) {
|
||||
this.appId = appId;
|
||||
this.packetService = packetService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Requests ARP packet.
|
||||
*/
|
||||
public void requestPacket() {
|
||||
TrafficSelector selector = DefaultTrafficSelector.builder()
|
||||
.matchEthType(EthType.EtherType.ARP.ethType().toShort())
|
||||
.build();
|
||||
|
||||
packetService.requestPackets(selector,
|
||||
PacketPriority.CONTROL,
|
||||
appId,
|
||||
Optional.empty());
|
||||
}
|
||||
|
||||
/**
|
||||
* Cancels ARP packet.
|
||||
*/
|
||||
public void cancelPacket() {
|
||||
TrafficSelector selector = DefaultTrafficSelector.builder()
|
||||
.matchEthType(EthType.EtherType.ARP.ethType().toShort())
|
||||
.build();
|
||||
|
||||
packetService.cancelPackets(selector,
|
||||
PacketPriority.CONTROL,
|
||||
appId,
|
||||
Optional.empty());
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a given service IP address to be served.
|
||||
*
|
||||
* @param serviceIp service ip
|
||||
*/
|
||||
public void addServiceIp(IpAddress serviceIp) {
|
||||
checkNotNull(serviceIp);
|
||||
serviceIPs.add(serviceIp.getIp4Address());
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a given service IP address from this ARP proxy.
|
||||
*
|
||||
* @param serviceIp service ip
|
||||
*/
|
||||
public void removeServiceIp(IpAddress serviceIp) {
|
||||
checkNotNull(serviceIp);
|
||||
serviceIPs.remove(serviceIp.getIp4Address());
|
||||
}
|
||||
|
||||
/**
|
||||
* Emits ARP reply with fake MAC address for a given ARP request.
|
||||
* It only handles requests for the registered service IPs, and the other
|
||||
* requests can be handled by other ARP handlers like openstackSwitching or
|
||||
* proxyArp, for example.
|
||||
*
|
||||
* @param context packet context
|
||||
* @param ethPacket ethernet packet
|
||||
*/
|
||||
public void processArpPacket(PacketContext context, Ethernet ethPacket) {
|
||||
ARP arpPacket = (ARP) ethPacket.getPayload();
|
||||
Ip4Address targetIp = Ip4Address.valueOf(arpPacket.getTargetProtocolAddress());
|
||||
|
||||
if (arpPacket.getOpCode() != ARP.OP_REQUEST) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!serviceIPs.contains(targetIp)) {
|
||||
return;
|
||||
}
|
||||
|
||||
Ethernet ethReply = ARP.buildArpReply(
|
||||
targetIp,
|
||||
DEFAULT_GATEWAY_MAC,
|
||||
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();
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user