Testtools should not be bundles
[bgpcep.git] / bgp / parser-impl / src / main / java / org / opendaylight / protocol / bgp / parser / impl / SimpleNlriRegistry.java
1 /*
2  * Copyright (c) 2013 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.bgp.parser.impl;
9
10 import java.util.concurrent.ConcurrentHashMap;
11 import java.util.concurrent.ConcurrentMap;
12
13 import org.opendaylight.protocol.bgp.parser.BGPParsingException;
14 import org.opendaylight.protocol.bgp.parser.BgpTableTypeImpl;
15 import org.opendaylight.protocol.bgp.parser.spi.AddressFamilyRegistry;
16 import org.opendaylight.protocol.bgp.parser.spi.NlriParser;
17 import org.opendaylight.protocol.bgp.parser.spi.NlriRegistry;
18 import org.opendaylight.protocol.bgp.parser.spi.SubsequentAddressFamilyRegistry;
19 import org.opendaylight.protocol.concepts.AbstractRegistration;
20 import org.opendaylight.protocol.util.ByteArray;
21 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130918.BgpTableType;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130918.update.path.attributes.MpReachNlri;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130918.update.path.attributes.MpReachNlriBuilder;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130918.update.path.attributes.MpUnreachNlri;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130918.update.path.attributes.MpUnreachNlriBuilder;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.AddressFamily;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.SubsequentAddressFamily;
28
29 import com.google.common.base.Preconditions;
30 import com.google.common.primitives.UnsignedBytes;
31
32 public final class SimpleNlriRegistry implements NlriRegistry {
33         private final ConcurrentMap<BgpTableType, NlriParser> handlers = new ConcurrentHashMap<>();
34         private final SubsequentAddressFamilyRegistry safiReg;
35         private final AddressFamilyRegistry afiReg;
36
37         public SimpleNlriRegistry(final AddressFamilyRegistry afiReg, final SubsequentAddressFamilyRegistry safiReg) {
38                 this.afiReg = Preconditions.checkNotNull(afiReg);
39                 this.safiReg = Preconditions.checkNotNull(safiReg);
40         }
41
42         private static BgpTableType createKey(final Class<? extends AddressFamily> afi,
43                         final Class<? extends SubsequentAddressFamily> safi) {
44                 Preconditions.checkNotNull(afi);
45                 Preconditions.checkNotNull(safi);
46                 return new BgpTableTypeImpl(afi, safi);
47         }
48
49         @Override
50         public synchronized AutoCloseable registerNlriParser(final Class<? extends AddressFamily> afi,
51                         final Class<? extends SubsequentAddressFamily> safi, final NlriParser parser) {
52                 final BgpTableType key = createKey(afi, safi);
53                 final NlriParser prev = handlers.get(key);
54                 Preconditions.checkState(prev == null, "AFI/SAFI is already bound to parser " + prev);
55
56                 handlers.put(key, parser);
57                 final Object lock = this;
58                 return new AbstractRegistration() {
59                         @Override
60                         protected void removeRegistration() {
61                                 synchronized (lock) {
62                                         handlers.remove(key);
63                                 }
64                         }
65                 };
66         }
67
68         private Class<? extends AddressFamily> getAfi(final byte[] header) throws BGPParsingException {
69                 final int afiVal = UnsignedBytes.toInt(header[0]) * 256 + UnsignedBytes.toInt(header[1]);
70                 final Class<? extends AddressFamily> afi = afiReg.classForFamily(afiVal);
71                 if (afi == null) {
72                         throw new BGPParsingException("Address Family Identifier: '" + afiVal + "' not supported.");
73                 }
74
75                 return afi;
76         }
77
78         private Class<? extends SubsequentAddressFamily> getSafi(final byte[] header) throws BGPParsingException {
79                 final int safiVal = UnsignedBytes.toInt(header[2]);
80                 final Class<? extends SubsequentAddressFamily> safi = safiReg.classForFamily(safiVal);
81                 if (safi == null) {
82                         throw new BGPParsingException("Subsequent Address Family Identifier: '" + safiVal + "' not supported.");
83                 }
84
85                 return safi;
86         }
87
88         @Override
89         public MpUnreachNlri parseMpUnreach(final byte[] bytes) throws BGPParsingException {
90                 final MpUnreachNlriBuilder builder = new MpUnreachNlriBuilder();
91                 builder.setAfi(getAfi(bytes));
92                 builder.setSafi(getSafi(bytes));
93
94                 final NlriParser parser = handlers.get(createKey(builder.getAfi(), builder.getSafi()));
95                 parser.parseNlri(ByteArray.subByte(bytes, 3, bytes.length - 3), builder);
96
97                 return builder.build();
98         }
99
100         @Override
101         public MpReachNlri parseMpReach(final byte[] bytes) throws BGPParsingException {
102                 final MpReachNlriBuilder builder = new MpReachNlriBuilder();
103                 builder.setAfi(getAfi(bytes));
104                 builder.setSafi(getSafi(bytes));
105
106                 final NlriParser parser = handlers.get(createKey(builder.getAfi(), builder.getSafi()));
107
108                 final int nextHopLength = UnsignedBytes.toInt(bytes[3]);
109                 int byteOffset = 4;
110
111                 final byte[] nextHop = ByteArray.subByte(bytes, byteOffset, nextHopLength);
112                 byteOffset += nextHopLength + 1;
113
114                 final byte[] nlri = ByteArray.subByte(bytes, byteOffset, bytes.length - byteOffset);
115                 parser.parseNlri(nlri, nextHop, builder);
116
117                 return builder.build();
118         }
119 }