blob: d483bbf1fc0e167cdb4979571aa24f2b9b53e84b [file] [log] [blame]
Pingping Linbe126562015-05-06 17:57:10 -07001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2015-present Open Networking Foundation
Pingping Linbe126562015-05-06 17:57:10 -07003 *
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 */
16package org.onosproject.virtualbng;
17
18import static org.slf4j.LoggerFactory.getLogger;
19
20import java.nio.ByteBuffer;
21
Ray Milkeyd84f89b2018-08-17 14:54:17 -070022import org.osgi.service.component.annotations.Activate;
23import org.osgi.service.component.annotations.Component;
24import org.osgi.service.component.annotations.Deactivate;
25import org.osgi.service.component.annotations.Reference;
26import org.osgi.service.component.annotations.ReferenceCardinality;
Pingping Linbe126562015-05-06 17:57:10 -070027import org.onlab.packet.ARP;
28import org.onlab.packet.Ethernet;
29import org.onlab.packet.Ip4Address;
30import org.onlab.packet.MacAddress;
31import org.onosproject.core.ApplicationId;
32import org.onosproject.core.CoreService;
33import org.onosproject.net.ConnectPoint;
34import org.onosproject.net.flow.DefaultTrafficSelector;
35import org.onosproject.net.flow.DefaultTrafficTreatment;
36import org.onosproject.net.flow.TrafficSelector;
37import org.onosproject.net.flow.TrafficTreatment;
38import org.onosproject.net.packet.DefaultOutboundPacket;
39import org.onosproject.net.packet.InboundPacket;
40import org.onosproject.net.packet.PacketContext;
41import org.onosproject.net.packet.PacketPriority;
42import org.onosproject.net.packet.PacketProcessor;
43import org.onosproject.net.packet.PacketService;
44import 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)
60public class VirtualPublicHosts {
61 private final Logger log = getLogger(getClass());
62
63 private static final String APP_NAME =
64 "org.onosproject.virtualbng.VirtualPublicHosts";
65
Ray Milkeyd84f89b2018-08-17 14:54:17 -070066 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Pingping Linbe126562015-05-06 17:57:10 -070067 protected CoreService coreService;
68
Ray Milkeyd84f89b2018-08-17 14:54:17 -070069 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Pingping Linbe126562015-05-06 17:57:10 -070070 protected PacketService packetService;
71
Ray Milkeyd84f89b2018-08-17 14:54:17 -070072 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Pingping Linbe126562015-05-06 17:57:10 -070073 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
Brian O'Connor3b783262015-07-29 17:49:24 -070082 packetService.addProcessor(processor, PacketProcessor.director(6));
Aaron Kruglikov07a923d2015-07-03 13:30:57 -070083 requestIntercepts();
Pingping Linbe126562015-05-06 17:57:10 -070084 log.info("vBNG virtual public hosts started");
85 }
86
87 @Deactivate
88 public void deactivate() {
Aaron Kruglikov07a923d2015-07-03 13:30:57 -070089 withdrawIntercepts();
Pingping Linbe126562015-05-06 17:57:10 -070090 packetService.removeProcessor(processor);
91 processor = null;
92 log.info("vBNG virtual public hosts Stopped");
93 }
94
95 /**
Aaron Kruglikov07a923d2015-07-03 13:30:57 -070096 * Request packet in via PacketService.
97 */
98 private void requestIntercepts() {
99 TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
100 // Only IPv4 is supported in current vBNG.
101 selector.matchEthType(Ethernet.TYPE_ARP);
102 packetService.requestPackets(selector.build(),
103 PacketPriority.REACTIVE, appId);
104 }
105
106 /**
107 * Cancel request for packet in via PacketService.
108 */
109 private void withdrawIntercepts() {
110 TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
111 // Only IPv4 is supported in current vBNG.
112 selector.matchEthType(Ethernet.TYPE_ARP);
113 packetService.cancelPackets(selector.build(),
114 PacketPriority.REACTIVE, appId);
115 }
116
117 /**
Pingping Linbe126562015-05-06 17:57:10 -0700118 * This class filters out the ARP request packets, generates the ARP
119 * reply packets, and emits those packets.
120 */
121 private class ArpRequestProcessor implements PacketProcessor {
122 @Override
123 public void process(PacketContext context) {
124
125 InboundPacket pkt = context.inPacket();
126 Ethernet ethPkt = pkt.parsed();
127
128 // Only handle the ARP packets
129 if (ethPkt == null || ethPkt.getEtherType() != Ethernet.TYPE_ARP) {
130 return;
131 }
132 ARP arpPacket = (ARP) ethPkt.getPayload();
133 // Only handle ARP request packets
134 if (arpPacket.getOpCode() != ARP.OP_REQUEST) {
135 return;
136 }
137
138 Ip4Address targetIpAddress = Ip4Address
139 .valueOf(arpPacket.getTargetProtocolAddress());
140
141 // Only handle an ARP request when the target IP address inside is
142 // an assigned public IP address
143 if (!vbngConfigService.isAssignedPublicIpAddress(targetIpAddress)) {
144 return;
145 }
146
147 MacAddress virtualHostMac =
148 vbngConfigService.getPublicFacingMac();
149 if (virtualHostMac == null) {
150 return;
151 }
152
153 ConnectPoint srcConnectPoint = pkt.receivedFrom();
154 Ethernet eth = ARP.buildArpReply(targetIpAddress,
155 virtualHostMac,
156 ethPkt);
157
158 TrafficTreatment.Builder builder =
159 DefaultTrafficTreatment.builder();
160 builder.setOutput(srcConnectPoint.port());
161 packetService.emit(new DefaultOutboundPacket(
162 srcConnectPoint.deviceId(),
163 builder.build(),
164 ByteBuffer.wrap(eth.serialize())));
165 }
166 }
167}