blob: 70ade23a0e1339a51ffeeab6bb22ec46fcdcf667 [file] [log] [blame]
Rusty Eddy95421642015-10-21 17:22:13 -07001/*
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 */
16package org.onosproject.pim.impl;
17
18import org.jboss.netty.util.Timeout;
19import org.jboss.netty.util.TimerTask;
20import org.onosproject.incubator.net.config.basics.ConfigException;
21import org.onosproject.incubator.net.config.basics.InterfaceConfig;
22import org.onosproject.incubator.net.intf.Interface;
23import org.onosproject.incubator.net.intf.InterfaceService;
24import org.onosproject.net.ConnectPoint;
25
26import java.util.Collection;
27import java.util.HashMap;
28import java.util.Map;
29import java.util.Set;
30import java.util.concurrent.TimeUnit;
31
32import org.onosproject.net.config.NetworkConfigEvent;
33import org.onosproject.net.config.NetworkConfigListener;
34import org.onosproject.net.config.NetworkConfigService;
35import org.slf4j.Logger;
36import org.slf4j.LoggerFactory;
37
38/**
39 * PIMInterfaces is a collection of all neighbors we have received
40 * PIM hello messages from. The main structure is a HashMap indexed
41 * by ConnectPoint with another HashMap indexed on the PIM neighbors
42 * IPAddress, it contains all PIM neighbors attached on that ConnectPoint.
43 */
44public final class PIMInterfaces {
45
46 private Logger log = LoggerFactory.getLogger("PIMInterfaces");
47
48 private static PIMInterfaces instance = null;
49
50 // Used to listen to network configuration changes
51 private NetworkConfigService configService;
52
53 // Used to access IP Interface definitions for our segment
54 private InterfaceService interfaceService;
55
56 // Internal class used to listen for network configuration changes
57 private InternalConfigListener configListener = new InternalConfigListener();
58
59 // This is the global container for all PIM Interfaces indexed by ConnectPoints.
60 private Map<ConnectPoint, PIMInterface> interfaces = new HashMap<>();
61
62 // Default hello message interval
63 private int helloMessageInterval = 60;
64
65 // Timer used to send hello messages on this interface
66 private Timeout helloTimer;
67
68 // Required by a utility class
69 private PIMInterfaces() {}
70
71 /**
72 * Get the instance of PIMInterfaces. Create the instance if needed.
73 *
74 * @return PIMInterface instance
75 */
76 public static PIMInterfaces getInstance() {
77 if (null == instance) {
78 instance = new PIMInterfaces();
79 }
80 return instance;
81 }
82
83 // Initialize the services
84 public void initialize(NetworkConfigService cs, InterfaceService is) {
85 configService = cs;
86 interfaceService = is;
87
88 // Initialize interfaces if they already exist
89 initInterfaces();
90
91 // Listen for network config changes
92 configService.addListener(configListener);
93 }
94
95 /**
96 * Listener for network config events.
97 */
98 private class InternalConfigListener implements NetworkConfigListener {
99
100 private void updateInterfaces(InterfaceConfig config) {
101 Set<Interface> intfs;
102 try {
103 intfs = config.getInterfaces();
104 } catch (ConfigException e) {
105 log.error(e.toString());
106 return;
107 }
108 for (Interface intf : intfs) {
109 addInterface(intf);
110 }
111 }
112
113 /**
114 * Remove the PIMInterface represented by the ConnectPoint. If the
115 * PIMInterface does not exist this function is a no-op.
116 *
117 * @param cp The connectPoint representing the PIMInterface to be removed.
118 */
119 private void removeInterface(ConnectPoint cp) {
Satish Kd1e31e52015-11-21 18:20:05 +0530120 PIMInterfaces.this.removeInterface(cp);
Rusty Eddy95421642015-10-21 17:22:13 -0700121 }
122
123 @Override
124 public void event(NetworkConfigEvent event) {
125 switch (event.type()) {
126 case CONFIG_ADDED:
127 case CONFIG_UPDATED:
128 log.debug("Config updated: " + event.toString() + "\n");
129 if (event.configClass() == InterfaceConfig.class) {
130 InterfaceConfig config =
131 configService.getConfig((ConnectPoint) event.subject(), InterfaceConfig.class);
132 updateInterfaces(config);
133 }
134 break;
135 case CONFIG_REMOVED:
136 if (event.configClass() == InterfaceConfig.class) {
137 removeInterface((ConnectPoint) event.subject());
138 }
139 break;
140 case CONFIG_REGISTERED:
141 case CONFIG_UNREGISTERED:
142 default:
143 break;
144 }
145 }
146 }
147
148 // Configure interfaces if they already exist.
149 private void initInterfaces() {
150 Set<Interface> intfs = interfaceService.getInterfaces();
151 for (Interface intf : intfs) {
152 log.debug("Adding interface: " + intf.toString() + "\n");
153 addInterface(intf);
154 }
155 }
156
157 /**
158 * Create a PIM Interface and add to our interfaces list.
159 *
160 * @param intf the interface to add
161 * @return the PIMInterface
162 */
163 public PIMInterface addInterface(Interface intf) {
164 PIMInterface pif = new PIMInterface(intf);
165 interfaces.put(intf.connectPoint(), pif);
166
167 // If we have added our first interface start the hello timer.
168 if (interfaces.size() == 1) {
169 startHelloTimer();
170 }
171
172 // Return this interface
173 return pif;
174 }
175
176 /**
177 * Remove the PIMInterface from the given ConnectPoint.
178 *
179 * @param cp the ConnectPoint indexing the PIMInterface to be removed.
180 */
181 public void removeInterface(ConnectPoint cp) {
182 if (interfaces.containsKey(cp)) {
183 interfaces.remove(cp);
184 }
185
186 if (interfaces.size() == 0) {
187 PIMTimer.stop();
188 }
189 }
190
191 /**
192 * Return a collection of PIMInterfaces for use by the PIM Interface codec.
193 *
194 * @return the collection of PIMInterfaces
195 */
196 public Collection<PIMInterface> getInterfaces() {
197 return interfaces.values();
198 }
199
200 /**
201 * Get the PIM Interface indexed by the given ConnectPoint.
202 *
203 * @param cp the connect point
204 * @return the PIMInterface if it exists, NULL if not
205 */
206 public PIMInterface getInterface(ConnectPoint cp) {
207 return interfaces.get(cp);
208 }
209
210 /**
211 * Return a string of PIMInterfaces for the cli command.
212 *
213 * @return a string representing PIM interfaces
214 */
215 public String printInterfaces() {
216 String str = "";
217 for (PIMInterface pi : interfaces.values()) {
218 str += pi.toString();
219 }
220 return str;
221 }
222
223 /* ---------------------------------- PIM Hello Timer ----------------------------------- */
224
225 /**
226 * Start a new hello timer for this interface.
227 */
228 private void startHelloTimer() {
229 helloTimer = PIMTimer.getTimer().newTimeout(
230 new HelloTimer(),
231 helloMessageInterval,
232 TimeUnit.SECONDS);
233
234 log.debug("Started Hello Timer");
235 }
236
237 /**
238 * This inner class handles transmitting a PIM hello message on this ConnectPoint.
239 */
240 private final class HelloTimer implements TimerTask {
241
242 HelloTimer() {
243 }
244
245 @Override
246 public void run(Timeout timeout) throws Exception {
247
248 log.debug("Running Hello Timer\n");
249 // Technically we should not send all hello's in synch..
250 for (PIMInterface pi : interfaces.values()) {
251 pi.sendHello();
252 }
253
254 // restart the hello timer
255 if (interfaces.size() > 0) {
256 startHelloTimer();
257 }
258 }
259 }
260}