Shashikanth VH
Committed by Gerrit Code Review

[ONOS-3857] BGP send update flow specification message to peer.

Change-Id: Ieb727bfa89a6e7891e69c3070937aa9c98b28050
...@@ -19,6 +19,8 @@ import org.jboss.netty.channel.Channel; ...@@ -19,6 +19,8 @@ import org.jboss.netty.channel.Channel;
19 import org.onosproject.bgpio.exceptions.BgpParseException; 19 import org.onosproject.bgpio.exceptions.BgpParseException;
20 import org.onosproject.bgpio.protocol.BgpFactory; 20 import org.onosproject.bgpio.protocol.BgpFactory;
21 import org.onosproject.bgpio.protocol.BgpMessage; 21 import org.onosproject.bgpio.protocol.BgpMessage;
22 +import org.onosproject.bgpio.protocol.flowspec.BgpFlowSpecDetails;
23 +import org.onosproject.bgpio.protocol.flowspec.BgpFlowSpecPrefix;
22 import org.onosproject.bgpio.types.BgpValueType; 24 import org.onosproject.bgpio.types.BgpValueType;
23 25
24 /** 26 /**
...@@ -27,6 +29,23 @@ import org.onosproject.bgpio.types.BgpValueType; ...@@ -27,6 +29,23 @@ import org.onosproject.bgpio.types.BgpValueType;
27 */ 29 */
28 public interface BgpPeer { 30 public interface BgpPeer {
29 31
32 + enum FlowSpecOperation {
33 +
34 + /**
35 + * Signifies addition of flow specification rule.
36 + */
37 + ADD,
38 +
39 + /**
40 + * Signifies updation of flow specification rule.
41 + */
42 + UPDATE,
43 +
44 + /**
45 + * Signifies deletion of flow specification rule.
46 + */
47 + DELETE
48 + }
30 /** 49 /**
31 * Sets the associated Netty channel for this bgp peer. 50 * Sets the associated Netty channel for this bgp peer.
32 * 51 *
...@@ -110,4 +129,14 @@ public interface BgpPeer { ...@@ -110,4 +129,14 @@ public interface BgpPeer {
110 * @return sessionInfo bgp session info 129 * @return sessionInfo bgp session info
111 */ 130 */
112 BgpSessionInfo sessionInfo(); 131 BgpSessionInfo sessionInfo();
132 +
133 + /**
134 + * Updates flow specification rule.
135 + *
136 + * @param operType operation type add or delete or update
137 + * @param prefix prefix for the flow rule
138 + * @param flowSpec BGP flow specification components
139 + */
140 + void updateFlowSpec(FlowSpecOperation operType, BgpFlowSpecPrefix prefix,
141 + BgpFlowSpecDetails flowSpec);
113 } 142 }
......
...@@ -133,8 +133,16 @@ public class BgpControllerImpl implements BgpController { ...@@ -133,8 +133,16 @@ public class BgpControllerImpl implements BgpController {
133 boolean isLinkstate = false; 133 boolean isLinkstate = false;
134 while (listIterator.hasNext()) { 134 while (listIterator.hasNext()) {
135 BgpValueType attr = listIterator.next(); 135 BgpValueType attr = listIterator.next();
136 - if ((attr instanceof MpReachNlri) || (attr instanceof MpUnReachNlri)) { 136 + if (attr instanceof MpReachNlri) {
137 - isLinkstate = true; 137 + MpReachNlri mpReach = (MpReachNlri) attr;
138 + if (mpReach.bgpFlowSpecInfo() == null) {
139 + isLinkstate = true;
140 + }
141 + } else if (attr instanceof MpUnReachNlri) {
142 + MpUnReachNlri mpUnReach = (MpUnReachNlri) attr;
143 + if (mpUnReach.bgpFlowSpecInfo() == null) {
144 + isLinkstate = true;
145 + }
138 } 146 }
139 } 147 }
140 if (isLinkstate) { 148 if (isLinkstate) {
......
...@@ -17,6 +17,13 @@ ...@@ -17,6 +17,13 @@
17 package org.onosproject.bgp.controller.impl; 17 package org.onosproject.bgp.controller.impl;
18 18
19 import com.google.common.base.MoreObjects; 19 import com.google.common.base.MoreObjects;
20 +import com.google.common.base.Preconditions;
21 +
22 +import java.util.ArrayList;
23 +import java.util.LinkedList;
24 +import java.util.Map;
25 +import java.util.Set;
26 +
20 import org.jboss.netty.channel.Channel; 27 import org.jboss.netty.channel.Channel;
21 import org.onlab.packet.IpAddress; 28 import org.onlab.packet.IpAddress;
22 import org.onosproject.bgp.controller.BgpController; 29 import org.onosproject.bgp.controller.BgpController;
...@@ -28,13 +35,23 @@ import org.onosproject.bgpio.protocol.BgpFactories; ...@@ -28,13 +35,23 @@ import org.onosproject.bgpio.protocol.BgpFactories;
28 import org.onosproject.bgpio.protocol.BgpFactory; 35 import org.onosproject.bgpio.protocol.BgpFactory;
29 import org.onosproject.bgpio.protocol.BgpLSNlri; 36 import org.onosproject.bgpio.protocol.BgpLSNlri;
30 import org.onosproject.bgpio.protocol.BgpMessage; 37 import org.onosproject.bgpio.protocol.BgpMessage;
38 +import org.onosproject.bgpio.protocol.flowspec.BgpFlowSpecDetails;
39 +import org.onosproject.bgpio.protocol.flowspec.BgpFlowSpecPrefix;
31 import org.onosproject.bgpio.protocol.linkstate.BgpLinkLsNlriVer4; 40 import org.onosproject.bgpio.protocol.linkstate.BgpLinkLsNlriVer4;
32 import org.onosproject.bgpio.protocol.linkstate.BgpNodeLSNlriVer4; 41 import org.onosproject.bgpio.protocol.linkstate.BgpNodeLSNlriVer4;
33 import org.onosproject.bgpio.protocol.linkstate.BgpPrefixIPv4LSNlriVer4; 42 import org.onosproject.bgpio.protocol.linkstate.BgpPrefixIPv4LSNlriVer4;
34 import org.onosproject.bgpio.protocol.linkstate.PathAttrNlriDetails; 43 import org.onosproject.bgpio.protocol.linkstate.PathAttrNlriDetails;
44 +import org.onosproject.bgpio.types.AsPath;
45 +import org.onosproject.bgpio.types.As4Path;
35 import org.onosproject.bgpio.types.BgpValueType; 46 import org.onosproject.bgpio.types.BgpValueType;
47 +import org.onosproject.bgpio.types.LocalPref;
48 +import org.onosproject.bgpio.types.Med;
36 import org.onosproject.bgpio.types.MpReachNlri; 49 import org.onosproject.bgpio.types.MpReachNlri;
37 import org.onosproject.bgpio.types.MpUnReachNlri; 50 import org.onosproject.bgpio.types.MpUnReachNlri;
51 +import org.onosproject.bgpio.types.MultiProtocolExtnCapabilityTlv;
52 +import org.onosproject.bgpio.types.Origin;
53 +import org.onosproject.bgpio.types.RouteDistinguisher;
54 +import org.onosproject.bgpio.util.Constants;
38 import org.slf4j.Logger; 55 import org.slf4j.Logger;
39 import org.slf4j.LoggerFactory; 56 import org.slf4j.LoggerFactory;
40 57
...@@ -65,6 +82,26 @@ public class BgpPeerImpl implements BgpPeer { ...@@ -65,6 +82,26 @@ public class BgpPeerImpl implements BgpPeer {
65 private BgpLocalRib bgplocalRibVpn; 82 private BgpLocalRib bgplocalRibVpn;
66 private AdjRibIn adjRib; 83 private AdjRibIn adjRib;
67 private VpnAdjRibIn vpnAdjRib; 84 private VpnAdjRibIn vpnAdjRib;
85 + private BgpFlowSpecRibOut flowSpecRibOut;
86 + private BgpFlowSpecRibOut vpnFlowSpecRibOut;
87 +
88 + /**
89 + * Returns the flowSpec RIB out.
90 + *
91 + * @return flow Specification RIB out
92 + */
93 + public BgpFlowSpecRibOut flowSpecRibOut() {
94 + return flowSpecRibOut;
95 + }
96 +
97 + /**
98 + * Returns the VPN flowSpec RIB out.
99 + *
100 + * @return VPN flow Specification RIB out
101 + */
102 + public BgpFlowSpecRibOut vpnFlowSpecRibOut() {
103 + return vpnFlowSpecRibOut;
104 + }
68 105
69 /** 106 /**
70 * Return the adjacency RIB-IN. 107 * Return the adjacency RIB-IN.
...@@ -104,8 +141,129 @@ public class BgpPeerImpl implements BgpPeer { ...@@ -104,8 +141,129 @@ public class BgpPeerImpl implements BgpPeer {
104 this.bgplocalRibVpn = bgpController.bgpLocalRibVpn(); 141 this.bgplocalRibVpn = bgpController.bgpLocalRibVpn();
105 this.adjRib = new AdjRibIn(); 142 this.adjRib = new AdjRibIn();
106 this.vpnAdjRib = new VpnAdjRibIn(); 143 this.vpnAdjRib = new VpnAdjRibIn();
144 + this.flowSpecRibOut = new BgpFlowSpecRibOut();
145 + this.vpnFlowSpecRibOut = new BgpFlowSpecRibOut();
107 } 146 }
108 147
148 + /**
149 + * Check if peer support capability.
150 + *
151 + * @param type capability type
152 + * @param afi address family identifier
153 + * @param sAfi subsequent address family identifier
154 + * @return true if capability is supported, otherwise false
155 + */
156 + public final boolean isCapabilitySupported(short type, short afi, byte sAfi) {
157 +
158 + List<BgpValueType> capability = sessionInfo.remoteBgpCapability();
159 + ListIterator<BgpValueType> listIterator = capability.listIterator();
160 +
161 + while (listIterator.hasNext()) {
162 + BgpValueType tlv = listIterator.next();
163 +
164 + if (tlv.getType() == type) {
165 + if (tlv.getType() == MultiProtocolExtnCapabilityTlv.TYPE) {
166 + MultiProtocolExtnCapabilityTlv temp = (MultiProtocolExtnCapabilityTlv) tlv;
167 + if ((temp.getAfi() == afi) && (temp.getSafi() == sAfi)) {
168 + return true;
169 + }
170 + }
171 + }
172 + }
173 + return false;
174 + }
175 +
176 + /**
177 + * Send flow specification update message to peer.
178 + *
179 + * @param operType operation type
180 + * @param flowSpec flow specification details
181 + */
182 + public final void sendFlowSpecUpdateMessageToPeer(FlowSpecOperation operType, BgpFlowSpecDetails flowSpec) {
183 +
184 + List<BgpValueType> attributesList = new LinkedList<>();
185 + byte sessionType = sessionInfo.isIbgpSession() ? (byte) 0 : (byte) 1;
186 + byte sAfi = Constants.SAFI_FLOWSPEC_VALUE;
187 +
188 + boolean isFsCapabilitySet = isCapabilitySupported(MultiProtocolExtnCapabilityTlv.TYPE,
189 + Constants.AFI_FLOWSPEC_VALUE,
190 + Constants.SAFI_FLOWSPEC_VALUE);
191 +
192 + boolean isVpnFsCapabilitySet = isCapabilitySupported(MultiProtocolExtnCapabilityTlv.TYPE,
193 + Constants.AFI_FLOWSPEC_VALUE,
194 + Constants.VPN_SAFI_FLOWSPEC_VALUE);
195 + if ((!isFsCapabilitySet) && (!isVpnFsCapabilitySet)) {
196 + log.debug("Peer do not support BGP flow spec capability", channel.getRemoteAddress());
197 + return;
198 + }
199 +
200 + if (isVpnFsCapabilitySet) {
201 + sAfi = Constants.VPN_SAFI_FLOWSPEC_VALUE;
202 + }
203 +
204 + attributesList.add(new Origin(sessionType));
205 +
206 + if (sessionType != 0) {
207 + // EBGP
208 + if (!bgpController.getConfig().getLargeASCapability()) {
209 + List<Short> aspathSet = new ArrayList<>();
210 + List<Short> aspathSeq = new ArrayList<>();
211 + aspathSeq.add((short) bgpController.getConfig().getAsNumber());
212 +
213 + AsPath asPath = new AsPath(aspathSet, aspathSeq);
214 + attributesList.add(asPath);
215 + } else {
216 + List<Integer> aspathSet = new ArrayList<>();
217 + List<Integer> aspathSeq = new ArrayList<>();
218 + aspathSeq.add(bgpController.getConfig().getAsNumber());
219 +
220 + As4Path as4Path = new As4Path(aspathSet, aspathSeq);
221 + attributesList.add(as4Path);
222 + }
223 + attributesList.add(new Med(0));
224 + } else {
225 + attributesList.add(new AsPath());
226 + attributesList.add(new Med(0));
227 + attributesList.add(new LocalPref(100));
228 + }
229 +
230 + // TODO: Update flow spec action
231 +
232 + if (operType == FlowSpecOperation.ADD) {
233 + attributesList.add(new MpReachNlri(flowSpec, Constants.AFI_FLOWSPEC_VALUE, sAfi));
234 + } else if (operType == FlowSpecOperation.DELETE) {
235 + attributesList.add(new MpUnReachNlri(flowSpec, Constants.AFI_FLOWSPEC_VALUE, sAfi));
236 + }
237 +
238 + BgpMessage msg = Controller.getBgpMessageFactory4().updateMessageBuilder()
239 + .setBgpPathAttributes(attributesList).build();
240 +
241 + log.debug("Sending Flow spec Update message to {}", channel.getRemoteAddress());
242 + channel.write(Collections.singletonList(msg));
243 + }
244 +
245 + @Override
246 + public void updateFlowSpec(FlowSpecOperation operType, BgpFlowSpecPrefix prefix, BgpFlowSpecDetails flowSpec) {
247 + Preconditions.checkNotNull(operType, "flow specification operation type cannot be null");
248 + Preconditions.checkNotNull(prefix, "flow specification prefix cannot be null");
249 + Preconditions.checkNotNull(flowSpec, "flow specification details cannot be null");
250 + Preconditions.checkNotNull(flowSpec.fsActionTlv(), "flow specification action cannot be null");
251 +
252 + if (operType == FlowSpecOperation.ADD) {
253 + if (flowSpec.routeDistinguisher() == null) {
254 + flowSpecRibOut.add(prefix, flowSpec);
255 + } else {
256 + vpnFlowSpecRibOut.add(flowSpec.routeDistinguisher(), prefix, flowSpec);
257 + }
258 + } else if (operType == FlowSpecOperation.DELETE) {
259 + if (flowSpec.routeDistinguisher() == null) {
260 + flowSpecRibOut.delete(prefix);
261 + } else {
262 + vpnFlowSpecRibOut.delete(flowSpec.routeDistinguisher(), prefix);
263 + }
264 + }
265 + sendFlowSpecUpdateMessageToPeer(operType, flowSpec);
266 + }
109 267
110 @Override 268 @Override
111 public void buildAdjRibIn(List<BgpValueType> pathAttr) throws BgpParseException { 269 public void buildAdjRibIn(List<BgpValueType> pathAttr) throws BgpParseException {
...@@ -255,12 +413,47 @@ public class BgpPeerImpl implements BgpPeer { ...@@ -255,12 +413,47 @@ public class BgpPeerImpl implements BgpPeer {
255 localRibVpn.localRibUpdate(vpnAdjacencyRib()); 413 localRibVpn.localRibUpdate(vpnAdjacencyRib());
256 } 414 }
257 415
416 + /**
417 + * Update peer flow specification RIB on peer disconnect.
418 + *
419 + */
420 + public void updateFlowSpecOnPeerDisconnect() {
421 +
422 + boolean isCapabilitySet = isCapabilitySupported(MultiProtocolExtnCapabilityTlv.TYPE,
423 + Constants.AFI_FLOWSPEC_VALUE,
424 + Constants.SAFI_FLOWSPEC_VALUE);
425 + if (isCapabilitySet) {
426 + Set<BgpFlowSpecPrefix> flowSpecKeys = flowSpecRibOut.flowSpecTree().keySet();
427 + for (BgpFlowSpecPrefix key : flowSpecKeys) {
428 + BgpFlowSpecDetails flowSpecDetails = flowSpecRibOut.flowSpecTree().get(key);
429 + sendFlowSpecUpdateMessageToPeer(FlowSpecOperation.DELETE, flowSpecDetails);
430 + }
431 + }
432 +
433 + boolean isVpnCapabilitySet = isCapabilitySupported(MultiProtocolExtnCapabilityTlv.TYPE,
434 + Constants.AFI_FLOWSPEC_VALUE,
435 + Constants.VPN_SAFI_FLOWSPEC_VALUE);
436 + if (isVpnCapabilitySet) {
437 + Set<RouteDistinguisher> flowSpecKeys = vpnFlowSpecRibOut.vpnFlowSpecTree().keySet();
438 + for (RouteDistinguisher key : flowSpecKeys) {
439 + Map<BgpFlowSpecPrefix, BgpFlowSpecDetails> fsTree = vpnFlowSpecRibOut.vpnFlowSpecTree().get(key);
440 +
441 + Set<BgpFlowSpecPrefix> fsKeys = fsTree.keySet();
442 + for (BgpFlowSpecPrefix fsKey : fsKeys) {
443 + BgpFlowSpecDetails flowSpecDetails = vpnFlowSpecRibOut.flowSpecTree().get(fsKey);
444 + sendFlowSpecUpdateMessageToPeer(FlowSpecOperation.DELETE, flowSpecDetails);
445 + }
446 + }
447 + }
448 + }
449 +
258 // ************************ 450 // ************************
259 // Channel related 451 // Channel related
260 // ************************ 452 // ************************
261 453
262 @Override 454 @Override
263 public final void disconnectPeer() { 455 public final void disconnectPeer() {
456 + this.updateFlowSpecOnPeerDisconnect();
264 this.channel.close(); 457 this.channel.close();
265 } 458 }
266 459
......