Move ipv4/ipv6 ByteBuf utilities to Ipv{4,6}Util
[bgpcep.git] / bmp / bmp-spi / src / main / java / org / opendaylight / protocol / bmp / spi / parser / AbstractBmpPerPeerMessageParser.java
1 /*
2  * Copyright (c) 2015 Cisco Systems, Inc. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8 package org.opendaylight.protocol.bmp.spi.parser;
9
10 import static com.google.common.base.Preconditions.checkArgument;
11 import static java.util.Objects.requireNonNull;
12
13 import io.netty.buffer.ByteBuf;
14 import org.opendaylight.bgp.concepts.RouteDistinguisherUtil;
15 import org.opendaylight.protocol.bgp.parser.spi.MessageRegistry;
16 import org.opendaylight.protocol.util.BitArray;
17 import org.opendaylight.protocol.util.ByteArray;
18 import org.opendaylight.protocol.util.Ipv4Util;
19 import org.opendaylight.protocol.util.Ipv6Util;
20 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.AsNumber;
21 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
22 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Timestamp;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bmp.message.rev180329.AdjRibInType;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bmp.message.rev180329.Peer.PeerDistinguisher;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bmp.message.rev180329.PeerType;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bmp.message.rev180329.peer.header.PeerHeader;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bmp.message.rev180329.peer.header.PeerHeaderBuilder;
28 import org.opendaylight.yangtools.concepts.Builder;
29 import org.opendaylight.yangtools.yang.binding.Notification;
30 import org.opendaylight.yangtools.yang.common.netty.ByteBufUtils;
31
32 public abstract class AbstractBmpPerPeerMessageParser<T extends Builder<?>> extends AbstractBmpMessageWithTlvParser<T> {
33     private static final int L_FLAG_POS = 1;
34     private static final int V_FLAG_POS = 0;
35     private static final int FLAGS_SIZE = 8;
36     private static final int PEER_DISTINGUISHER_SIZE = 8;
37     private static final int PER_PEER_HEADER_SIZE = 32;
38
39     private final MessageRegistry bgpMssageRegistry;
40
41     public AbstractBmpPerPeerMessageParser(final MessageRegistry bgpMssageRegistry) {
42         this(bgpMssageRegistry, null);
43     }
44
45     public AbstractBmpPerPeerMessageParser(final MessageRegistry bgpMssageRegistry, final BmpTlvRegistry tlvRegistry) {
46         super(tlvRegistry);
47         this.bgpMssageRegistry = requireNonNull(bgpMssageRegistry);
48     }
49
50     @Override
51     public void serializeMessageBody(final Notification message, final ByteBuf buffer) {
52         if (message
53                 instanceof org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bmp.message.rev180329
54                 .PeerHeader) {
55             final org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bmp.message.rev180329.PeerHeader
56                     messageWithPerPeerHeader = (org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bmp
57                     .message.rev180329.PeerHeader) message;
58             serializePerPeerHeader(messageWithPerPeerHeader.getPeerHeader(), buffer);
59         }
60     }
61
62     protected static PeerHeader parsePerPeerHeader(final ByteBuf bytes) {
63         checkArgument(bytes.readableBytes() >= PER_PEER_HEADER_SIZE);
64         final PeerHeaderBuilder phBuilder = new PeerHeaderBuilder();
65         final PeerType peerType = PeerType.forValue(bytes.readByte());
66         phBuilder.setType(peerType);
67         final BitArray flags = BitArray.valueOf(bytes, FLAGS_SIZE);
68         phBuilder.setAdjRibInType(AdjRibInType.forValue(flags.get(L_FLAG_POS) ? 1 : 0));
69         phBuilder.setIpv4(!flags.get(V_FLAG_POS));
70         switch (peerType) {
71             case L3vpn:
72                 phBuilder.setPeerDistinguisher(
73                         new PeerDistinguisher(RouteDistinguisherUtil.parseRouteDistinguisher(bytes)));
74                 break;
75             case Local:
76                 phBuilder.setPeerDistinguisher(
77                         new PeerDistinguisher(ByteArray.readBytes(bytes, PEER_DISTINGUISHER_SIZE)));
78                 break;
79             case Global:
80             default:
81                 bytes.skipBytes(PEER_DISTINGUISHER_SIZE);
82                 break;
83         }
84         if (phBuilder.isIpv4()) {
85             bytes.skipBytes(Ipv6Util.IPV6_LENGTH - Ipv4Util.IP4_LENGTH);
86             phBuilder.setAddress(new IpAddress(Ipv4Util.addressForByteBuf(bytes)));
87         } else {
88             phBuilder.setAddress(new IpAddress(Ipv6Util.addressForByteBuf(bytes)));
89         }
90         phBuilder.setAs(new AsNumber(ByteBufUtils.readUint32(bytes)));
91         phBuilder.setBgpId(Ipv4Util.addressForByteBuf(bytes));
92         phBuilder.setTimestampSec(new Timestamp(ByteBufUtils.readUint32(bytes)));
93         phBuilder.setTimestampMicro(new Timestamp(ByteBufUtils.readUint32(bytes)));
94         return phBuilder.build();
95     }
96
97     protected void serializePerPeerHeader(final PeerHeader peerHeader, final ByteBuf output) {
98         checkArgument(peerHeader != null, "Per-peer header cannot be null.");
99         final PeerType peerType = peerHeader.getType();
100         output.writeByte(peerType.getIntValue());
101         final BitArray flags = new BitArray(FLAGS_SIZE);
102         flags.set(L_FLAG_POS, peerHeader.getAdjRibInType().getIntValue() != 0);
103         flags.set(V_FLAG_POS, !peerHeader.isIpv4());
104         flags.toByteBuf(output);
105         final PeerDistinguisher peerDistinguisher = peerHeader.getPeerDistinguisher();
106         switch (peerType) {
107             case L3vpn:
108                 RouteDistinguisherUtil.serializeRouteDistinquisher(peerDistinguisher.getRouteDistinguisher(), output);
109                 break;
110             case Local:
111                 output.writeBytes(peerDistinguisher.getBinary());
112                 break;
113             case Global:
114             default:
115                 output.writeZero(PEER_DISTINGUISHER_SIZE);
116                 break;
117         }
118         if (peerHeader.isIpv4()) {
119             output.writeZero(Ipv6Util.IPV6_LENGTH - Ipv4Util.IP4_LENGTH);
120             Ipv4Util.writeIpv4Address(peerHeader.getAddress().getIpv4Address(), output);
121         } else {
122             Ipv6Util.writeIpv6Address(peerHeader.getAddress().getIpv6Address(), output);
123         }
124         ByteBufUtils.write(output, peerHeader.getAs().getValue());
125         Ipv4Util.writeIpv4Address(peerHeader.getBgpId(), output);
126
127         final Timestamp stampSec = peerHeader.getTimestampSec();
128         if (stampSec != null) {
129             ByteBufUtils.write(output, stampSec.getValue());
130         } else {
131             output.writeInt(0);
132         }
133         final Timestamp stampMicro = peerHeader.getTimestampMicro();
134         if (stampMicro != null) {
135             ByteBufUtils.write(output, stampMicro.getValue());
136         } else {
137             output.writeInt(0);
138         }
139     }
140
141     protected final MessageRegistry getBgpMessageRegistry() {
142         return this.bgpMssageRegistry;
143     }
144 }