2 * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
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
8 package org.opendaylight.protocol.bgp.parser.spi.pojo;
10 import com.google.common.base.Preconditions;
11 import com.google.common.collect.Iterables;
12 import com.google.common.primitives.UnsignedBytes;
14 import io.netty.buffer.ByteBuf;
15 import io.netty.buffer.Unpooled;
17 import java.util.concurrent.ConcurrentHashMap;
18 import java.util.concurrent.ConcurrentMap;
20 import org.opendaylight.bgp.concepts.NextHopUtil;
21 import org.opendaylight.protocol.bgp.parser.BGPParsingException;
22 import org.opendaylight.protocol.bgp.parser.BgpTableTypeImpl;
23 import org.opendaylight.protocol.bgp.parser.spi.AddressFamilyRegistry;
24 import org.opendaylight.protocol.bgp.parser.spi.NlriParser;
25 import org.opendaylight.protocol.bgp.parser.spi.NlriRegistry;
26 import org.opendaylight.protocol.bgp.parser.spi.NlriSerializer;
27 import org.opendaylight.protocol.bgp.parser.spi.SubsequentAddressFamilyRegistry;
28 import org.opendaylight.protocol.concepts.AbstractRegistration;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.BgpTableType;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.update.path.attributes.MpReachNlri;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.update.path.attributes.MpReachNlriBuilder;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.update.path.attributes.MpUnreachNlri;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.update.path.attributes.MpUnreachNlriBuilder;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.AddressFamily;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.SubsequentAddressFamily;
36 import org.opendaylight.yangtools.yang.binding.DataObject;
38 final class SimpleNlriRegistry implements NlriRegistry {
40 private static final int RESERVED = 1;
42 private final ConcurrentMap<BgpTableType, NlriParser> handlers = new ConcurrentHashMap<>();
43 private final ConcurrentMap<Class<? extends DataObject>, NlriSerializer> serializers = new ConcurrentHashMap<>();
44 private final SubsequentAddressFamilyRegistry safiReg;
45 private final AddressFamilyRegistry afiReg;
47 public SimpleNlriRegistry(final AddressFamilyRegistry afiReg, final SubsequentAddressFamilyRegistry safiReg) {
48 this.afiReg = Preconditions.checkNotNull(afiReg);
49 this.safiReg = Preconditions.checkNotNull(safiReg);
52 private static BgpTableType createKey(final Class<? extends AddressFamily> afi,
53 final Class<? extends SubsequentAddressFamily> safi) {
54 Preconditions.checkNotNull(afi);
55 Preconditions.checkNotNull(safi);
56 return new BgpTableTypeImpl(afi, safi);
59 synchronized AutoCloseable registerNlriSerializer(final Class<? extends DataObject> nlriClass, final NlriSerializer serializer){
60 final NlriSerializer prev = this.serializers.get(nlriClass);
61 Preconditions.checkState(prev == null, "Serializer already bound to class " + prev);
63 this.serializers.put(nlriClass, serializer);
64 final Object lock = this;
65 return new AbstractRegistration() {
67 protected void removeRegistration() {
69 SimpleNlriRegistry.this.serializers.remove(nlriClass);
75 synchronized AutoCloseable registerNlriParser(final Class<? extends AddressFamily> afi,
76 final Class<? extends SubsequentAddressFamily> safi, final NlriParser parser) {
77 final BgpTableType key = createKey(afi, safi);
78 final NlriParser prev = this.handlers.get(key);
79 Preconditions.checkState(prev == null, "AFI/SAFI is already bound to parser " + prev);
81 this.handlers.put(key, parser);
82 final Object lock = this;
83 return new AbstractRegistration() {
85 protected void removeRegistration() {
87 SimpleNlriRegistry.this.handlers.remove(key);
93 private Class<? extends AddressFamily> getAfi(final ByteBuf buffer) throws BGPParsingException {
94 final int afiVal = buffer.readUnsignedShort();
95 final Class<? extends AddressFamily> afi = this.afiReg.classForFamily(afiVal);
97 throw new BGPParsingException("Address Family Identifier: '" + afiVal + "' not supported.");
102 private Class<? extends SubsequentAddressFamily> getSafi(final ByteBuf buffer) throws BGPParsingException {
103 final int safiVal = UnsignedBytes.toInt(buffer.readByte());
104 final Class<? extends SubsequentAddressFamily> safi = this.safiReg.classForFamily(safiVal);
106 throw new BGPParsingException("Subsequent Address Family Identifier: '" + safiVal + "' not supported.");
112 public MpUnreachNlri parseMpUnreach(final ByteBuf buffer) throws BGPParsingException {
113 final MpUnreachNlriBuilder builder = new MpUnreachNlriBuilder();
114 builder.setAfi(getAfi(buffer));
115 builder.setSafi(getSafi(buffer));
117 final NlriParser parser = this.handlers.get(createKey(builder.getAfi(), builder.getSafi()));
118 final ByteBuf nlri = buffer.slice();
119 parser.parseNlri(nlri, builder);
120 return builder.build();
124 public void serializeMpReach(MpReachNlri mpReachNlri, ByteBuf byteAggregator) {
125 byteAggregator.writeShort(this.afiReg.numberForClass(mpReachNlri.getAfi()));
126 byteAggregator.writeByte(this.safiReg.numberForClass(mpReachNlri.getSafi()));
128 final ByteBuf nextHopBuffer = Unpooled.buffer();
129 NextHopUtil.serializeNextHop(mpReachNlri.getCNextHop(), nextHopBuffer);
131 byteAggregator.writeByte(nextHopBuffer.writerIndex());
132 byteAggregator.writeBytes(nextHopBuffer);
133 byteAggregator.writeZero(RESERVED);
137 public void serializeMpUnReach(MpUnreachNlri mpUnreachNlri, ByteBuf byteAggregator) {
138 byteAggregator.writeShort(this.afiReg.numberForClass(mpUnreachNlri.getAfi()));
139 byteAggregator.writeByte(this.safiReg.numberForClass(mpUnreachNlri.getSafi()));
143 public Iterable<NlriSerializer> getSerializers() {
144 return Iterables.unmodifiableIterable(this.serializers.values());
148 public MpReachNlri parseMpReach(final ByteBuf buffer) throws BGPParsingException {
149 final MpReachNlriBuilder builder = new MpReachNlriBuilder();
150 builder.setAfi(getAfi(buffer));
151 builder.setSafi(getSafi(buffer));
153 final NlriParser parser = this.handlers.get(createKey(builder.getAfi(), builder.getSafi()));
155 final int nextHopLength = UnsignedBytes.toInt(buffer.readByte());
156 builder.setCNextHop(NextHopUtil.parseNextHop(buffer.slice(buffer.readerIndex(), nextHopLength)));
157 buffer.skipBytes(nextHopLength + RESERVED);
159 final ByteBuf nlri = buffer.slice();
160 parser.parseNlri(nlri, builder);
161 return builder.build();