CORD-483 Made virtual network gateway MAC address configurable
- Added 'gatewayMAC' field to network config for cordvtn
- Implemented to send gratuitous ARP when gateway MAC is updated
Change-Id: I4f9050f4be64f04e0568515bbb95474513bbe057
diff --git a/apps/cordvtn/src/main/java/org/onosproject/cordvtn/CordVtnArpProxy.java b/apps/cordvtn/src/main/java/org/onosproject/cordvtn/CordVtnArpProxy.java
index 4cef148..917bd6c 100644
--- a/apps/cordvtn/src/main/java/org/onosproject/cordvtn/CordVtnArpProxy.java
+++ b/apps/cordvtn/src/main/java/org/onosproject/cordvtn/CordVtnArpProxy.java
@@ -23,6 +23,7 @@
import org.onlab.packet.IpAddress;
import org.onlab.packet.MacAddress;
import org.onosproject.core.ApplicationId;
+import org.onosproject.net.Host;
import org.onosproject.net.flow.DefaultTrafficSelector;
import org.onosproject.net.flow.DefaultTrafficTreatment;
import org.onosproject.net.flow.TrafficSelector;
@@ -37,6 +38,7 @@
import java.util.Optional;
import java.util.Set;
+import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.slf4j.LoggerFactory.getLogger;
@@ -45,8 +47,6 @@
*/
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;
@@ -120,22 +120,21 @@
*
* @param context packet context
* @param ethPacket ethernet packet
+ * @param gatewayMac gateway mac address
*/
- public void processArpPacket(PacketContext context, Ethernet ethPacket) {
+ public void processArpPacket(PacketContext context, Ethernet ethPacket, MacAddress gatewayMac) {
+ checkArgument(!gatewayMac.equals(MacAddress.NONE));
+
ARP arpPacket = (ARP) ethPacket.getPayload();
Ip4Address targetIp = Ip4Address.valueOf(arpPacket.getTargetProtocolAddress());
- if (arpPacket.getOpCode() != ARP.OP_REQUEST) {
+ if (arpPacket.getOpCode() != ARP.OP_REQUEST || !serviceIPs.contains(targetIp)) {
return;
}
- if (!serviceIPs.contains(targetIp)) {
- return;
- }
-
Ethernet ethReply = ARP.buildArpReply(
targetIp,
- DEFAULT_GATEWAY_MAC,
+ gatewayMac,
ethPacket);
TrafficTreatment treatment = DefaultTrafficTreatment.builder()
@@ -149,4 +148,57 @@
context.block();
}
+
+ /**
+ * Emits gratuitous ARP when a gateway mac address has been changed.
+ *
+ * @param ip ip address to update MAC
+ * @param mac new mac address
+ * @param hosts set of hosts to send gratuitous ARP packet
+ */
+ public void sendGratuitousArp(IpAddress ip, MacAddress mac, Set<Host> hosts) {
+ checkArgument(!mac.equals(MacAddress.NONE));
+
+ Ethernet ethArp = buildGratuitousArp(ip.getIp4Address(), mac);
+ hosts.stream().forEach(host -> {
+ TrafficTreatment treatment = DefaultTrafficTreatment.builder()
+ .setOutput(host.location().port())
+ .build();
+
+ packetService.emit(new DefaultOutboundPacket(
+ host.location().deviceId(),
+ treatment,
+ ByteBuffer.wrap(ethArp.serialize())));
+ });
+ }
+
+ /**
+ * Builds gratuitous ARP packet with a given IP and MAC address.
+ *
+ * @param ip ip address for TPA and SPA
+ * @param mac new mac address
+ * @return ethernet packet
+ */
+ private Ethernet buildGratuitousArp(IpAddress ip, MacAddress mac) {
+ Ethernet eth = new Ethernet();
+
+ eth.setEtherType(Ethernet.TYPE_ARP);
+ eth.setSourceMACAddress(mac);
+ eth.setDestinationMACAddress(MacAddress.BROADCAST);
+
+ ARP arp = new ARP();
+ arp.setOpCode(ARP.OP_REQUEST);
+ arp.setHardwareType(ARP.HW_TYPE_ETHERNET);
+ arp.setHardwareAddressLength((byte) Ethernet.DATALAYER_ADDRESS_LENGTH);
+ arp.setProtocolType(ARP.PROTO_TYPE_IP);
+ arp.setProtocolAddressLength((byte) Ip4Address.BYTE_LENGTH);
+
+ arp.setSenderHardwareAddress(mac.toBytes());
+ arp.setTargetHardwareAddress(MacAddress.BROADCAST.toBytes());
+ arp.setSenderProtocolAddress(ip.getIp4Address().toOctets());
+ arp.setTargetProtocolAddress(ip.getIp4Address().toOctets());
+
+ eth.setPayload(arp);
+ return eth;
+ }
}