ONOS-734 Add unit tests for 4 Octets AS numbers in SDN-IP

 * Fix a bug in the storing, handling and verification of the AS numbers
   with 4 octet AS capability is used.

 * Add an unit test to test the decoding and parsing of supported
   BGP Capabilities: Multiprotocol Extensions AFI/SAFI, and 4 octet AS.

 * Minor refactoring of the BGP unit test framework.

Change-Id: I474b356bc00369c307ac0c5c214b065c1cc0c52c
diff --git a/apps/sdnip/src/main/java/org/onosproject/sdnip/bgp/BgpOpen.java b/apps/sdnip/src/main/java/org/onosproject/sdnip/bgp/BgpOpen.java
index d15a669..93ef852 100644
--- a/apps/sdnip/src/main/java/org/onosproject/sdnip/bgp/BgpOpen.java
+++ b/apps/sdnip/src/main/java/org/onosproject/sdnip/bgp/BgpOpen.java
@@ -101,32 +101,6 @@
 
         // Remote AS number
         long remoteAs = message.readUnsignedShort();
-        //
-        // Verify that the AS number is same for all other BGP Sessions
-        // NOTE: This check applies only for our use-case where all BGP
-        // sessions are iBGP.
-        //
-        for (BgpSession bs : bgpSession.getBgpSessionManager().getBgpSessions()) {
-            if ((bs.remoteInfo().asNumber() != 0) &&
-                (remoteAs != bs.remoteInfo().asNumber())) {
-                log.debug("BGP RX OPEN Error from {}: Bad Peer AS {}. " +
-                          "Expected {}",
-                          bgpSession.remoteInfo().address(), remoteAs,
-                          bs.remoteInfo().asNumber());
-                //
-                // ERROR: Bad Peer AS
-                //
-                // Send NOTIFICATION and close the connection
-                int errorCode = OpenMessageError.ERROR_CODE;
-                int errorSubcode = OpenMessageError.BAD_PEER_AS;
-                ChannelBuffer txMessage =
-                    BgpNotification.prepareBgpNotification(errorCode,
-                                                           errorSubcode, null);
-                ctx.getChannel().write(txMessage);
-                bgpSession.closeSession(ctx);
-                return;
-            }
-        }
         bgpSession.remoteInfo().setAsNumber(remoteAs);
         //
         // NOTE: Currently, the local AS number is always set to the remote AS.
@@ -194,16 +168,63 @@
             return;
         }
 
+        //
+        // NOTE: Prepare the BGP OPEN message before the original local AS
+        // is overwritten by the 4-octet AS number
+        //
+        ChannelBuffer txOpenMessage = prepareBgpOpen(bgpSession.localInfo());
+
+        //
+        // Use the 4-octet AS number in lieu of the "My AS" field
+        // See RFC 6793, Section 4.1, second paragraph.
+        //
+        if (bgpSession.remoteInfo().as4OctetCapability()) {
+            long as4Number = bgpSession.remoteInfo().as4Number();
+            bgpSession.remoteInfo().setAsNumber(as4Number);
+            bgpSession.localInfo().setAsNumber(as4Number);
+        }
+
+        //
+        // Verify that the AS number is same for all other BGP Sessions
+        // NOTE: This check applies only for our use-case where all BGP
+        // sessions are iBGP.
+        //
+        for (BgpSession bs : bgpSession.getBgpSessionManager().getBgpSessions()) {
+            if ((bs.remoteInfo().asNumber() != 0) &&
+                (bgpSession.remoteInfo().asNumber() !=
+                 bs.remoteInfo().asNumber())) {
+                log.debug("BGP RX OPEN Error from {}: Bad Peer AS {}. " +
+                          "Expected {}",
+                          bgpSession.remoteInfo().address(),
+                          bgpSession.remoteInfo().asNumber(),
+                          bs.remoteInfo().asNumber());
+                //
+                // ERROR: Bad Peer AS
+                //
+                // Send NOTIFICATION and close the connection
+                int errorCode = OpenMessageError.ERROR_CODE;
+                int errorSubcode = OpenMessageError.BAD_PEER_AS;
+                ChannelBuffer txMessage =
+                    BgpNotification.prepareBgpNotification(errorCode,
+                                                           errorSubcode, null);
+                ctx.getChannel().write(txMessage);
+                bgpSession.closeSession(ctx);
+                return;
+            }
+        }
+
         log.debug("BGP RX OPEN message from {}: " +
                   "BGPv{} AS {} BGP-ID {} Holdtime {}",
-                  bgpSession.remoteInfo().address(), remoteBgpVersion,
-                  remoteAs, remoteBgpId, remoteHoldtime);
+                  bgpSession.remoteInfo().address(),
+                  bgpSession.remoteInfo().bgpVersion(),
+                  bgpSession.remoteInfo().asNumber(),
+                  bgpSession.remoteInfo().bgpId(),
+                  bgpSession.remoteInfo().holdtime());
 
         // Send my OPEN followed by KEEPALIVE
-        ChannelBuffer txMessage = prepareBgpOpen(bgpSession.localInfo());
-        ctx.getChannel().write(txMessage);
+        ctx.getChannel().write(txOpenMessage);
         //
-        txMessage = BgpKeepalive.prepareBgpKeepalive();
+        ChannelBuffer txMessage = BgpKeepalive.prepareBgpKeepalive();
         ctx.getChannel().write(txMessage);
 
         // Start the KEEPALIVE timer
@@ -219,7 +240,7 @@
      * @param localInfo the BGP Session local information to use
      * @return the message to transmit (BGP header included)
      */
-    private static ChannelBuffer prepareBgpOpen(BgpSessionInfo localInfo) {
+    static ChannelBuffer prepareBgpOpen(BgpSessionInfo localInfo) {
         ChannelBuffer message =
             ChannelBuffers.buffer(BgpConstants.BGP_MESSAGE_MAX_LENGTH);
 
@@ -360,9 +381,6 @@
 
                     bgpSession.remoteInfo().setAs4OctetCapability();
                     bgpSession.remoteInfo().setAs4Number(as4Number);
-                    // Use the 4-octet AS number in lieu of the "My AS" field
-                    // See RFC 6793, Section 4.1, second paragraph.
-                    bgpSession.remoteInfo().setAsNumber(as4Number);
 
                     //
                     // Copy remote 4-octet AS Number Capabilities and AS
@@ -371,7 +389,6 @@
                     //
                     bgpSession.localInfo().setAs4OctetCapability();
                     bgpSession.localInfo().setAs4Number(as4Number);
-                    bgpSession.localInfo().setAsNumber(as4Number);
                     log.debug("BGP RX OPEN Capability: AS4 Number = {}",
                               as4Number);
                     break;
@@ -461,8 +478,8 @@
             message.writeByte(Capabilities.TYPE);               // Param type
             message.writeByte(Capabilities.MIN_LENGTH +
                               As4Octet.LENGTH);                 // Param len
-            message.writeByte(As4Octet.CODE);                   // Capab, code
-            message.writeByte(As4Octet.LENGTH);                 // Capab, len
+            message.writeByte(As4Octet.CODE);                   // Capab. code
+            message.writeByte(As4Octet.LENGTH);                 // Capab. len
             message.writeInt((int) localInfo.as4Number());
         }
         return message;