summaryrefslogtreecommitdiffstats
path: root/ldpd
diff options
context:
space:
mode:
authorRenato Westphal <renato@opensourcerouting.org>2020-04-03 19:42:25 +0200
committerRenato Westphal <renato@opensourcerouting.org>2020-04-08 04:37:07 +0200
commit8963e0c82b02a0afe8d319844e42e21dd57d6747 (patch)
treed6dd567b1c3daab4e26787a5872e7e60d2fac7c0 /ldpd
parentMerge pull request #6180 from mjstapp/fix_bgp_ecomm_sa (diff)
downloadfrr-8963e0c82b02a0afe8d319844e42e21dd57d6747.tar.xz
frr-8963e0c82b02a0afe8d319844e42e21dd57d6747.zip
ldpd: don't drop packets coming through a broken LSP
When the Independent Control mode is in use (the default one), each LDP speaker allocates labels independently, which can lead to broken LSPs when the LDP and IGP domains are not congruent. What we were doing in this case was to drop all packets coming through a broken LSP, which causes drastic side effects in the network like loss of IP connectivity between routers. We can however do a best-effort attempt to avoid packet loss by popping the top-level label of the incoming packets and forwarding them normally to their nexthops. This will be enough to guarantee that labeled IP packets will reach their final destination. The broken LSPs will still be unsuitable to tunnel labeled traffic, like VPN packets, but in this case there's nothing we can do about it. Cisco's IOS does something similar, called the "Untagged/No Label" operation, which removes the entire label stack and forward the packet unlabeled. We don't have such functionality available in the Linux kernel, but this shouldn't make any difference for practical purposes. Fixes #6127. Signed-off-by: Renato Westphal <renato@opensourcerouting.org>
Diffstat (limited to 'ldpd')
-rw-r--r--ldpd/ldp_zebra.c42
1 files changed, 26 insertions, 16 deletions
diff --git a/ldpd/ldp_zebra.c b/ldpd/ldp_zebra.c
index b3ccb7760..28e56ecd6 100644
--- a/ldpd/ldp_zebra.c
+++ b/ldpd/ldp_zebra.c
@@ -108,8 +108,7 @@ ldp_zebra_send_mpls_labels(int cmd, struct kroute *kr)
struct zapi_labels zl = {};
struct zapi_nexthop *znh;
- if (kr->local_label < MPLS_LABEL_RESERVED_MAX ||
- kr->remote_label == NO_LABEL)
+ if (kr->local_label < MPLS_LABEL_RESERVED_MAX)
return (0);
debug_zebra_out("prefix %s/%u nexthop %s ifindex %u labels %s/%s (%s)",
@@ -122,21 +121,32 @@ ldp_zebra_send_mpls_labels(int cmd, struct kroute *kr)
zl.local_label = kr->local_label;
/* Set prefix. */
- SET_FLAG(zl.message, ZAPI_LABELS_FTN);
- zl.route.prefix.family = kr->af;
- switch (kr->af) {
- case AF_INET:
- zl.route.prefix.u.prefix4 = kr->prefix.v4;
- break;
- case AF_INET6:
- zl.route.prefix.u.prefix6 = kr->prefix.v6;
- break;
- default:
- fatalx("ldp_zebra_send_mpls_labels: unknown af");
+ if (kr->remote_label != NO_LABEL) {
+ SET_FLAG(zl.message, ZAPI_LABELS_FTN);
+ zl.route.prefix.family = kr->af;
+ switch (kr->af) {
+ case AF_INET:
+ zl.route.prefix.u.prefix4 = kr->prefix.v4;
+ break;
+ case AF_INET6:
+ zl.route.prefix.u.prefix6 = kr->prefix.v6;
+ break;
+ default:
+ fatalx("ldp_zebra_send_mpls_labels: unknown af");
+ }
+ zl.route.prefix.prefixlen = kr->prefixlen;
+ zl.route.type = kr->route_type;
+ zl.route.instance = kr->route_instance;
}
- zl.route.prefix.prefixlen = kr->prefixlen;
- zl.route.type = kr->route_type;
- zl.route.instance = kr->route_instance;
+
+ /*
+ * For broken LSPs, instruct the forwarding plane to pop the top-level
+ * label and forward packets normally. This is a best-effort attempt
+ * to deliver labeled IP packets to their final destination (instead of
+ * dropping them).
+ */
+ if (kr->remote_label == NO_LABEL)
+ kr->remote_label = MPLS_LABEL_IMPLICIT_NULL;
/* Set nexthop. */
zl.nexthop_num = 1;