blob: afcd4ee664cdcc9483ef49b63f411058aa3d2236 [file] [log] [blame]
Thomas Vachuska781d18b2014-10-27 10:31:25 -07001/*
Ray Milkey34c95902015-04-15 09:47:53 -07002 * Copyright 2014-2015 Open Networking Laboratory
Thomas Vachuska781d18b2014-10-27 10:31:25 -07003 *
Thomas Vachuska4f1a60c2014-10-28 13:39:07 -07004 * 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
Thomas Vachuska781d18b2014-10-27 10:31:25 -07007 *
Thomas Vachuska4f1a60c2014-10-28 13:39:07 -07008 * 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.
Thomas Vachuska781d18b2014-10-27 10:31:25 -070015 */
Brian O'Connorabafb502014-12-02 22:26:20 -080016package org.onosproject.proxyarp;
alshabibc274c902014-10-03 14:58:27 -070017
alshabibc274c902014-10-03 14:58:27 -070018import org.apache.felix.scr.annotations.Activate;
19import org.apache.felix.scr.annotations.Component;
20import org.apache.felix.scr.annotations.Deactivate;
Pavlin Radoslavov93b606b2015-02-25 17:28:39 -080021import org.apache.felix.scr.annotations.Modified;
22import org.apache.felix.scr.annotations.Property;
alshabibc274c902014-10-03 14:58:27 -070023import org.apache.felix.scr.annotations.Reference;
24import org.apache.felix.scr.annotations.ReferenceCardinality;
Jonathan Hart3cfce8e2015-01-14 16:43:27 -080025import org.onlab.packet.Ethernet;
Kunihiro Ishiguro93224452015-02-13 00:40:08 +090026import org.onlab.packet.ICMP6;
alshabib78baaf22015-02-18 18:55:45 -080027import org.onlab.packet.IPv6;
Thomas Vachuska6519e6f2015-03-11 02:29:31 -070028import org.onosproject.cfg.ComponentConfigService;
Brian O'Connorabafb502014-12-02 22:26:20 -080029import org.onosproject.core.ApplicationId;
30import org.onosproject.core.CoreService;
Jonathan Hart3cfce8e2015-01-14 16:43:27 -080031import org.onosproject.net.flow.DefaultTrafficSelector;
32import org.onosproject.net.flow.TrafficSelector;
Ayaka Koshibebfbe1d72015-03-16 16:51:41 -070033import org.onosproject.net.packet.InboundPacket;
Brian O'Connorabafb502014-12-02 22:26:20 -080034import org.onosproject.net.packet.PacketContext;
Jonathan Hart3cfce8e2015-01-14 16:43:27 -080035import org.onosproject.net.packet.PacketPriority;
Brian O'Connorabafb502014-12-02 22:26:20 -080036import org.onosproject.net.packet.PacketProcessor;
37import org.onosproject.net.packet.PacketService;
38import org.onosproject.net.proxyarp.ProxyArpService;
Pavlin Radoslavov93b606b2015-02-25 17:28:39 -080039import org.osgi.service.component.ComponentContext;
alshabibc274c902014-10-03 14:58:27 -070040import org.slf4j.Logger;
41
Thomas Vachuska6519e6f2015-03-11 02:29:31 -070042import java.util.Dictionary;
43
Pavlin Radoslavov93b606b2015-02-25 17:28:39 -080044import static com.google.common.base.Strings.isNullOrEmpty;
alshabib78baaf22015-02-18 18:55:45 -080045import static org.slf4j.LoggerFactory.getLogger;
46
alshabibc274c902014-10-03 14:58:27 -070047/**
48 * Sample reactive proxy arp application.
49 */
50@Component(immediate = true)
51public class ProxyArp {
52
alshabibc274c902014-10-03 14:58:27 -070053 private final Logger log = getLogger(getClass());
54
55 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
56 protected PacketService packetService;
57
58 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
59 protected ProxyArpService proxyArpService;
60
61 private ProxyArpProcessor processor = new ProxyArpProcessor();
62
alshabib92c65ad2014-10-08 21:56:05 -070063 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
64 protected CoreService coreService;
65
Thomas Vachuska6519e6f2015-03-11 02:29:31 -070066 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
67 protected ComponentConfigService cfgService;
68
alshabibc274c902014-10-03 14:58:27 -070069 private ApplicationId appId;
70
Pavlin Radoslavov93b606b2015-02-25 17:28:39 -080071 @Property(name = "ipv6NeighborDiscovery", boolValue = false,
Thomas Vachuska6519e6f2015-03-11 02:29:31 -070072 label = "Enable IPv6 Neighbor Discovery; default is false")
Ayaka Koshibebfbe1d72015-03-16 16:51:41 -070073 protected boolean ipv6NeighborDiscovery = false;
Pavlin Radoslavov93b606b2015-02-25 17:28:39 -080074
alshabibc274c902014-10-03 14:58:27 -070075 @Activate
Pavlin Radoslavov93b606b2015-02-25 17:28:39 -080076 public void activate(ComponentContext context) {
Thomas Vachuska6519e6f2015-03-11 02:29:31 -070077 cfgService.registerProperties(getClass());
Brian O'Connorabafb502014-12-02 22:26:20 -080078 appId = coreService.registerApplication("org.onosproject.proxyarp");
Pavlin Radoslavov93b606b2015-02-25 17:28:39 -080079
alshabibc274c902014-10-03 14:58:27 -070080 packetService.addProcessor(processor, PacketProcessor.ADVISOR_MAX + 1);
Charles M.C. Chane148de82015-05-06 12:38:21 +080081 readComponentConfiguration(context);
82 requestPackests();
Jonathan Hart3cfce8e2015-01-14 16:43:27 -080083
Charles M.C. Chane148de82015-05-06 12:38:21 +080084 log.info("Started with Application ID {}", appId.id());
85 }
86
87 @Deactivate
88 public void deactivate() {
89 // TODO revoke all packet requests when deactivate
90 cfgService.unregisterProperties(getClass(), false);
91 packetService.removeProcessor(processor);
92 processor = null;
93 log.info("Stopped");
94 }
95
96 @Modified
97 public void modified(ComponentContext context) {
98 // TODO revoke unnecessary packet requests when config being modified
99 readComponentConfiguration(context);
100 requestPackests();
101 }
102
103 /**
104 * Request packet in via PacketService.
105 */
106 private void requestPackests() {
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800107 TrafficSelector.Builder selectorBuilder =
108 DefaultTrafficSelector.builder();
109 selectorBuilder.matchEthType(Ethernet.TYPE_ARP);
110 packetService.requestPackets(selectorBuilder.build(),
111 PacketPriority.CONTROL, appId);
112
Pavlin Radoslavov93b606b2015-02-25 17:28:39 -0800113 if (ipv6NeighborDiscovery) {
114 // IPv6 Neighbor Solicitation packet.
115 selectorBuilder = DefaultTrafficSelector.builder();
116 selectorBuilder.matchEthType(Ethernet.TYPE_IPV6);
117 selectorBuilder.matchIPProtocol(IPv6.PROTOCOL_ICMP6);
118 selectorBuilder.matchIcmpv6Type(ICMP6.NEIGHBOR_SOLICITATION);
119 packetService.requestPackets(selectorBuilder.build(),
120 PacketPriority.CONTROL, appId);
Kunihiro Ishiguro93224452015-02-13 00:40:08 +0900121
Pavlin Radoslavov93b606b2015-02-25 17:28:39 -0800122 // IPv6 Neighbor Advertisement packet.
123 selectorBuilder = DefaultTrafficSelector.builder();
124 selectorBuilder.matchEthType(Ethernet.TYPE_IPV6);
125 selectorBuilder.matchIPProtocol(IPv6.PROTOCOL_ICMP6);
126 selectorBuilder.matchIcmpv6Type(ICMP6.NEIGHBOR_ADVERTISEMENT);
127 packetService.requestPackets(selectorBuilder.build(),
128 PacketPriority.CONTROL, appId);
129 }
Pavlin Radoslavov93b606b2015-02-25 17:28:39 -0800130 }
131
132 /**
133 * Extracts properties from the component configuration context.
134 *
135 * @param context the component context
136 */
137 private void readComponentConfiguration(ComponentContext context) {
138 Dictionary<?, ?> properties = context.getProperties();
139 Boolean flag;
140
141 flag = isPropertyEnabled(properties, "ipv6NeighborDiscovery");
142 if (flag == null) {
143 log.info("IPv6 Neighbor Discovery is not configured, " +
Thomas Vachuska6519e6f2015-03-11 02:29:31 -0700144 "using current value of {}", ipv6NeighborDiscovery);
Pavlin Radoslavov93b606b2015-02-25 17:28:39 -0800145 } else {
146 ipv6NeighborDiscovery = flag;
147 log.info("Configured. IPv6 Neighbor Discovery is {}",
148 ipv6NeighborDiscovery ? "enabled" : "disabled");
149 }
150 }
151
152 /**
153 * Check property name is defined and set to true.
154 *
Thomas Vachuska6519e6f2015-03-11 02:29:31 -0700155 * @param properties properties to be looked up
Pavlin Radoslavov93b606b2015-02-25 17:28:39 -0800156 * @param propertyName the name of the property to look up
157 * @return value when the propertyName is defined or return null
158 */
159 private static Boolean isPropertyEnabled(Dictionary<?, ?> properties,
160 String propertyName) {
161 Boolean value = null;
162 try {
163 String s = (String) properties.get(propertyName);
164 value = isNullOrEmpty(s) ? null : s.trim().equals("true");
165 } catch (ClassCastException e) {
166 // No propertyName defined.
167 value = null;
168 }
169 return value;
170 }
alshabibc274c902014-10-03 14:58:27 -0700171
172 /**
173 * Packet processor responsible for forwarding packets along their paths.
174 */
175 private class ProxyArpProcessor implements PacketProcessor {
176
177 @Override
178 public void process(PacketContext context) {
179 // Stop processing if the packet has been handled, since we
180 // can't do any more to it.
181 if (context.isHandled()) {
182 return;
183 }
Ayaka Koshibebfbe1d72015-03-16 16:51:41 -0700184 // If IPv6 NDP is disabled, don't handle IPv6 frames.
185 InboundPacket pkt = context.inPacket();
186 Ethernet ethPkt = pkt.parsed();
187 if (ethPkt == null) {
188 return;
189 }
190 if (!ipv6NeighborDiscovery && (ethPkt.getEtherType() == Ethernet.TYPE_IPV6)) {
191 return;
192 }
alshabibc274c902014-10-03 14:58:27 -0700193 //handle the arp packet.
Kunihiro Ishigurof1bff502015-01-30 15:47:06 -0800194 proxyArpService.handlePacket(context);
alshabibc274c902014-10-03 14:58:27 -0700195 }
196 }
197}
198
199