Pingping Lin

add an ARP reply emulator for public IP to vBNG

Change-Id: Id142ef278363d39330e1c1f061f33d23e6b5e790
...@@ -23,6 +23,7 @@ import java.util.List; ...@@ -23,6 +23,7 @@ import java.util.List;
23 23
24 import org.onlab.packet.IpAddress; 24 import org.onlab.packet.IpAddress;
25 import org.onlab.packet.IpPrefix; 25 import org.onlab.packet.IpPrefix;
26 +import org.onlab.packet.MacAddress;
26 27
27 /** 28 /**
28 * Contains the configuration data for virtual BNG that has been read from a 29 * Contains the configuration data for virtual BNG that has been read from a
...@@ -32,6 +33,7 @@ public final class VbngConfiguration { ...@@ -32,6 +33,7 @@ public final class VbngConfiguration {
32 33
33 private final List<IpPrefix> localPublicIpPrefixes; 34 private final List<IpPrefix> localPublicIpPrefixes;
34 private final IpAddress nextHopIpAddress; 35 private final IpAddress nextHopIpAddress;
36 + private final MacAddress publicFacingMac;
35 37
36 /** 38 /**
37 * Default constructor. 39 * Default constructor.
...@@ -39,6 +41,7 @@ public final class VbngConfiguration { ...@@ -39,6 +41,7 @@ public final class VbngConfiguration {
39 private VbngConfiguration() { 41 private VbngConfiguration() {
40 localPublicIpPrefixes = null; 42 localPublicIpPrefixes = null;
41 nextHopIpAddress = null; 43 nextHopIpAddress = null;
44 + publicFacingMac = null;
42 } 45 }
43 46
44 /** 47 /**
...@@ -46,14 +49,19 @@ public final class VbngConfiguration { ...@@ -46,14 +49,19 @@ public final class VbngConfiguration {
46 * 49 *
47 * @param nextHopIpAddress the IP address of the next hop 50 * @param nextHopIpAddress the IP address of the next hop
48 * @param prefixes the public IP prefix list for local SDN network 51 * @param prefixes the public IP prefix list for local SDN network
52 + * @param publicFacingMac the MAC address configured for all local
53 + * public IP addresses
49 */ 54 */
50 @JsonCreator 55 @JsonCreator
51 public VbngConfiguration(@JsonProperty("localPublicIpPrefixes") 56 public VbngConfiguration(@JsonProperty("localPublicIpPrefixes")
52 List<IpPrefix> prefixes, 57 List<IpPrefix> prefixes,
53 @JsonProperty("nextHopIpAddress") 58 @JsonProperty("nextHopIpAddress")
54 - IpAddress nextHopIpAddress) { 59 + IpAddress nextHopIpAddress,
60 + @JsonProperty("publicFacingMac")
61 + MacAddress publicFacingMac) {
55 localPublicIpPrefixes = prefixes; 62 localPublicIpPrefixes = prefixes;
56 this.nextHopIpAddress = nextHopIpAddress; 63 this.nextHopIpAddress = nextHopIpAddress;
64 + this.publicFacingMac = publicFacingMac;
57 } 65 }
58 66
59 /** 67 /**
...@@ -73,4 +81,13 @@ public final class VbngConfiguration { ...@@ -73,4 +81,13 @@ public final class VbngConfiguration {
73 public IpAddress getNextHopIpAddress() { 81 public IpAddress getNextHopIpAddress() {
74 return nextHopIpAddress; 82 return nextHopIpAddress;
75 } 83 }
84 +
85 + /**
86 + * Gets the MAC address configured for all the public IP addresses.
87 + *
88 + * @return the MAC address
89 + */
90 + public MacAddress getPublicFacingMac() {
91 + return publicFacingMac;
92 + }
76 } 93 }
......
...@@ -31,6 +31,7 @@ import org.apache.felix.scr.annotations.Deactivate; ...@@ -31,6 +31,7 @@ import org.apache.felix.scr.annotations.Deactivate;
31 import org.apache.felix.scr.annotations.Service; 31 import org.apache.felix.scr.annotations.Service;
32 import org.onlab.packet.IpAddress; 32 import org.onlab.packet.IpAddress;
33 import org.onlab.packet.IpPrefix; 33 import org.onlab.packet.IpPrefix;
34 +import org.onlab.packet.MacAddress;
34 import org.slf4j.Logger; 35 import org.slf4j.Logger;
35 import org.slf4j.LoggerFactory; 36 import org.slf4j.LoggerFactory;
36 37
...@@ -58,6 +59,7 @@ public class VbngConfigurationManager implements VbngConfigurationService { ...@@ -58,6 +59,7 @@ public class VbngConfigurationManager implements VbngConfigurationService {
58 new ConcurrentHashMap<>(); 59 new ConcurrentHashMap<>();
59 60
60 private IpAddress nextHopIpAddress; 61 private IpAddress nextHopIpAddress;
62 + private MacAddress macOfPublicIpAddresses;
61 63
62 @Activate 64 @Activate
63 public void activate() { 65 public void activate() {
...@@ -96,6 +98,7 @@ public class VbngConfigurationManager implements VbngConfigurationService { ...@@ -96,6 +98,7 @@ public class VbngConfigurationManager implements VbngConfigurationService {
96 localPublicIpPrefixes.put(prefix, true); 98 localPublicIpPrefixes.put(prefix, true);
97 } 99 }
98 nextHopIpAddress = config.getNextHopIpAddress(); 100 nextHopIpAddress = config.getNextHopIpAddress();
101 + macOfPublicIpAddresses = config.getPublicFacingMac();
99 102
100 } catch (FileNotFoundException e) { 103 } catch (FileNotFoundException e) {
101 log.warn("Configuration file not found: {}", configFileName); 104 log.warn("Configuration file not found: {}", configFileName);
...@@ -109,6 +112,11 @@ public class VbngConfigurationManager implements VbngConfigurationService { ...@@ -109,6 +112,11 @@ public class VbngConfigurationManager implements VbngConfigurationService {
109 return nextHopIpAddress; 112 return nextHopIpAddress;
110 } 113 }
111 114
115 + @Override
116 + public MacAddress getPublicFacingMac() {
117 + return macOfPublicIpAddresses;
118 + }
119 +
112 // TODO handle the case: the number of public IP addresses is not enough 120 // TODO handle the case: the number of public IP addresses is not enough
113 // for 1:1 mapping from public IP to private IP. 121 // for 1:1 mapping from public IP to private IP.
114 @Override 122 @Override
...@@ -169,6 +177,11 @@ public class VbngConfigurationManager implements VbngConfigurationService { ...@@ -169,6 +177,11 @@ public class VbngConfigurationManager implements VbngConfigurationService {
169 return ipAddressMap.get(privateIpAddress); 177 return ipAddressMap.get(privateIpAddress);
170 } 178 }
171 179
180 + @Override
181 + public boolean isAssignedPublicIpAddress(IpAddress ipAddress) {
182 + return ipAddressMap.containsValue(ipAddress);
183 + }
184 +
172 /** 185 /**
173 * Generates a new IP address base on a given IP address plus a number to 186 * Generates a new IP address base on a given IP address plus a number to
174 * increase. 187 * increase.
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
16 package org.onosproject.virtualbng; 16 package org.onosproject.virtualbng;
17 17
18 import org.onlab.packet.IpAddress; 18 import org.onlab.packet.IpAddress;
19 +import org.onlab.packet.MacAddress;
19 20
20 /** 21 /**
21 * Provides information about the virtual BNG configuration. 22 * Provides information about the virtual BNG configuration.
...@@ -30,6 +31,22 @@ public interface VbngConfigurationService { ...@@ -30,6 +31,22 @@ public interface VbngConfigurationService {
30 public IpAddress getNextHopIpAddress(); 31 public IpAddress getNextHopIpAddress();
31 32
32 /** 33 /**
34 + * Gets the MAC address configured for all the public IP addresses.
35 + *
36 + * @return the MAC address
37 + */
38 + public MacAddress getPublicFacingMac();
39 +
40 + /**
41 + * Evaluates whether an IP address is an assigned public IP address.
42 + *
43 + * @param ipAddress the IP address to evaluate
44 + * @return true if the input IP address is an assigned public IP address,
45 + * otherwise false
46 + */
47 + public boolean isAssignedPublicIpAddress(IpAddress ipAddress);
48 +
49 + /**
33 * Gets an available public IP address from local public IP prefixes. 50 * Gets an available public IP address from local public IP prefixes.
34 * 51 *
35 * @param privateIpAddress a private IP address 52 * @param privateIpAddress a private IP address
......
1 +/*
2 + * Copyright 2015 Open Networking Laboratory
3 + *
4 + * Licensed under the Apache License, Version 2.0 (the "License");
5 + * you may not use this file except in compliance with the License.
6 + * You may obtain a copy of the License at
7 + *
8 + * http://www.apache.org/licenses/LICENSE-2.0
9 + *
10 + * Unless required by applicable law or agreed to in writing, software
11 + * distributed under the License is distributed on an "AS IS" BASIS,
12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 + * See the License for the specific language governing permissions and
14 + * limitations under the License.
15 + */
16 +package org.onosproject.virtualbng;
17 +
18 +import static org.slf4j.LoggerFactory.getLogger;
19 +
20 +import java.nio.ByteBuffer;
21 +
22 +import org.apache.felix.scr.annotations.Activate;
23 +import org.apache.felix.scr.annotations.Component;
24 +import org.apache.felix.scr.annotations.Deactivate;
25 +import org.apache.felix.scr.annotations.Reference;
26 +import org.apache.felix.scr.annotations.ReferenceCardinality;
27 +import org.onlab.packet.ARP;
28 +import org.onlab.packet.Ethernet;
29 +import org.onlab.packet.Ip4Address;
30 +import org.onlab.packet.MacAddress;
31 +import org.onosproject.core.ApplicationId;
32 +import org.onosproject.core.CoreService;
33 +import org.onosproject.net.ConnectPoint;
34 +import org.onosproject.net.flow.DefaultTrafficSelector;
35 +import org.onosproject.net.flow.DefaultTrafficTreatment;
36 +import org.onosproject.net.flow.TrafficSelector;
37 +import org.onosproject.net.flow.TrafficTreatment;
38 +import org.onosproject.net.packet.DefaultOutboundPacket;
39 +import org.onosproject.net.packet.InboundPacket;
40 +import org.onosproject.net.packet.PacketContext;
41 +import org.onosproject.net.packet.PacketPriority;
42 +import org.onosproject.net.packet.PacketProcessor;
43 +import org.onosproject.net.packet.PacketService;
44 +import org.slf4j.Logger;
45 +
46 +/**
47 + * When the upstream gateway which is outside local SDN network wants to send
48 + * packets to our local public IP addresses, it will send out ARP requests to
49 + * get the MAC address of each public IP address. Actually, there are no hosts
50 + * configured with those public IP addresses, so this class is to emulate the
51 + * behavior of the non-existed hosts and return ARP replies.
52 + * <p>
53 + * Since we will rewrite the destination MAC address in the switch before
54 + * traffic packets go to the destination, so the MAC address can be any number.
55 + * We manually configured a random MAC address for this purpose in the vBNG
56 + * configuration file.
57 + * </p>
58 + */
59 +@Component(immediate = true)
60 +public class VirtualPublicHosts {
61 + private final Logger log = getLogger(getClass());
62 +
63 + private static final String APP_NAME =
64 + "org.onosproject.virtualbng.VirtualPublicHosts";
65 +
66 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
67 + protected CoreService coreService;
68 +
69 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
70 + protected PacketService packetService;
71 +
72 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
73 + protected VbngConfigurationService vbngConfigService;
74 +
75 + private ApplicationId appId;
76 + private ArpRequestProcessor processor = new ArpRequestProcessor();
77 +
78 + @Activate
79 + public void activate() {
80 + appId = coreService.registerApplication(APP_NAME);
81 +
82 + packetService.addProcessor(processor,
83 + PacketProcessor.ADVISOR_MAX + 6);
84 +
85 + TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
86 + // Only IPv4 is supported in current vBNG.
87 + selector.matchEthType(Ethernet.TYPE_ARP);
88 + packetService.requestPackets(selector.build(),
89 + PacketPriority.REACTIVE, appId);
90 +
91 + log.info("vBNG virtual public hosts started");
92 + }
93 +
94 + @Deactivate
95 + public void deactivate() {
96 + packetService.removeProcessor(processor);
97 + processor = null;
98 + log.info("vBNG virtual public hosts Stopped");
99 + }
100 +
101 + /**
102 + * This class filters out the ARP request packets, generates the ARP
103 + * reply packets, and emits those packets.
104 + */
105 + private class ArpRequestProcessor implements PacketProcessor {
106 + @Override
107 + public void process(PacketContext context) {
108 +
109 + InboundPacket pkt = context.inPacket();
110 + Ethernet ethPkt = pkt.parsed();
111 +
112 + // Only handle the ARP packets
113 + if (ethPkt == null || ethPkt.getEtherType() != Ethernet.TYPE_ARP) {
114 + return;
115 + }
116 + ARP arpPacket = (ARP) ethPkt.getPayload();
117 + // Only handle ARP request packets
118 + if (arpPacket.getOpCode() != ARP.OP_REQUEST) {
119 + return;
120 + }
121 +
122 + Ip4Address targetIpAddress = Ip4Address
123 + .valueOf(arpPacket.getTargetProtocolAddress());
124 +
125 + // Only handle an ARP request when the target IP address inside is
126 + // an assigned public IP address
127 + if (!vbngConfigService.isAssignedPublicIpAddress(targetIpAddress)) {
128 + return;
129 + }
130 +
131 + MacAddress virtualHostMac =
132 + vbngConfigService.getPublicFacingMac();
133 + if (virtualHostMac == null) {
134 + return;
135 + }
136 +
137 + ConnectPoint srcConnectPoint = pkt.receivedFrom();
138 + Ethernet eth = ARP.buildArpReply(targetIpAddress,
139 + virtualHostMac,
140 + ethPkt);
141 +
142 + TrafficTreatment.Builder builder =
143 + DefaultTrafficTreatment.builder();
144 + builder.setOutput(srcConnectPoint.port());
145 + packetService.emit(new DefaultOutboundPacket(
146 + srcConnectPoint.deviceId(),
147 + builder.build(),
148 + ByteBuffer.wrap(eth.serialize())));
149 + }
150 + }
151 +}