Jonathan Hart

Port the BGP implementation of SDN-IP.

...@@ -126,6 +126,8 @@ public class Router implements RouteListener { ...@@ -126,6 +126,8 @@ public class Router implements RouteListener {
126 bgpIntentsSynchronizerExecutor = Executors.newSingleThreadExecutor( 126 bgpIntentsSynchronizerExecutor = Executors.newSingleThreadExecutor(
127 new ThreadFactoryBuilder() 127 new ThreadFactoryBuilder()
128 .setNameFormat("bgp-intents-synchronizer-%d").build()); 128 .setNameFormat("bgp-intents-synchronizer-%d").build());
129 +
130 + this.hostService.addListener(new InternalHostListener());
129 } 131 }
130 132
131 /** 133 /**
......
...@@ -10,6 +10,7 @@ import org.apache.felix.scr.annotations.ReferenceCardinality; ...@@ -10,6 +10,7 @@ import org.apache.felix.scr.annotations.ReferenceCardinality;
10 import org.onlab.onos.net.host.HostService; 10 import org.onlab.onos.net.host.HostService;
11 import org.onlab.onos.net.intent.IntentService; 11 import org.onlab.onos.net.intent.IntentService;
12 import org.onlab.onos.sdnip.RouteUpdate.Type; 12 import org.onlab.onos.sdnip.RouteUpdate.Type;
13 +import org.onlab.onos.sdnip.bgp.BgpSessionManager;
13 import org.onlab.onos.sdnip.config.SdnIpConfigReader; 14 import org.onlab.onos.sdnip.config.SdnIpConfigReader;
14 import org.onlab.packet.IpAddress; 15 import org.onlab.packet.IpAddress;
15 import org.onlab.packet.IpPrefix; 16 import org.onlab.packet.IpPrefix;
...@@ -32,6 +33,7 @@ public class SdnIp { ...@@ -32,6 +33,7 @@ public class SdnIp {
32 private SdnIpConfigReader config; 33 private SdnIpConfigReader config;
33 private PeerConnectivity peerConnectivity; 34 private PeerConnectivity peerConnectivity;
34 private Router router; 35 private Router router;
36 + private BgpSessionManager bgpSessionManager;
35 37
36 @Activate 38 @Activate
37 protected void activate() { 39 protected void activate() {
...@@ -48,6 +50,9 @@ public class SdnIp { ...@@ -48,6 +50,9 @@ public class SdnIp {
48 router = new Router(intentService, hostService, config, interfaceService); 50 router = new Router(intentService, hostService, config, interfaceService);
49 router.start(); 51 router.start();
50 52
53 + bgpSessionManager = new BgpSessionManager(router);
54 + bgpSessionManager.startUp(2000); // TODO
55 +
51 // TODO need to disable link discovery on external ports 56 // TODO need to disable link discovery on external ports
52 57
53 router.update(new RouteUpdate(Type.UPDATE, new RouteEntry( 58 router.update(new RouteUpdate(Type.UPDATE, new RouteEntry(
......
1 +package org.onlab.onos.sdnip.bgp;
2 +
3 +import org.jboss.netty.buffer.ChannelBuffer;
4 +import org.jboss.netty.buffer.ChannelBuffers;
5 +import org.jboss.netty.channel.Channel;
6 +import org.jboss.netty.channel.ChannelHandlerContext;
7 +import org.jboss.netty.handler.codec.frame.FrameDecoder;
8 +import org.onlab.onos.sdnip.bgp.BgpConstants.Notifications.MessageHeaderError;
9 +import org.slf4j.Logger;
10 +import org.slf4j.LoggerFactory;
11 +
12 +/**
13 + * Class for handling the decoding of the BGP messages.
14 + */
15 +class BgpFrameDecoder extends FrameDecoder {
16 + private static final Logger log =
17 + LoggerFactory.getLogger(BgpFrameDecoder.class);
18 +
19 + private final BgpSession bgpSession;
20 +
21 + /**
22 + * Constructor for a given BGP Session.
23 + *
24 + * @param bgpSession the BGP session state to use.
25 + */
26 + BgpFrameDecoder(BgpSession bgpSession) {
27 + this.bgpSession = bgpSession;
28 + }
29 +
30 + @Override
31 + protected Object decode(ChannelHandlerContext ctx,
32 + Channel channel,
33 + ChannelBuffer buf) throws Exception {
34 + //
35 + // NOTE: If we close the channel during the decoding, we might still
36 + // see some incoming messages while the channel closing is completed.
37 + //
38 + if (bgpSession.isClosed()) {
39 + return null;
40 + }
41 +
42 + log.trace("BGP Peer: decode(): remoteAddr = {} localAddr = {} " +
43 + "messageSize = {}",
44 + ctx.getChannel().getRemoteAddress(),
45 + ctx.getChannel().getLocalAddress(),
46 + buf.readableBytes());
47 +
48 + // Test for minimum length of the BGP message
49 + if (buf.readableBytes() < BgpConstants.BGP_HEADER_LENGTH) {
50 + // No enough data received
51 + return null;
52 + }
53 +
54 + //
55 + // Mark the current buffer position in case we haven't received
56 + // the whole message.
57 + //
58 + buf.markReaderIndex();
59 +
60 + //
61 + // Read and check the BGP message Marker field: it must be all ones
62 + // (See RFC 4271, Section 4.1)
63 + //
64 + byte[] marker = new byte[BgpConstants.BGP_HEADER_MARKER_LENGTH];
65 + buf.readBytes(marker);
66 + for (int i = 0; i < marker.length; i++) {
67 + if (marker[i] != (byte) 0xff) {
68 + log.debug("BGP RX Error: invalid marker {} at position {}",
69 + marker[i], i);
70 + //
71 + // ERROR: Connection Not Synchronized
72 + //
73 + // Send NOTIFICATION and close the connection
74 + int errorCode = MessageHeaderError.ERROR_CODE;
75 + int errorSubcode =
76 + MessageHeaderError.CONNECTION_NOT_SYNCHRONIZED;
77 + ChannelBuffer txMessage =
78 + bgpSession.prepareBgpNotification(errorCode, errorSubcode,
79 + null);
80 + ctx.getChannel().write(txMessage);
81 + bgpSession.closeChannel(ctx);
82 + return null;
83 + }
84 + }
85 +
86 + //
87 + // Read and check the BGP message Length field
88 + //
89 + int length = buf.readUnsignedShort();
90 + if ((length < BgpConstants.BGP_HEADER_LENGTH) ||
91 + (length > BgpConstants.BGP_MESSAGE_MAX_LENGTH)) {
92 + log.debug("BGP RX Error: invalid Length field {}. " +
93 + "Must be between {} and {}",
94 + length,
95 + BgpConstants.BGP_HEADER_LENGTH,
96 + BgpConstants.BGP_MESSAGE_MAX_LENGTH);
97 + //
98 + // ERROR: Bad Message Length
99 + //
100 + // Send NOTIFICATION and close the connection
101 + ChannelBuffer txMessage =
102 + bgpSession.prepareBgpNotificationBadMessageLength(length);
103 + ctx.getChannel().write(txMessage);
104 + bgpSession.closeChannel(ctx);
105 + return null;
106 + }
107 +
108 + //
109 + // Test whether the rest of the message is received:
110 + // So far we have read the Marker (16 octets) and the
111 + // Length (2 octets) fields.
112 + //
113 + int remainingMessageLen =
114 + length - BgpConstants.BGP_HEADER_MARKER_LENGTH - 2;
115 + if (buf.readableBytes() < remainingMessageLen) {
116 + // No enough data received
117 + buf.resetReaderIndex();
118 + return null;
119 + }
120 +
121 + //
122 + // Read the BGP message Type field, and process based on that type
123 + //
124 + int type = buf.readUnsignedByte();
125 + remainingMessageLen--; // Adjust after reading the type
126 + ChannelBuffer message = buf.readBytes(remainingMessageLen);
127 +
128 + //
129 + // Process the remaining of the message based on the message type
130 + //
131 + switch (type) {
132 + case BgpConstants.BGP_TYPE_OPEN:
133 + bgpSession.processBgpOpen(ctx, message);
134 + break;
135 + case BgpConstants.BGP_TYPE_UPDATE:
136 + bgpSession.processBgpUpdate(ctx, message);
137 + break;
138 + case BgpConstants.BGP_TYPE_NOTIFICATION:
139 + bgpSession.processBgpNotification(ctx, message);
140 + break;
141 + case BgpConstants.BGP_TYPE_KEEPALIVE:
142 + bgpSession.processBgpKeepalive(ctx, message);
143 + break;
144 + default:
145 + //
146 + // ERROR: Bad Message Type
147 + //
148 + // Send NOTIFICATION and close the connection
149 + int errorCode = MessageHeaderError.ERROR_CODE;
150 + int errorSubcode = MessageHeaderError.BAD_MESSAGE_TYPE;
151 + ChannelBuffer data = ChannelBuffers.buffer(1);
152 + data.writeByte(type);
153 + ChannelBuffer txMessage =
154 + bgpSession.prepareBgpNotification(errorCode, errorSubcode,
155 + data);
156 + ctx.getChannel().write(txMessage);
157 + bgpSession.closeChannel(ctx);
158 + return null;
159 + }
160 + return null;
161 + }
162 +}
1 +/**
2 + * Implementation of the BGP protocol.
3 + */
4 +package org.onlab.onos.sdnip.bgp;
...\ No newline at end of file ...\ No newline at end of file
...@@ -2,13 +2,15 @@ package org.onlab.packet; ...@@ -2,13 +2,15 @@ package org.onlab.packet;
2 2
3 import java.util.Arrays; 3 import java.util.Arrays;
4 4
5 +
6 +
5 /** 7 /**
6 * A class representing an IPv4 address. 8 * A class representing an IPv4 address.
7 * <p/> 9 * <p/>
8 * TODO this class is a clone of IpPrefix and still needs to be modified to 10 * TODO this class is a clone of IpPrefix and still needs to be modified to
9 * look more like an IpAddress. 11 * look more like an IpAddress.
10 */ 12 */
11 -public final class IpAddress { 13 +public final class IpAddress implements Comparable<IpAddress> {
12 14
13 // TODO a comparator for netmasks? E.g. for sorting by prefix match order. 15 // TODO a comparator for netmasks? E.g. for sorting by prefix match order.
14 16
...@@ -289,6 +291,13 @@ public final class IpAddress { ...@@ -289,6 +291,13 @@ public final class IpAddress {
289 } 291 }
290 292
291 @Override 293 @Override
294 + public int compareTo(IpAddress o) {
295 + Long lv = ((long) this.toRealInt()) & 0xffffffffL;
296 + Long rv = ((long) o.toRealInt()) & 0xffffffffL;
297 + return lv.compareTo(rv);
298 + }
299 +
300 + @Override
292 public int hashCode() { 301 public int hashCode() {
293 final int prime = 31; 302 final int prime = 31;
294 int result = 1; 303 int result = 1;
......