Convert NLRI to withdrawn routes 80/78780/6
authorRobert Varga <robert.varga@pantheon.tech>
Fri, 14 Dec 2018 03:34:02 +0000 (04:34 +0100)
committerRobert Varga <nite@hq.sk>
Fri, 14 Dec 2018 07:28:45 +0000 (07:28 +0000)
When we encounter a treat-as-withdraw condition, we need to convert
all reachability information to its withdraw equivalent.

This patch deals with those procedures for NLRI field, appending it
to any Withdrawn Routes field present.

JIRA: BGPCEP-359
Change-Id: I4471e28c1ab6bb8de6016d36911c693c5e897778
Signed-off-by: Matej Perina <matej.perina@pantheon.tech>
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/message/BGPUpdateMessageParser.java

index 9e86efd026e7bda73541a4033ed99916d944fa07..a331d742377215bed3bf03d23a474d7033f4c4f9 100755 (executable)
@@ -10,6 +10,8 @@ package org.opendaylight.protocol.bgp.parser.impl.message;
 import static java.util.Objects.requireNonNull;
 
 import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Streams;
 import io.netty.buffer.ByteBuf;
 import io.netty.buffer.Unpooled;
 import java.util.ArrayList;
@@ -184,8 +186,8 @@ public final class BGPUpdateMessageParser implements MessageParser, MessageSeria
         Update msg = builder.build();
 
         if (withdrawCauseOpt.isPresent()) {
-            // FIXME: BGPCEP-359: check if we can treat the message as withdraw and convert the message
-            throw new BGPDocumentedException(withdrawCauseOpt.get());
+            // Attempt to apply treat-as-withdraw
+            msg = withdrawUpdate(msg, errorHandling, withdrawCauseOpt.get());
         }
 
         LOG.debug("BGP Update message was parsed {}.", msg);
@@ -251,4 +253,31 @@ public final class BGPUpdateMessageParser implements MessageParser, MessageSeria
         return errorHandling.reportError(BGPError.WELL_KNOWN_ATTR_MISSING, new byte[] { (byte) attrType },
             "Well known mandatory attribute missing: %s", attrName);
     }
+
+    private static Update withdrawUpdate(final Update parsed, final RevisedErrorHandling errorHandling,
+            final BGPTreatAsWithdrawException withdrawCause) throws BGPDocumentedException {
+        if (errorHandling == RevisedErrorHandling.NONE) {
+            throw new BGPDocumentedException(withdrawCause);
+        }
+
+        // TODO: additional checks as per RFC7606 section 5.2
+
+        LOG.debug("Converting BGP Update message {} to withdraw", parsed, withdrawCause);
+        final UpdateBuilder builder = new UpdateBuilder();
+
+        final List<Nlri> nlris = parsed.getNlri();
+        final List<WithdrawnRoutes> withdrawn;
+        if (nlris != null && !nlris.isEmpty()) {
+            withdrawn = Streams.concat(parsed.nonnullWithdrawnRoutes().stream(),
+                nlris.stream().map(nlri -> new WithdrawnRoutesBuilder(nlri).build()))
+                    .collect(ImmutableList.toImmutableList());
+        } else {
+            withdrawn = parsed.getWithdrawnRoutes();
+        }
+        builder.setWithdrawnRoutes(withdrawn);
+
+        // FIXME: BGPCEP-359: deal with MP_REACH-to-MP_UNREACH conversion
+
+        return builder.build();
+    }
 }