Bug-2064: Implementation of RFC5492 Error handling.
[bgpcep.git] / bgp / rib-impl / src / main / java / org / opendaylight / protocol / bgp / rib / impl / BGPClientSessionValidator.java
index 9b33795fa54dcde3d17b58e72dabd9b31e84b9b3..7547e12889ab19d14df048d9a82212641b2afbbe 100644 (file)
@@ -8,16 +8,22 @@
 
 package org.opendaylight.protocol.bgp.rib.impl;
 
+import com.google.common.base.Optional;
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.Unpooled;
 import java.util.List;
 import org.opendaylight.protocol.bgp.parser.AsNumberUtil;
 import org.opendaylight.protocol.bgp.parser.BGPDocumentedException;
 import org.opendaylight.protocol.bgp.parser.BGPError;
+import org.opendaylight.protocol.bgp.parser.impl.message.open.As4CapabilityHandler;
+import org.opendaylight.protocol.bgp.parser.spi.CapabilitySerializer;
 import org.opendaylight.protocol.bgp.rib.impl.spi.BGPSessionPreferences;
 import org.opendaylight.protocol.bgp.rib.impl.spi.BGPSessionValidator;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.AsNumber;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.Open;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.open.BgpParameters;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.open.bgp.parameters.c.parameters.As4BytesCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.open.bgp.parameters.OptionalCapabilities;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.open.bgp.parameters.optional.capabilities.c.parameters.As4BytesCase;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -56,8 +62,9 @@ public class BGPClientSessionValidator implements BGPSessionValidator {
 
         final List<BgpParameters> prefs = openObj.getBgpParameters();
         if (prefs != null && !prefs.isEmpty()) {
-            if(!hasAs4BytesCapability(prefs) || !hasAs4BytesCapability(localPref.getParams())) {
-                throw new BGPDocumentedException("Both speaker and peer must advertise AS4Bytes capability.", BGPError.UNSPECIFIC_OPEN_ERROR);
+            if(getAs4BytesCapability(localPref.getParams()).isPresent() && !getAs4BytesCapability(prefs).isPresent()) {
+                throw new BGPDocumentedException("The peer must advertise AS4Bytes capability.", BGPError.UNSUPPORTED_CAPABILITY,
+                        serializeAs4BytesCapability(getAs4BytesCapability(localPref.getParams()).get()));
             }
             if (!prefs.containsAll(localPref.getParams())) {
                 LOG.info("BGP Open message session parameters differ, session still accepted.");
@@ -67,12 +74,21 @@ public class BGPClientSessionValidator implements BGPSessionValidator {
         }
     }
 
-    private boolean hasAs4BytesCapability(final List<BgpParameters> prefs) {
+    private static Optional<As4BytesCase> getAs4BytesCapability(final List<BgpParameters> prefs) {
         for(final BgpParameters param : prefs) {
-            if(param.getCParameters() instanceof As4BytesCase) {
-                return true;
+            for (final OptionalCapabilities capa : param.getOptionalCapabilities()) {
+                if(capa.getCParameters() instanceof As4BytesCase) {
+                    return Optional.of((As4BytesCase) capa.getCParameters());
+                }
             }
         }
-        return false;
+        return Optional.absent();
+    }
+
+    private static byte[] serializeAs4BytesCapability(final As4BytesCase as4Capability) {
+        final ByteBuf buffer = Unpooled.buffer(1 /*CODE*/ + 1 /*LENGTH*/ + Integer.SIZE / Byte.SIZE /*4 byte value*/);
+        final CapabilitySerializer serializer = new As4CapabilityHandler();
+        serializer.serializeCapability(as4Capability, buffer);
+        return buffer.array();
     }
 }