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