Refactor the BGP code in the SDN-IP application:
* Resolves ONOS-476 * Moved the BGP message-specific processing from class BgpSession to per-message type classes: BgpKeepalive, BgpNotification, BgpOpen, BgpUpdate * Minor modifications in some of the methods or BGP-specific API to accomodate the above change. No functional changes. Change-Id: I95df128fa31c60397a279aaca25a487b7991a6e1
Showing
9 changed files
with
519 additions
and
12 deletions
... | @@ -90,8 +90,9 @@ class BgpFrameDecoder extends FrameDecoder { | ... | @@ -90,8 +90,9 @@ class BgpFrameDecoder extends FrameDecoder { |
90 | int errorSubcode = | 90 | int errorSubcode = |
91 | MessageHeaderError.CONNECTION_NOT_SYNCHRONIZED; | 91 | MessageHeaderError.CONNECTION_NOT_SYNCHRONIZED; |
92 | ChannelBuffer txMessage = | 92 | ChannelBuffer txMessage = |
93 | - bgpSession.prepareBgpNotification(errorCode, errorSubcode, | 93 | + BgpNotification.prepareBgpNotification(errorCode, |
94 | - null); | 94 | + errorSubcode, |
95 | + null); | ||
95 | ctx.getChannel().write(txMessage); | 96 | ctx.getChannel().write(txMessage); |
96 | bgpSession.closeSession(ctx); | 97 | bgpSession.closeSession(ctx); |
97 | return null; | 98 | return null; |
... | @@ -114,7 +115,7 @@ class BgpFrameDecoder extends FrameDecoder { | ... | @@ -114,7 +115,7 @@ class BgpFrameDecoder extends FrameDecoder { |
114 | // | 115 | // |
115 | // Send NOTIFICATION and close the connection | 116 | // Send NOTIFICATION and close the connection |
116 | ChannelBuffer txMessage = | 117 | ChannelBuffer txMessage = |
117 | - bgpSession.prepareBgpNotificationBadMessageLength(length); | 118 | + BgpNotification.prepareBgpNotificationBadMessageLength(length); |
118 | ctx.getChannel().write(txMessage); | 119 | ctx.getChannel().write(txMessage); |
119 | bgpSession.closeSession(ctx); | 120 | bgpSession.closeSession(ctx); |
120 | return null; | 121 | return null; |
... | @@ -145,16 +146,16 @@ class BgpFrameDecoder extends FrameDecoder { | ... | @@ -145,16 +146,16 @@ class BgpFrameDecoder extends FrameDecoder { |
145 | // | 146 | // |
146 | switch (type) { | 147 | switch (type) { |
147 | case BgpConstants.BGP_TYPE_OPEN: | 148 | case BgpConstants.BGP_TYPE_OPEN: |
148 | - bgpSession.processBgpOpen(ctx, message); | 149 | + BgpOpen.processBgpOpen(bgpSession, ctx, message); |
149 | break; | 150 | break; |
150 | case BgpConstants.BGP_TYPE_UPDATE: | 151 | case BgpConstants.BGP_TYPE_UPDATE: |
151 | - bgpSession.processBgpUpdate(ctx, message); | 152 | + BgpUpdate.processBgpUpdate(bgpSession, ctx, message); |
152 | break; | 153 | break; |
153 | case BgpConstants.BGP_TYPE_NOTIFICATION: | 154 | case BgpConstants.BGP_TYPE_NOTIFICATION: |
154 | - bgpSession.processBgpNotification(ctx, message); | 155 | + BgpNotification.processBgpNotification(bgpSession, ctx, message); |
155 | break; | 156 | break; |
156 | case BgpConstants.BGP_TYPE_KEEPALIVE: | 157 | case BgpConstants.BGP_TYPE_KEEPALIVE: |
157 | - bgpSession.processBgpKeepalive(ctx, message); | 158 | + BgpKeepalive.processBgpKeepalive(bgpSession, ctx, message); |
158 | break; | 159 | break; |
159 | default: | 160 | default: |
160 | // | 161 | // |
... | @@ -166,8 +167,8 @@ class BgpFrameDecoder extends FrameDecoder { | ... | @@ -166,8 +167,8 @@ class BgpFrameDecoder extends FrameDecoder { |
166 | ChannelBuffer data = ChannelBuffers.buffer(1); | 167 | ChannelBuffer data = ChannelBuffers.buffer(1); |
167 | data.writeByte(type); | 168 | data.writeByte(type); |
168 | ChannelBuffer txMessage = | 169 | ChannelBuffer txMessage = |
169 | - bgpSession.prepareBgpNotification(errorCode, errorSubcode, | 170 | + BgpNotification.prepareBgpNotification(errorCode, errorSubcode, |
170 | - data); | 171 | + data); |
171 | ctx.getChannel().write(txMessage); | 172 | ctx.getChannel().write(txMessage); |
172 | bgpSession.closeSession(ctx); | 173 | bgpSession.closeSession(ctx); |
173 | return null; | 174 | return null; | ... | ... |
1 | +/* | ||
2 | + * Copyright 2014 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 | +package org.onosproject.sdnip.bgp; | ||
17 | + | ||
18 | +import org.jboss.netty.buffer.ChannelBuffer; | ||
19 | +import org.jboss.netty.buffer.ChannelBuffers; | ||
20 | +import org.jboss.netty.channel.ChannelHandlerContext; | ||
21 | +import org.slf4j.Logger; | ||
22 | +import org.slf4j.LoggerFactory; | ||
23 | + | ||
24 | +/** | ||
25 | + * A class for handling BGP KEEPALIVE messages. | ||
26 | + */ | ||
27 | +final class BgpKeepalive { | ||
28 | + private static final Logger log = | ||
29 | + LoggerFactory.getLogger(BgpKeepalive.class); | ||
30 | + | ||
31 | + /** | ||
32 | + * Default constructor. | ||
33 | + * <p> | ||
34 | + * The constructor is private to prevent creating an instance of | ||
35 | + * this utility class. | ||
36 | + */ | ||
37 | + private BgpKeepalive() { | ||
38 | + } | ||
39 | + | ||
40 | + /** | ||
41 | + * Processes BGP KEEPALIVE message. | ||
42 | + * | ||
43 | + * @param bgpSession the BGP Session to use | ||
44 | + * @param ctx the Channel Handler Context | ||
45 | + * @param message the message to process | ||
46 | + */ | ||
47 | + static void processBgpKeepalive(BgpSession bgpSession, | ||
48 | + ChannelHandlerContext ctx, | ||
49 | + ChannelBuffer message) { | ||
50 | + if (message.readableBytes() + BgpConstants.BGP_HEADER_LENGTH != | ||
51 | + BgpConstants.BGP_KEEPALIVE_EXPECTED_LENGTH) { | ||
52 | + log.debug("BGP RX KEEPALIVE Error from {}: " + | ||
53 | + "Invalid total message length {}. Expected {}", | ||
54 | + bgpSession.getRemoteAddress(), | ||
55 | + message.readableBytes() + BgpConstants.BGP_HEADER_LENGTH, | ||
56 | + BgpConstants.BGP_KEEPALIVE_EXPECTED_LENGTH); | ||
57 | + // | ||
58 | + // ERROR: Bad Message Length | ||
59 | + // | ||
60 | + // Send NOTIFICATION and close the connection | ||
61 | + ChannelBuffer txMessage = | ||
62 | + BgpNotification.prepareBgpNotificationBadMessageLength( | ||
63 | + message.readableBytes() + BgpConstants.BGP_HEADER_LENGTH); | ||
64 | + ctx.getChannel().write(txMessage); | ||
65 | + bgpSession.closeSession(ctx); | ||
66 | + return; | ||
67 | + } | ||
68 | + | ||
69 | + // | ||
70 | + // Parse the KEEPALIVE message: nothing to do | ||
71 | + // | ||
72 | + log.trace("BGP RX KEEPALIVE message from {}", | ||
73 | + bgpSession.getRemoteAddress()); | ||
74 | + | ||
75 | + // Start the Session Timeout timer | ||
76 | + bgpSession.restartSessionTimeoutTimer(ctx); | ||
77 | + } | ||
78 | + | ||
79 | + /** | ||
80 | + * Prepares BGP KEEPALIVE message. | ||
81 | + * | ||
82 | + * @return the message to transmit (BGP header included) | ||
83 | + */ | ||
84 | + static ChannelBuffer prepareBgpKeepalive() { | ||
85 | + ChannelBuffer message = | ||
86 | + ChannelBuffers.buffer(BgpConstants.BGP_MESSAGE_MAX_LENGTH); | ||
87 | + | ||
88 | + // | ||
89 | + // Prepare the KEEPALIVE message payload: nothing to do | ||
90 | + // | ||
91 | + return BgpMessage.prepareBgpMessage(BgpConstants.BGP_TYPE_KEEPALIVE, | ||
92 | + message); | ||
93 | + } | ||
94 | +} |
1 | +/* | ||
2 | + * Copyright 2014 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 | +package org.onosproject.sdnip.bgp; | ||
17 | + | ||
18 | +import org.jboss.netty.buffer.ChannelBuffer; | ||
19 | +import org.jboss.netty.buffer.ChannelBuffers; | ||
20 | +import org.slf4j.Logger; | ||
21 | +import org.slf4j.LoggerFactory; | ||
22 | + | ||
23 | +/** | ||
24 | + * A class for preparing BGP messages. | ||
25 | + */ | ||
26 | +final class BgpMessage { | ||
27 | + private static final Logger log = | ||
28 | + LoggerFactory.getLogger(BgpMessage.class); | ||
29 | + | ||
30 | + /** | ||
31 | + * Default constructor. | ||
32 | + * <p> | ||
33 | + * The constructor is private to prevent creating an instance of | ||
34 | + * this utility class. | ||
35 | + */ | ||
36 | + private BgpMessage() { | ||
37 | + } | ||
38 | + | ||
39 | + /** | ||
40 | + * Prepares BGP message. | ||
41 | + * | ||
42 | + * @param type the BGP message type | ||
43 | + * @param payload the message payload to transmit (BGP header excluded) | ||
44 | + * @return the message to transmit (BGP header included) | ||
45 | + */ | ||
46 | + static ChannelBuffer prepareBgpMessage(int type, ChannelBuffer payload) { | ||
47 | + ChannelBuffer message = | ||
48 | + ChannelBuffers.buffer(BgpConstants.BGP_HEADER_LENGTH + | ||
49 | + payload.readableBytes()); | ||
50 | + | ||
51 | + // Write the marker | ||
52 | + for (int i = 0; i < BgpConstants.BGP_HEADER_MARKER_LENGTH; i++) { | ||
53 | + message.writeByte(0xff); | ||
54 | + } | ||
55 | + | ||
56 | + // Write the rest of the BGP header | ||
57 | + message.writeShort(BgpConstants.BGP_HEADER_LENGTH + | ||
58 | + payload.readableBytes()); | ||
59 | + message.writeByte(type); | ||
60 | + | ||
61 | + // Write the payload | ||
62 | + message.writeBytes(payload); | ||
63 | + return message; | ||
64 | + } | ||
65 | +} |
1 | +/* | ||
2 | + * Copyright 2014 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 | +package org.onosproject.sdnip.bgp; | ||
17 | + | ||
18 | +import org.jboss.netty.buffer.ChannelBuffer; | ||
19 | +import org.jboss.netty.buffer.ChannelBuffers; | ||
20 | +import org.jboss.netty.channel.ChannelHandlerContext; | ||
21 | +import org.onosproject.sdnip.bgp.BgpConstants.Notifications.MessageHeaderError; | ||
22 | +import org.slf4j.Logger; | ||
23 | +import org.slf4j.LoggerFactory; | ||
24 | + | ||
25 | +/** | ||
26 | + * A class for handling BGP NOTIFICATION messages. | ||
27 | + */ | ||
28 | +final class BgpNotification { | ||
29 | + private static final Logger log = | ||
30 | + LoggerFactory.getLogger(BgpNotification.class); | ||
31 | + | ||
32 | + /** | ||
33 | + * Default constructor. | ||
34 | + * <p> | ||
35 | + * The constructor is private to prevent creating an instance of | ||
36 | + * this utility class. | ||
37 | + */ | ||
38 | + private BgpNotification() { | ||
39 | + } | ||
40 | + | ||
41 | + /** | ||
42 | + * Processes BGP NOTIFICATION message. | ||
43 | + * | ||
44 | + * @param bgpSession the BGP Session to use | ||
45 | + * @param ctx the Channel Handler Context | ||
46 | + * @param message the message to process | ||
47 | + */ | ||
48 | + static void processBgpNotification(BgpSession bgpSession, | ||
49 | + ChannelHandlerContext ctx, | ||
50 | + ChannelBuffer message) { | ||
51 | + int minLength = | ||
52 | + BgpConstants.BGP_NOTIFICATION_MIN_LENGTH - BgpConstants.BGP_HEADER_LENGTH; | ||
53 | + if (message.readableBytes() < minLength) { | ||
54 | + log.debug("BGP RX NOTIFICATION Error from {}: " + | ||
55 | + "Message length {} too short. Must be at least {}", | ||
56 | + bgpSession.getRemoteAddress(), message.readableBytes(), | ||
57 | + minLength); | ||
58 | + // | ||
59 | + // ERROR: Bad Message Length | ||
60 | + // | ||
61 | + // NOTE: We do NOT send NOTIFICATION in response to a notification | ||
62 | + return; | ||
63 | + } | ||
64 | + | ||
65 | + // | ||
66 | + // Parse the NOTIFICATION message | ||
67 | + // | ||
68 | + int errorCode = message.readUnsignedByte(); | ||
69 | + int errorSubcode = message.readUnsignedByte(); | ||
70 | + int dataLength = message.readableBytes(); | ||
71 | + | ||
72 | + log.debug("BGP RX NOTIFICATION message from {}: Error Code {} " + | ||
73 | + "Error Subcode {} Data Length {}", | ||
74 | + bgpSession.getRemoteAddress(), errorCode, errorSubcode, | ||
75 | + dataLength); | ||
76 | + | ||
77 | + // | ||
78 | + // NOTE: If the peer sent a NOTIFICATION, we leave it to the peer to | ||
79 | + // close the connection. | ||
80 | + // | ||
81 | + | ||
82 | + // Start the Session Timeout timer | ||
83 | + bgpSession.restartSessionTimeoutTimer(ctx); | ||
84 | + } | ||
85 | + | ||
86 | + /** | ||
87 | + * Prepares BGP NOTIFICATION message. | ||
88 | + * | ||
89 | + * @param errorCode the BGP NOTIFICATION Error Code | ||
90 | + * @param errorSubcode the BGP NOTIFICATION Error Subcode if applicable, | ||
91 | + * otherwise BgpConstants.Notifications.ERROR_SUBCODE_UNSPECIFIC | ||
92 | + * @param data the BGP NOTIFICATION Data if applicable, otherwise null | ||
93 | + * @return the message to transmit (BGP header included) | ||
94 | + */ | ||
95 | + static ChannelBuffer prepareBgpNotification(int errorCode, | ||
96 | + int errorSubcode, | ||
97 | + ChannelBuffer data) { | ||
98 | + ChannelBuffer message = | ||
99 | + ChannelBuffers.buffer(BgpConstants.BGP_MESSAGE_MAX_LENGTH); | ||
100 | + | ||
101 | + // | ||
102 | + // Prepare the NOTIFICATION message payload | ||
103 | + // | ||
104 | + message.writeByte(errorCode); | ||
105 | + message.writeByte(errorSubcode); | ||
106 | + if (data != null) { | ||
107 | + message.writeBytes(data); | ||
108 | + } | ||
109 | + return BgpMessage.prepareBgpMessage(BgpConstants.BGP_TYPE_NOTIFICATION, | ||
110 | + message); | ||
111 | + } | ||
112 | + | ||
113 | + /** | ||
114 | + * Prepares BGP NOTIFICATION message: Bad Message Length. | ||
115 | + * | ||
116 | + * @param length the erroneous Length field | ||
117 | + * @return the message to transmit (BGP header included) | ||
118 | + */ | ||
119 | + static ChannelBuffer prepareBgpNotificationBadMessageLength(int length) { | ||
120 | + int errorCode = MessageHeaderError.ERROR_CODE; | ||
121 | + int errorSubcode = MessageHeaderError.BAD_MESSAGE_LENGTH; | ||
122 | + ChannelBuffer data = ChannelBuffers.buffer(2); | ||
123 | + data.writeShort(length); | ||
124 | + | ||
125 | + return prepareBgpNotification(errorCode, errorSubcode, data); | ||
126 | + } | ||
127 | +} |
1 | +/* | ||
2 | + * Copyright 2014 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 | +package org.onosproject.sdnip.bgp; | ||
17 | + | ||
18 | +import org.jboss.netty.buffer.ChannelBuffer; | ||
19 | +import org.jboss.netty.buffer.ChannelBuffers; | ||
20 | +import org.jboss.netty.channel.ChannelHandlerContext; | ||
21 | +import org.onlab.packet.Ip4Address; | ||
22 | +import org.onosproject.sdnip.bgp.BgpConstants.Notifications; | ||
23 | +import org.onosproject.sdnip.bgp.BgpConstants.Notifications.OpenMessageError; | ||
24 | +import org.slf4j.Logger; | ||
25 | +import org.slf4j.LoggerFactory; | ||
26 | + | ||
27 | +/** | ||
28 | + * A class for handling BGP OPEN messages. | ||
29 | + */ | ||
30 | +final class BgpOpen { | ||
31 | + private static final Logger log = LoggerFactory.getLogger(BgpOpen.class); | ||
32 | + | ||
33 | + /** | ||
34 | + * Default constructor. | ||
35 | + * <p> | ||
36 | + * The constructor is private to prevent creating an instance of | ||
37 | + * this utility class. | ||
38 | + */ | ||
39 | + private BgpOpen() { | ||
40 | + } | ||
41 | + | ||
42 | + /** | ||
43 | + * Processes BGP OPEN message. | ||
44 | + * | ||
45 | + * @param bgpSession the BGP Session to use | ||
46 | + * @param ctx the Channel Handler Context | ||
47 | + * @param message the message to process | ||
48 | + */ | ||
49 | + static void processBgpOpen(BgpSession bgpSession, | ||
50 | + ChannelHandlerContext ctx, | ||
51 | + ChannelBuffer message) { | ||
52 | + int minLength = | ||
53 | + BgpConstants.BGP_OPEN_MIN_LENGTH - BgpConstants.BGP_HEADER_LENGTH; | ||
54 | + if (message.readableBytes() < minLength) { | ||
55 | + log.debug("BGP RX OPEN Error from {}: " + | ||
56 | + "Message length {} too short. Must be at least {}", | ||
57 | + bgpSession.getRemoteAddress(), message.readableBytes(), | ||
58 | + minLength); | ||
59 | + // | ||
60 | + // ERROR: Bad Message Length | ||
61 | + // | ||
62 | + // Send NOTIFICATION and close the connection | ||
63 | + ChannelBuffer txMessage = | ||
64 | + BgpNotification.prepareBgpNotificationBadMessageLength( | ||
65 | + message.readableBytes() + BgpConstants.BGP_HEADER_LENGTH); | ||
66 | + ctx.getChannel().write(txMessage); | ||
67 | + bgpSession.closeSession(ctx); | ||
68 | + return; | ||
69 | + } | ||
70 | + | ||
71 | + // | ||
72 | + // Parse the OPEN message | ||
73 | + // | ||
74 | + // Remote BGP version | ||
75 | + int remoteBgpVersion = message.readUnsignedByte(); | ||
76 | + if (remoteBgpVersion != BgpConstants.BGP_VERSION) { | ||
77 | + log.debug("BGP RX OPEN Error from {}: " + | ||
78 | + "Unsupported BGP version {}. Should be {}", | ||
79 | + bgpSession.getRemoteAddress(), remoteBgpVersion, | ||
80 | + BgpConstants.BGP_VERSION); | ||
81 | + // | ||
82 | + // ERROR: Unsupported Version Number | ||
83 | + // | ||
84 | + // Send NOTIFICATION and close the connection | ||
85 | + int errorCode = OpenMessageError.ERROR_CODE; | ||
86 | + int errorSubcode = OpenMessageError.UNSUPPORTED_VERSION_NUMBER; | ||
87 | + ChannelBuffer data = ChannelBuffers.buffer(2); | ||
88 | + data.writeShort(BgpConstants.BGP_VERSION); | ||
89 | + ChannelBuffer txMessage = | ||
90 | + BgpNotification.prepareBgpNotification(errorCode, errorSubcode, | ||
91 | + data); | ||
92 | + ctx.getChannel().write(txMessage); | ||
93 | + bgpSession.closeSession(ctx); | ||
94 | + return; | ||
95 | + } | ||
96 | + bgpSession.setRemoteBgpVersion(remoteBgpVersion); | ||
97 | + | ||
98 | + // Remote AS number | ||
99 | + long remoteAs = message.readUnsignedShort(); | ||
100 | + // | ||
101 | + // Verify that the AS number is same for all other BGP Sessions | ||
102 | + // NOTE: This check applies only for our use-case where all BGP | ||
103 | + // sessions are iBGP. | ||
104 | + // | ||
105 | + for (BgpSession bs : bgpSession.getBgpSessionManager().getBgpSessions()) { | ||
106 | + if ((bs.getRemoteAs() != 0) && (remoteAs != bs.getRemoteAs())) { | ||
107 | + log.debug("BGP RX OPEN Error from {}: Bad Peer AS {}. " + | ||
108 | + "Expected {}", | ||
109 | + bgpSession.getRemoteAddress(), remoteAs, | ||
110 | + bs.getRemoteAs()); | ||
111 | + // | ||
112 | + // ERROR: Bad Peer AS | ||
113 | + // | ||
114 | + // Send NOTIFICATION and close the connection | ||
115 | + int errorCode = OpenMessageError.ERROR_CODE; | ||
116 | + int errorSubcode = OpenMessageError.BAD_PEER_AS; | ||
117 | + ChannelBuffer txMessage = | ||
118 | + BgpNotification.prepareBgpNotification(errorCode, | ||
119 | + errorSubcode, null); | ||
120 | + ctx.getChannel().write(txMessage); | ||
121 | + bgpSession.closeSession(ctx); | ||
122 | + return; | ||
123 | + } | ||
124 | + } | ||
125 | + bgpSession.setRemoteAs(remoteAs); | ||
126 | + | ||
127 | + // Remote Hold Time | ||
128 | + long remoteHoldtime = message.readUnsignedShort(); | ||
129 | + if ((remoteHoldtime != 0) && | ||
130 | + (remoteHoldtime < BgpConstants.BGP_KEEPALIVE_MIN_HOLDTIME)) { | ||
131 | + log.debug("BGP RX OPEN Error from {}: " + | ||
132 | + "Unacceptable Hold Time field {}. " + | ||
133 | + "Should be 0 or at least {}", | ||
134 | + bgpSession.getRemoteAddress(), remoteHoldtime, | ||
135 | + BgpConstants.BGP_KEEPALIVE_MIN_HOLDTIME); | ||
136 | + // | ||
137 | + // ERROR: Unacceptable Hold Time | ||
138 | + // | ||
139 | + // Send NOTIFICATION and close the connection | ||
140 | + int errorCode = OpenMessageError.ERROR_CODE; | ||
141 | + int errorSubcode = OpenMessageError.UNACCEPTABLE_HOLD_TIME; | ||
142 | + ChannelBuffer txMessage = | ||
143 | + BgpNotification.prepareBgpNotification(errorCode, errorSubcode, | ||
144 | + null); | ||
145 | + ctx.getChannel().write(txMessage); | ||
146 | + bgpSession.closeSession(ctx); | ||
147 | + return; | ||
148 | + } | ||
149 | + bgpSession.setRemoteHoldtime(remoteHoldtime); | ||
150 | + | ||
151 | + // Remote BGP Identifier | ||
152 | + Ip4Address remoteBgpId = | ||
153 | + Ip4Address.valueOf((int) message.readUnsignedInt()); | ||
154 | + bgpSession.setRemoteBgpId(remoteBgpId); | ||
155 | + | ||
156 | + // Optional Parameters | ||
157 | + int optParamLen = message.readUnsignedByte(); | ||
158 | + if (message.readableBytes() < optParamLen) { | ||
159 | + log.debug("BGP RX OPEN Error from {}: " + | ||
160 | + "Invalid Optional Parameter Length field {}. " + | ||
161 | + "Remaining Optional Parameters {}", | ||
162 | + bgpSession.getRemoteAddress(), optParamLen, | ||
163 | + message.readableBytes()); | ||
164 | + // | ||
165 | + // ERROR: Invalid Optional Parameter Length field: Unspecific | ||
166 | + // | ||
167 | + // Send NOTIFICATION and close the connection | ||
168 | + int errorCode = OpenMessageError.ERROR_CODE; | ||
169 | + int errorSubcode = Notifications.ERROR_SUBCODE_UNSPECIFIC; | ||
170 | + ChannelBuffer txMessage = | ||
171 | + BgpNotification.prepareBgpNotification(errorCode, errorSubcode, | ||
172 | + null); | ||
173 | + ctx.getChannel().write(txMessage); | ||
174 | + bgpSession.closeSession(ctx); | ||
175 | + return; | ||
176 | + } | ||
177 | + // NOTE: Parse the optional parameters (if needed) | ||
178 | + message.readBytes(optParamLen); // NOTE: data ignored | ||
179 | + | ||
180 | + log.debug("BGP RX OPEN message from {}: " + | ||
181 | + "BGPv{} AS {} BGP-ID {} Holdtime {}", | ||
182 | + bgpSession.getRemoteAddress(), remoteBgpVersion, remoteAs, | ||
183 | + remoteBgpId, remoteHoldtime); | ||
184 | + | ||
185 | + // Send my OPEN followed by KEEPALIVE | ||
186 | + ChannelBuffer txMessage = prepareBgpOpen(bgpSession); | ||
187 | + ctx.getChannel().write(txMessage); | ||
188 | + // | ||
189 | + txMessage = BgpKeepalive.prepareBgpKeepalive(); | ||
190 | + ctx.getChannel().write(txMessage); | ||
191 | + | ||
192 | + // Start the KEEPALIVE timer | ||
193 | + bgpSession.restartKeepaliveTimer(ctx); | ||
194 | + | ||
195 | + // Start the Session Timeout timer | ||
196 | + bgpSession.restartSessionTimeoutTimer(ctx); | ||
197 | + } | ||
198 | + | ||
199 | + /** | ||
200 | + * Prepares BGP OPEN message. | ||
201 | + * | ||
202 | + * @param bgpSession the BGP Session to use | ||
203 | + * @return the message to transmit (BGP header included) | ||
204 | + */ | ||
205 | + private static ChannelBuffer prepareBgpOpen(BgpSession bgpSession) { | ||
206 | + ChannelBuffer message = | ||
207 | + ChannelBuffers.buffer(BgpConstants.BGP_MESSAGE_MAX_LENGTH); | ||
208 | + | ||
209 | + // | ||
210 | + // Prepare the OPEN message payload | ||
211 | + // | ||
212 | + message.writeByte(bgpSession.getLocalBgpVersion()); | ||
213 | + message.writeShort((int) bgpSession.getLocalAs()); | ||
214 | + message.writeShort((int) bgpSession.getLocalHoldtime()); | ||
215 | + message.writeInt(bgpSession.getLocalBgpId().toInt()); | ||
216 | + message.writeByte(0); // No Optional Parameters | ||
217 | + return BgpMessage.prepareBgpMessage(BgpConstants.BGP_TYPE_OPEN, | ||
218 | + message); | ||
219 | + } | ||
220 | +} |
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
... | @@ -81,7 +81,7 @@ public class BgpRoutesListCommand extends AbstractShellCommand { | ... | @@ -81,7 +81,7 @@ public class BgpRoutesListCommand extends AbstractShellCommand { |
81 | 81 | ||
82 | // Print the routes | 82 | // Print the routes |
83 | if (foundBgpSession != null) { | 83 | if (foundBgpSession != null) { |
84 | - printRoutes(foundBgpSession.getBgpRibIn()); | 84 | + printRoutes(foundBgpSession.bgpRibIn().values()); |
85 | } else { | 85 | } else { |
86 | printRoutes(service.getBgpRoutes()); | 86 | printRoutes(service.getBgpRoutes()); |
87 | } | 87 | } | ... | ... |
... | @@ -303,7 +303,7 @@ public class BgpSessionManagerTest { | ... | @@ -303,7 +303,7 @@ public class BgpSessionManagerTest { |
303 | private Collection<BgpRouteEntry> waitForBgpRibIn(BgpSession bgpSession, | 303 | private Collection<BgpRouteEntry> waitForBgpRibIn(BgpSession bgpSession, |
304 | long expectedRoutes) | 304 | long expectedRoutes) |
305 | throws InterruptedException { | 305 | throws InterruptedException { |
306 | - Collection<BgpRouteEntry> bgpRibIn = bgpSession.getBgpRibIn(); | 306 | + Collection<BgpRouteEntry> bgpRibIn = bgpSession.bgpRibIn().values(); |
307 | 307 | ||
308 | final int maxChecks = 500; // Max wait of 5 seconds | 308 | final int maxChecks = 500; // Max wait of 5 seconds |
309 | for (int i = 0; i < maxChecks; i++) { | 309 | for (int i = 0; i < maxChecks; i++) { |
... | @@ -311,7 +311,7 @@ public class BgpSessionManagerTest { | ... | @@ -311,7 +311,7 @@ public class BgpSessionManagerTest { |
311 | break; | 311 | break; |
312 | } | 312 | } |
313 | Thread.sleep(10); | 313 | Thread.sleep(10); |
314 | - bgpRibIn = bgpSession.getBgpRibIn(); | 314 | + bgpRibIn = bgpSession.bgpRibIn().values(); |
315 | } | 315 | } |
316 | 316 | ||
317 | return bgpRibIn; | 317 | return bgpRibIn; | ... | ... |
-
Please register or login to post a comment