blob: 45cda266c48fb83f8f742077ee0afef21ee367de [file] [log] [blame]
Jonathan Hart4cb39882015-08-12 23:50:55 -04001/*
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
17package org.onosproject.routing.config;
18
19import com.fasterxml.jackson.databind.JsonNode;
papazois7d39a742015-10-14 10:15:56 +030020import com.fasterxml.jackson.databind.node.ArrayNode;
21import com.fasterxml.jackson.databind.node.JsonNodeFactory;
22import com.fasterxml.jackson.databind.node.ObjectNode;
Jonathan Hart4cb39882015-08-12 23:50:55 -040023import com.google.common.collect.Sets;
24import org.onlab.packet.IpAddress;
Luca Prete8f2a3ce2016-03-29 16:13:01 -070025import org.onlab.packet.VlanId;
Jonathan Hart4cb39882015-08-12 23:50:55 -040026import org.onosproject.core.ApplicationId;
Jonathan Hart4cb39882015-08-12 23:50:55 -040027import org.onosproject.net.ConnectPoint;
Jonathan Harta8625482015-09-08 16:14:56 -070028import org.onosproject.net.config.Config;
Jonathan Hart4cb39882015-08-12 23:50:55 -040029
papazois7d39a742015-10-14 10:15:56 +030030import java.util.Objects;
Jonathan Harta8625482015-09-08 16:14:56 -070031import java.util.Optional;
Jonathan Hart4cb39882015-08-12 23:50:55 -040032import java.util.Set;
33
34import static com.google.common.base.Preconditions.checkNotNull;
35
36/**
37 * Configuration object for BGP config.
38 */
39public class BgpConfig extends Config<ApplicationId> {
40
41 public static final String SPEAKERS = "bgpSpeakers";
42 public static final String CONNECT_POINT = "connectPoint";
Jonathan Harta8625482015-09-08 16:14:56 -070043 public static final String NAME = "name";
Jonathan Hart4cb39882015-08-12 23:50:55 -040044 public static final String PEERS = "peers";
Luca Prete8f2a3ce2016-03-29 16:13:01 -070045 public static final String VLAN = "vlan";
Jonathan Hart4cb39882015-08-12 23:50:55 -040046
Jonathan Hart4cb39882015-08-12 23:50:55 -040047 /**
48 * Gets the set of configured BGP speakers.
49 *
50 * @return BGP speakers
51 */
52 public Set<BgpSpeakerConfig> bgpSpeakers() {
53 Set<BgpSpeakerConfig> speakers = Sets.newHashSet();
54
Thomas Vachuska0a400ea2015-09-04 11:25:03 -070055 JsonNode speakersNode = object.get(SPEAKERS);
papazois7d39a742015-10-14 10:15:56 +030056
57 if (speakersNode == null) {
58 return speakers;
59 }
60
Jonathan Hart4cb39882015-08-12 23:50:55 -040061 speakersNode.forEach(jsonNode -> {
62 Set<IpAddress> listenAddresses = Sets.newHashSet();
63 jsonNode.path(PEERS).forEach(addressNode ->
Jonathan Harta8625482015-09-08 16:14:56 -070064 listenAddresses.add(IpAddress.valueOf(addressNode.asText()))
Jonathan Hart4cb39882015-08-12 23:50:55 -040065 );
Jonathan Harta8625482015-09-08 16:14:56 -070066
67 Optional<String> name;
68 if (jsonNode.get(NAME) == null) {
69 name = Optional.empty();
70 } else {
71 name = Optional.of(jsonNode.get(NAME).asText());
72 }
73
Luca Prete8f2a3ce2016-03-29 16:13:01 -070074 VlanId vlan = getVlan(jsonNode);
75
Jonathan Harta8625482015-09-08 16:14:56 -070076 speakers.add(new BgpSpeakerConfig(name,
Luca Prete8f2a3ce2016-03-29 16:13:01 -070077 vlan,
Jonathan Hart4cb39882015-08-12 23:50:55 -040078 ConnectPoint.deviceConnectPoint(jsonNode.path(CONNECT_POINT).asText()),
79 listenAddresses));
80 });
81
82 return speakers;
83 }
84
Luca Prete8f2a3ce2016-03-29 16:13:01 -070085 // If configured, it retreives a VLAN Id from a BGP speaker node
86 private VlanId getVlan(JsonNode node) {
87 VlanId vlan = VlanId.NONE;
88 if (!node.path(VLAN).isMissingNode()) {
89 vlan = VlanId.vlanId(node.path(VLAN).asText());
90 }
91 return vlan;
92 }
93
Jonathan Hart4cb39882015-08-12 23:50:55 -040094 /**
papazois7d39a742015-10-14 10:15:56 +030095 * Examines whether a name of BGP speaker exists in configuration.
96 *
97 * @param name name of BGP speaker being search
98 * @return speaker
99 */
100 public BgpSpeakerConfig getSpeakerWithName(String name) {
101 for (BgpConfig.BgpSpeakerConfig speaker : bgpSpeakers()) {
Sho SHIMIZUef7e2902016-02-12 18:38:29 -0800102 if (speaker.name().filter(name::equals).isPresent()) {
papazois7d39a742015-10-14 10:15:56 +0300103 return speaker;
104 }
105 }
106 return null;
107 }
108
109 /**
110 * Adds BGP speaker to configuration.
111 *
112 * @param speaker BGP speaker configuration entry
113 */
114 public void addSpeaker(BgpSpeakerConfig speaker) {
115 ObjectNode speakerNode = JsonNodeFactory.instance.objectNode();
116
117 speakerNode.put(NAME, speaker.name().get());
118
Luca Prete8f2a3ce2016-03-29 16:13:01 -0700119 speakerNode.put(VLAN, speaker.vlan().toString());
120
papazois7d39a742015-10-14 10:15:56 +0300121 speakerNode.put(CONNECT_POINT, speaker.connectPoint().elementId().toString()
122 + "/" + speaker.connectPoint().port().toString());
123
124 ArrayNode peersNode = speakerNode.putArray(PEERS);
125 for (IpAddress peerAddress: speaker.peers()) {
126 peersNode.add(peerAddress.toString());
127 }
128
129 ArrayNode speakersArray = bgpSpeakers().isEmpty() ?
130 initBgpConfiguration() : (ArrayNode) object.get(SPEAKERS);
131 speakersArray.add(speakerNode);
132 }
133
134 /**
135 * Removes BGP speaker from configuration.
136 *
137 * @param speakerName BGP speaker name
138 */
139 public void removeSpeaker(String speakerName) {
140 ArrayNode speakersArray = (ArrayNode) object.get(SPEAKERS);
141
142 for (int i = 0; i < speakersArray.size(); i++) {
143 if (speakersArray.get(i).hasNonNull(NAME) &&
144 speakersArray.get(i).get(NAME).asText().equals(speakerName)) {
145 speakersArray.remove(i);
146 return;
147 }
148 }
149 }
150
151 /**
152 * Adds peering address to BGP speaker.
153 *
154 * @param speakerName name of BGP speaker
155 * @param peerAddress peering address to be added
156 */
157 public void addPeerToSpeaker(String speakerName, IpAddress peerAddress) {
158 JsonNode speakersNode = object.get(SPEAKERS);
159 speakersNode.forEach(jsonNode -> {
160 if (jsonNode.hasNonNull(NAME) &&
161 jsonNode.get(NAME).asText().equals(speakerName)) {
162 ArrayNode peersNode = (ArrayNode) jsonNode.get(PEERS);
163 for (int i = 0; i < peersNode.size(); i++) {
164 if (peersNode.get(i).asText().equals(peerAddress.toString())) {
165 return; // Peer already exists.
166 }
167 }
168 peersNode.add(peerAddress.toString());
169 }
170 });
171 }
172
173 /**
174 * Finds BGP speaker peering with a given external peer.
175 *
Luca Prete8f2a3ce2016-03-29 16:13:01 -0700176 * @param peerAddress BGP peer address
177 * @return BGP speaker
papazois7d39a742015-10-14 10:15:56 +0300178 */
179 public BgpSpeakerConfig getSpeakerFromPeer(IpAddress peerAddress) {
180 for (BgpConfig.BgpSpeakerConfig speaker : bgpSpeakers()) {
181 if (speaker.peers().contains(peerAddress)) {
182 return speaker;
183 }
184 }
185 return null;
186 }
187
188 /**
189 * Removes peering address from BGP speaker.
190 *
191 * @param speaker BGP speaker configuration entries
192 * @param peerAddress peering address to be removed
193 */
194 public void removePeerFromSpeaker(BgpSpeakerConfig speaker, IpAddress peerAddress) {
195 JsonNode speakersNode = object.get(SPEAKERS);
196 speakersNode.forEach(jsonNode -> {
197 if (jsonNode.hasNonNull(NAME) &&
198 jsonNode.get(NAME).asText().equals(speaker.name().get())) {
199 ArrayNode peersNode = (ArrayNode) jsonNode.get(PEERS);
200 for (int i = 0; i < peersNode.size(); i++) {
201 if (peersNode.get(i).asText().equals(peerAddress.toString())) {
202 peersNode.remove(i);
203 return;
204 }
205 }
206 }
207 });
208 }
209
210 /**
211 * Creates empty configuration for BGP speakers.
212 *
213 * @return empty array of BGP speakers
214 */
215 private ArrayNode initBgpConfiguration() {
216 return object.putArray(SPEAKERS);
217 }
218
219
220 /**
Jonathan Hart4cb39882015-08-12 23:50:55 -0400221 * Configuration for a BGP speaker.
222 */
223 public static class BgpSpeakerConfig {
224
Jonathan Harta8625482015-09-08 16:14:56 -0700225 private Optional<String> name;
Luca Prete8f2a3ce2016-03-29 16:13:01 -0700226 private VlanId vlanId;
Jonathan Hart4cb39882015-08-12 23:50:55 -0400227 private ConnectPoint connectPoint;
228 private Set<IpAddress> peers;
229
Luca Prete8f2a3ce2016-03-29 16:13:01 -0700230 public BgpSpeakerConfig(Optional<String> name, VlanId vlanId,
231 ConnectPoint connectPoint, Set<IpAddress> peers) {
Jonathan Harta8625482015-09-08 16:14:56 -0700232 this.name = checkNotNull(name);
Luca Prete8f2a3ce2016-03-29 16:13:01 -0700233 this.vlanId = checkNotNull(vlanId);
Jonathan Hart4cb39882015-08-12 23:50:55 -0400234 this.connectPoint = checkNotNull(connectPoint);
235 this.peers = checkNotNull(peers);
236 }
237
Jonathan Harta8625482015-09-08 16:14:56 -0700238 public Optional<String> name() {
239 return name;
240 }
241
Luca Prete8f2a3ce2016-03-29 16:13:01 -0700242 public VlanId vlan() {
243 return vlanId;
244 }
245
Jonathan Hart4cb39882015-08-12 23:50:55 -0400246 public ConnectPoint connectPoint() {
247 return connectPoint;
248 }
249
250 public Set<IpAddress> peers() {
251 return peers;
252 }
papazois7d39a742015-10-14 10:15:56 +0300253
254 /**
255 * Examines if BGP peer is connected.
256 *
257 * @param peer IP address of peer
258 * @return result of search
259 */
260 public boolean isConnectedToPeer(IpAddress peer) {
261 for (final IpAddress entry : peers()) {
262 if (entry.equals(peer)) {
263 return true;
264 }
265 }
266 return false;
267 }
268
269 @Override
270 public boolean equals(Object obj) {
271 if (this == obj) {
272 return true;
273 }
274 if (obj instanceof BgpSpeakerConfig) {
275 final BgpSpeakerConfig that = (BgpSpeakerConfig) obj;
276 return Objects.equals(this.name, that.name) &&
Luca Prete8f2a3ce2016-03-29 16:13:01 -0700277 Objects.equals(this.vlanId, that.vlanId) &&
papazois7d39a742015-10-14 10:15:56 +0300278 Objects.equals(this.connectPoint, that.connectPoint) &&
279 Objects.equals(this.peers, that.peers);
280 }
281 return false;
282 }
283
284 @Override
285 public int hashCode() {
Luca Prete8f2a3ce2016-03-29 16:13:01 -0700286 return Objects.hash(name, vlanId, connectPoint, peers);
papazois7d39a742015-10-14 10:15:56 +0300287 }
Jonathan Hart4cb39882015-08-12 23:50:55 -0400288 }
289}