BGP peer up notification message

BMP sends peer up notification message to collection when BGP peers are connected

Change-Id: I87e5a7bd02451352e823e693a4334a3dc82582f3
diff --git a/apps/bgpmonitoring/app/src/main/java/org/onosproject/bgpmonitoring/type/BmpPeerUpNotification.java b/apps/bgpmonitoring/app/src/main/java/org/onosproject/bgpmonitoring/type/BmpPeerUpNotification.java
new file mode 100644
index 0000000..cba9f04
--- /dev/null
+++ b/apps/bgpmonitoring/app/src/main/java/org/onosproject/bgpmonitoring/type/BmpPeerUpNotification.java
@@ -0,0 +1,431 @@
+/*
+ * Copyright 2024-present Open Networking Foundation
+ *
+ * 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.
+ */
+
+ /*
+      0                   1                   2                   3
+      0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+     |                 Local Address (16 bytes)                      |
+     ~                                                               ~
+     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+     |         Local Port            |        Remote Port            |
+     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+     |                    Sent OPEN Message                          |
+     ~                                                               ~
+     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+     |                  Received OPEN Message                        |
+     ~                                                               ~
+     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+     |                 Information (variable)                        |
+     ~                                                               ~
+     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ */
+package org.onosproject.bgpmonitoring.type;
+
+import org.jboss.netty.buffer.ChannelBuffers;
+import com.google.common.base.MoreObjects;
+import org.onlab.packet.Deserializer;
+import org.onosproject.bgpio.exceptions.BgpParseException;
+import org.onosproject.bgpio.protocol.BgpMessage;
+import org.onosproject.bgpio.protocol.ver4.BgpMessageVer4;
+import org.onosproject.bgpio.types.BgpHeader;
+import org.onosproject.bgpmonitoring.PeerUpNotificationMessage;
+import org.onosproject.bgpmonitoring.BmpParseException;
+import org.onosproject.bgpmonitoring.PerPeer;
+
+import java.net.InetAddress;
+import java.util.Arrays;
+import java.util.Objects;
+import java.util.function.BiPredicate;
+import java.nio.ByteBuffer;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import static com.google.common.base.Preconditions.checkState;
+
+/**
+ * A message sent to indicate that a peering
+ * session has come up.  The message includes information regarding
+ * the data exchanged between the peers in their OPEN messages, as
+ * well as information about the peering TCP session itself.  In
+ * addition to being sent whenever a peer transitions to the
+ * Established state, a Peer Up Notification is sent for each peer in
+ * the Established state when the BMP session itself comes up.
+ * <p>
+ * Local Address: The local IP address associated with the peering
+ * TCP session.  It is 4 bytes long if an IPv4 address is carried in
+ * this field, as determined by the V flag (with the 12 most
+ * significant bytes zero-filled) and 16 bytes long if an IPv6
+ * address is carried in this field.
+ * <p>
+ * Local Port: The local port number associated with the peering TCP
+ * session, or 0 if no TCP session actually exists (see Section 8.2).
+ * <p>
+ * Remote Port: The remote port number associated with the peering
+ * TCP session, or 0 if no TCP session actually exists.
+ * <p>
+ * Sent OPEN Message: The full OPEN message transmitted by the
+ * monitored router to its peer.
+ * <p>
+ * Received OPEN Message: The full OPEN message received by the
+ * monitored router from its peer.
+ * Information: Information about the peer, using the Information TLV
+ * format.  Only the string type is defined in this
+ * context; it may be repeated.  Inclusion of the Information field
+ * is OPTIONAL.  Its presence or absence can be inferred by
+ * inspection of the Message Length in the common header.
+ */
+public final class BmpPeerUpNotification extends PeerUpNotificationMessage {
+
+    private static final Logger log = LoggerFactory.getLogger(BmpPeerUpNotification.class);
+
+    private PerPeer perPeer;
+
+    private InetAddress localAddress;
+
+    private int localPort;
+
+    private int remotePort;
+
+    private BgpMessage sentOpenMsg;
+
+    private BgpMessage receivedOpenMsg;
+
+    private byte[] information;
+
+
+    private BmpPeerUpNotification(Builder builder) {
+        this.perPeer = builder.perPeer;
+        this.localAddress = builder.localAddress;
+        this.localPort = builder.localPort;
+        this.remotePort = builder.remotePort;
+        this.sentOpenMsg = builder.sentOpenMsg;
+        this.receivedOpenMsg = builder.receivedOpenMsg;
+        this.information = builder.information;
+
+
+    }
+
+    /**
+     * Returns BMP Peer Header of BMP Message.
+     *
+     * @return BMP Peer Header of BMP Message
+     */
+    @Override
+    public PerPeer getPerPeer() {
+        return perPeer;
+    }
+
+    /**
+     * Returns local ip address.
+     *
+     * @return local ip address
+     */
+    public InetAddress getLocalAddress() {
+        return localAddress;
+    }
+
+    /**
+     * Returns local port number.
+     *
+     * @return local port number
+     */
+    public int getLocalPort() {
+        return localPort;
+    }
+
+    /**
+     * Returns remote port number.
+     *
+     * @return remote port number
+     */
+    public int getRemotePort() {
+        return remotePort;
+    }
+
+    /**
+     * Returns Bgp sent open message.
+     *
+     * @return Bgp sent open message
+     */
+    public BgpMessage getSentOpenMsg() {
+        return sentOpenMsg;
+    }
+
+    /**
+     * Returns Bgp received open message.
+     *
+     * @return Bgp received open message
+     */
+    public BgpMessage getReceivedOpenMsg() {
+        return receivedOpenMsg;
+    }
+
+    /**
+     * Returns BMP peer information.
+     *
+     * @return BMP peer information
+     */
+    public byte[] getInformation() {
+        return information;
+    }
+
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) {
+            return true;
+        }
+        if (o == null || getClass() != o.getClass()) {
+            return false;
+        }
+        BmpPeerUpNotification that = (BmpPeerUpNotification) o;
+        return localPort == that.localPort &&
+                remotePort == that.remotePort &&
+                Objects.equals(localAddress, that.localAddress) &&
+                Objects.equals(sentOpenMsg, that.sentOpenMsg) &&
+                Objects.equals(receivedOpenMsg, that.receivedOpenMsg) &&
+                Arrays.equals(information, that.information) &&
+                Objects.equals(perPeer, that.perPeer);
+    }
+
+    @Override
+    public int hashCode() {
+        int result = Objects.hash(localAddress, localPort, remotePort, sentOpenMsg,
+                receivedOpenMsg, perPeer);
+        result = 31 * result + Arrays.hashCode(information);
+        return result;
+    }
+
+    @Override
+    public String toString() {
+        return MoreObjects.toStringHelper(getClass())
+                .add("perPeer", perPeer)
+                .add("localAddress", localAddress)
+                .add("localPort", localPort)
+                .add("remotePort", remotePort)
+                .add("sentOpenMsg", sentOpenMsg)
+                .add("receivedOpenMsg", receivedOpenMsg)
+                .add("information", Arrays.toString(information))
+                .toString();
+    }
+
+    /**
+     * Data deserializer function for BMP peer up notification message.
+     *
+     * @return data deserializer function
+     */
+    public static Deserializer<BmpPeerUpNotification> deserializer() {
+        return (data, offset, length) -> {
+            BiPredicate<ByteBuffer, Integer> isValidBuffer = (b, l)
+                    -> b.hasRemaining() && b.remaining() >= l;
+
+            ByteBuffer bb = ByteBuffer.wrap(data, offset, length);
+            if (!isValidBuffer.test(bb, PEERUP_NOTIFICATION_HEADER_MIN_LENGTH +
+                    PerPeerPacket.PEER_HEADER_MIN_LENGTH)) {
+                throw new BmpParseException("Invalid bmp peer up notification message buffer size.");
+            }
+            byte[] perPeerBytes = new byte[PerPeerPacket.PEER_HEADER_MIN_LENGTH];
+            bb.get(perPeerBytes);
+
+            Builder builder = new Builder()
+                    .perPeer(PerPeerPacket.deserializer().deserialize(perPeerBytes,
+                            0, PerPeerPacket.PEER_HEADER_MIN_LENGTH));
+
+
+            if (builder.perPeer.isIpv6()) {
+                builder.localAddress(PerPeerPacket.toInetAddress(IPV6_ADDRS, bb));
+            } else {
+                bb.position(bb.position() + (IPV6_ADDRS - IPV4_ADDRS));
+                builder.localAddress(PerPeerPacket.toInetAddress(IPV4_ADDRS, bb));
+            }
+
+            builder.localPort(bb.getShort())
+                    .remotePort(bb.getShort());
+
+
+            if (bb.remaining() < (PADDING_BYTES + BGP_LENGTH_FIELD)) {
+                throw new BmpParseException("Invalid bmp peer up notification message buffer size.");
+            }
+
+            bb.position(bb.position() + PADDING_BYTES);
+            int msgLength = bb.getShort();
+            bb.position(bb.position() - (PADDING_BYTES + BGP_LENGTH_FIELD));
+
+            if (bb.remaining() < msgLength) {
+                throw new BmpParseException("Not enough readable bytes");
+            }
+            byte[] routeBytes = new byte[msgLength];
+            bb.get(routeBytes);
+            try {
+                builder.sentOpenMsg(BgpMessageVer4.READER.readFrom(ChannelBuffers.wrappedBuffer(routeBytes),
+                        new BgpHeader()));
+            } catch (BgpParseException ex) {
+                throw new BmpParseException(ex);
+            }
+
+            if (bb.remaining() < (PADDING_BYTES + BGP_LENGTH_FIELD)) {
+                throw new BmpParseException("Not enough readable bytes");
+            }
+
+            bb.position(bb.position() + PADDING_BYTES);
+            msgLength = bb.getShort();
+            bb.position(bb.position() - (PADDING_BYTES + BGP_LENGTH_FIELD));
+
+            if (bb.remaining() < msgLength) {
+                throw new BmpParseException("Not enough readable bytes");
+            }
+            routeBytes = new byte[msgLength];
+            bb.get(routeBytes);
+            try {
+                builder.receivedOpenMsg(BgpMessageVer4.READER.readFrom(ChannelBuffers.wrappedBuffer(routeBytes),
+                        new BgpHeader()));
+            } catch (BgpParseException ex) {
+                throw new BmpParseException(ex);
+            }
+
+            if (bb.remaining() > 0) {
+                byte[] information = new byte[bb.remaining()];
+                bb.get(information);
+                builder.information(information);
+
+            }
+
+            return builder.build();
+
+        };
+    }
+
+
+    /**
+     * Builder for BMP peer up notification message.
+     */
+    private static class Builder {
+
+
+        private PerPeer perPeer;
+
+        private InetAddress localAddress;
+
+        private int localPort;
+
+        private int remotePort;
+
+        private BgpMessage sentOpenMsg;
+
+        private BgpMessage receivedOpenMsg;
+
+        private byte[] information;
+
+        /**
+         * Setter bmp per peer header.
+         *
+         * @param perPeer bmp per peer header.
+         * @return this class builder.
+         */
+        public Builder perPeer(PerPeer perPeer) {
+            this.perPeer = perPeer;
+            return this;
+        }
+
+        /**
+         * Setter bgp local address.
+         *
+         * @param localAddress bgp local address.
+         * @return this class builder.
+         */
+        public Builder localAddress(InetAddress localAddress) {
+            this.localAddress = localAddress;
+            return this;
+        }
+
+
+        /**
+         * Setter bgp local port.
+         *
+         * @param localPort bgp local port.
+         * @return this class builder.
+         */
+        public Builder localPort(int localPort) {
+            this.localPort = localPort;
+            return this;
+        }
+
+        /**
+         * Setter bgp remote port.
+         *
+         * @param remotePort bgp remote port.
+         * @return this class builder.
+         */
+        public Builder remotePort(int remotePort) {
+            this.remotePort = remotePort;
+            return this;
+        }
+
+        /**
+         * Setter bgp send open message.
+         *
+         * @param sentOpenMsg bgp send open message.
+         * @return this class builder.
+         */
+        public Builder sentOpenMsg(BgpMessage sentOpenMsg) {
+            this.sentOpenMsg = sentOpenMsg;
+            return this;
+        }
+
+        /**
+         * Setter bgp receive open message.
+         *
+         * @param receivedOpenMsg bgp receive open message.
+         * @return this class builder.
+         */
+        public Builder receivedOpenMsg(BgpMessage receivedOpenMsg) {
+            this.receivedOpenMsg = receivedOpenMsg;
+            return this;
+        }
+
+        /**
+         * Setter bgp information message.
+         *
+         * @param information bgp information message.
+         * @return this class builder.
+         */
+        public Builder information(byte[] information) {
+            this.information = information;
+            return this;
+        }
+
+        /**
+         * Checks arguments for bmp peer up notification.
+         */
+        private void checkArguments() {
+            checkState(perPeer != null, "Invalid bmp per peer in peer up notification message.");
+            checkState(sentOpenMsg != null, "Invalid bgp send open message.");
+            checkState(receivedOpenMsg != null, "Invalid bgp receive open message.");
+        }
+
+        /**
+         * Builds BMP peer up notification message.
+         *
+         * @return BMP peer up notification message.
+         */
+        public BmpPeerUpNotification build() {
+            checkArguments();
+            return new BmpPeerUpNotification(this);
+        }
+    }
+}