aboutsummaryrefslogtreecommitdiffstats
path: root/framework/src/onos/bgp/ctl/src/test/java/org/onosproject/bgp/BgpPeerFrameDecoderTest.java
blob: 7767053f53c76e20c400f9ea6c5d89c9bbc8f024 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
/*
 * Copyright 2014-2015 Open Networking Laboratory
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.onosproject.bgp;

import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.handler.codec.frame.FrameDecoder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.concurrent.CountDownLatch;

/**
 * Class to decode the message received.
 */
public class BgpPeerFrameDecoderTest extends FrameDecoder {
    static final byte OPEN_MSG_TYPE = 0x1;
    static final byte KEEPALIVE_MSG_TYPE = 0x4;
    static final byte UPDATE_MSG_TYPE = 0x2;
    static final byte NOTIFICATION_MSG_TYPE = 0x3;
    static final int MINIMUM_COMMON_HEADER_LENGTH = 19;
    static final int MINIMUM_OPEN_MSG_LENGTH = 29;
    static final int MINIMUM_HEADER_MARKER_LENGTH = 16;
    static final int HEADER_AND_MSG_LEN = 18;

    protected static final Logger log = LoggerFactory
            .getLogger(BgpPeerFrameDecoderTest.class);
    final CountDownLatch receivedOpenMessageLatch = new CountDownLatch(1);
    final CountDownLatch receivedKeepaliveMessageLatch = new CountDownLatch(1);
    final CountDownLatch receivedNotificationMessageLatch = new CountDownLatch(1);

    @Override
    protected Object decode(ChannelHandlerContext ctx,
                            Channel channel,
                            ChannelBuffer cb) throws Exception {

        if (cb.readableBytes() < MINIMUM_COMMON_HEADER_LENGTH) {
            log.debug("Error: Packet length is less then minimum length");
            return null;
        }

        byte[] marker = new byte[MINIMUM_HEADER_MARKER_LENGTH];
        cb.readBytes(marker);
        for (int i = 0; i < marker.length; i++) {
            if (marker[i] != (byte) 0xff) {
                log.debug("Error: Marker must be set all ones");
                ctx.getChannel().close();
                return null;
            }
        }

        short length = cb.readShort();
        if (length < MINIMUM_COMMON_HEADER_LENGTH) {
            log.debug("Error: Bad message length");
            ctx.getChannel().close();
            return null;
        }

        if (length != (cb.readableBytes() + HEADER_AND_MSG_LEN)) {
            log.debug("Error: Bad message length");
            ctx.getChannel().close();
            return null;
        }

        byte type = cb.readByte();
        int len = length - MINIMUM_COMMON_HEADER_LENGTH;

        ChannelBuffer message = cb.readBytes(len);

        switch (type) {
        case OPEN_MSG_TYPE:
            processBgpOpen(ctx, message);
            break;
        case UPDATE_MSG_TYPE:
            break;
        case NOTIFICATION_MSG_TYPE:
            processBgpNotification(ctx, message);
            break;
        case KEEPALIVE_MSG_TYPE:
            processBgpKeepalive(ctx, message);
            break;
        default:
            ctx.getChannel().close();
            return null;
        }

        return null;
    }

    /**
     * Processes BGP open message.
     *
     * @param ctx Channel handler context
     * @param message open message
     */
    private void processBgpOpen(ChannelHandlerContext ctx,
                                ChannelBuffer message) {
        int minLength =
            MINIMUM_OPEN_MSG_LENGTH - MINIMUM_COMMON_HEADER_LENGTH;
        if (message.readableBytes() < minLength) {
            log.debug("Error: Bad message length");
            ctx.getChannel().close();
            return;
        }

        message.readByte(); // read version
        message.readShort(); // read AS number
        message.readShort(); // read Hold timer
        message.readInt(); // read BGP Identifier
        // Optional Parameters
        int optParamLen = message.readUnsignedByte();
        if (message.readableBytes() < optParamLen) {
            log.debug("Error: Bad message length");
            ctx.getChannel().close();
            return;
        }
        message.readBytes(optParamLen);

        // Open message received
        receivedOpenMessageLatch.countDown();
    }

    /**
     * Processes BGP keepalive message.
     *
     * @param ctx Channel handler context
     * @param message keepalive message
     */
    private void processBgpKeepalive(ChannelHandlerContext ctx,
                                     ChannelBuffer message) {

        // Keepalive message received
        receivedKeepaliveMessageLatch.countDown();
    }

    /**
     * Processes BGP notification message.
     *
     * @param ctx Channel handler context
     * @param message notification message
     */
    private void processBgpNotification(ChannelHandlerContext ctx,
                                     ChannelBuffer message) {
        byte[] data;
        message.readByte(); //read error code
        message.readByte(); // read error sub code
        if (message.readableBytes() > 0) {
            data = new byte[message.readableBytes()];
            message.readBytes(data, 0, message.readableBytes());
        }

        // Notification message received
        receivedNotificationMessageLatch.countDown();
    }
}