-
Notifications
You must be signed in to change notification settings - Fork 1.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add Pseudowire management in Zebra #601
Conversation
When Zebra receives a PW from ldpd, it tries to install it in kernel and in case of failure notifies back to ldpd daemon and enqueues the PW for retry. The installation to kernel is not yet implemented as Linux kernel doesn't have support for it yet. It will be done through a module hook, so it can be outsourced to a remote dataplane. Signed-off-by: ßingen <bingen@voltanet.io>
Continous Integration Result: SUCCESSFULCongratulations, this patch passed basic tests Tested-by: NetDEF / OpenSourceRouting.org CI System CI System Testrun URL: https://ci1.netdef.org/browse/FRR-FRRPULLREQ-786/ This is a comment from an EXPERIMENTAL automated CI system. CLANG Static Analyzer Summary
No Changes in Static Analysis warnings compared to base132 Static Analyzer issues remaining.See details at |
This looks isolated and after a review from @rwestphal it can be integrated |
Continous Integration Result: SUCCESSFULCongratulations, this patch passed basic tests Tested-by: NetDEF / OpenSourceRouting.org CI System CI System Testrun URL: https://ci1.netdef.org/browse/FRR-FRRPULLREQ-821/ This is a comment from an EXPERIMENTAL automated CI system. CLANG Static Analyzer Summary
No Changes in Static Analysis warnings compared to base132 Static Analyzer issues remaining.See details at |
@bingen please push this against master and not stable/3.0, as it is a new feature. More feedback soon. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good work, this is the missing piece of VPLS support in FRR.
Please address my nits and re-open this against master. In the meantime I'll cook a patch on top of this to install the LDP signaled pseudowires in the kernel when running on OpenBSD, mostly as a proof of concept.
@@ -188,6 +190,7 @@ void fec_snap(struct lde_nbr *); | |||
void fec_tree_clear(void); | |||
struct fec_nh *fec_nh_find(struct fec_node *, int, union ldpd_addr *, | |||
ifindex_t, uint8_t); | |||
void update_local_label (struct fec_node *fn, int connected); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
unused prototype
int | ||
kmpw_set(struct kpw *kpw) | ||
{ | ||
zebra_send_kpw (ZEBRA_KPW_ADD, zclient, kpw); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please remove the TODO comment below.
Better yet, rewrite this function like this:
return (zebra_send_kpw (ZEBRA_PW_ADD, zclient, kpw));
return (0); | ||
} | ||
|
||
int | ||
kmpw_unset(struct kpw *kpw) | ||
{ | ||
zebra_send_kpw (ZEBRA_KPW_DELETE, zclient, kpw); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here
@@ -25,6 +25,8 @@ | |||
#include "openbsd-tree.h" | |||
#include "if.h" | |||
|
|||
#define RETRY_SYNC_PW_INTERVAL 5 /* in seconds */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is not used anywhere
@@ -94,6 +94,9 @@ typedef enum { | |||
ZEBRA_LABEL_MANAGER_CONNECT, | |||
ZEBRA_GET_LABEL_CHUNK, | |||
ZEBRA_RELEASE_LABEL_CHUNK, | |||
ZEBRA_KPW_ADD, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Forgive the bikeshedding, but I'd prefer to remove the "K" from these constants.
ZEBRA_PW_ADD and ZEBRA_PW_DELETE look better.
int af; | ||
union ldpd_addr nexthop; | ||
uint32_t local_label; | ||
uint32_t remote_label; | ||
uint8_t flags; | ||
uint32_t pwid; | ||
char vpn_name[L2VPN_NAME_LEN]; | ||
unsigned short ac_port_ifindex; | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is the ac_port_ifindex
for? It's not being used anywhere.
Also, the other members you're adding here are not necessary in my opinion.
We don't want to send protocol-specific pseudowire attributes to zebra, like pwid
, lsr_id
and vpn_name
. Currently only ldpd supports L2VPNs, but in the future we should implement support for BGP-signaled L2VPNs as well.
I think that pseudowires can be uniquely identified by their ifname and ifindex, zebra doesn't need to track more information than that.
{ | ||
struct stream *s; | ||
|
||
debug_zebra_out("ILM %s PW %u (%s) ifindex %hu, type %d. %s -> nexthop %s label %s", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ILM?
zebra_size_t length, vrf_id_t vrf_id) | ||
{ | ||
struct stream *s; | ||
uint8_t status; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
padding not consistent with the rest of the code
@rwestphal thanks for your feedback, I will address it soon but a first comment about where to submit the PR to. This is supposed to be related to commit 595b4be which is in stable/3.0, so I think it should be there. As we talked by e-mail some time ago, with the code in stable/3.0 as it is now, it will show the PW status as UP by default, even if it's not true. |
@bingen In my opinion this PR is way too big for stable/3.0. If you really need the pseudowire manager on stable/3.0 you can always create an internal fork to accommodate your custom requirements. The commit you pointed out didn't break anything because VPLS is not supposed to work without a pseudowire manager in zebra. On stable/3.0, all pseudowires signaled by ldpd are going to /dev/null. We could revert 595b4be, but would that make any difference? |
If the label is implicit null it's not installed in Zebra, so this check doesn't make sense. Signed-off-by: ßingen <bingen@voltanet.io>
Continous Integration Result: SUCCESSFULCongratulations, this patch passed basic tests Tested-by: NetDEF / OpenSourceRouting.org CI System CI System Testrun URL: https://ci1.netdef.org/browse/FRR-FRRPULLREQ-839/ This is a comment from an EXPERIMENTAL automated CI system. CLANG Static Analyzer Summary
No Changes in Static Analysis warnings compared to base132 Static Analyzer issues remaining.See details at |
zebra/zebra_pw.c
Outdated
zlog_warn ("No label found in rib for PW %u at VPN %s", pw->pwid, | ||
pw->vpn_name); | ||
return 1; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If the label is implicit null it's not installed in Zebra, so this check doesn't make sense.
Not really, you can't remove this.
The P from VPLS stands for Private. Removing these lines introduces a security issue as you break the isolation between the VPLS customers.
Receiving an implicit-null label for the pseudowire's remote endpoint is different than receiving no label at all.
If you receive an implicit-null label, it means that the remote endpoint is directly connected to you. In this case, due to the default PHP behavior, you can send the pseudowire frames with the VPN label only. You don't need to push an additional label to tunnel the packets to the remote endpoint.
Now let's say that you didn't receive any label for the pseudowire's remote endpoint. In this case, you don't know if the remote endpoint is directly connected to you or not. If you send L2VPN frames pushing just one label (the VPN label) and the nexthop is not the remote endpoint, then it will not understand what to do with the VPN label. Even worse, it might have allocated the very same label for another VPLS client and forward the packet to it. Now you have a security issue. This is possible because labels are locally allocated in standard MPLS networks (when segment routing is not in use).
With that said, the real problem here is that we're not adding LDP's implicit-null labels to routes. Removing the out_label != MPLS_IMP_NULL_LABEL
checks below (zserv.c) should solve the problem.
if (command == ZEBRA_MPLS_LABELS_ADD)
{
mpls_lsp_install (zvrf, type, in_label, out_label, gtype, &gate,
ifindex);
if (out_label != MPLS_IMP_NULL_LABEL)
mpls_ftn_update (1, zvrf, type, &prefix, gtype, &gate, ifindex,
distance, out_label);
}
else if (command == ZEBRA_MPLS_LABELS_DELETE)
{
mpls_lsp_uninstall (zvrf, type, in_label, gtype, &gate, ifindex);
if (out_label != MPLS_IMP_NULL_LABEL)
mpls_ftn_update (0, zvrf, type, &prefix, gtype, &gate, ifindex,
distance, out_label);
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ya, you are right, good catch. I saw the other code (where it discards Implicit Null labels) but I didn't touch because I thought that it would be there for a reason and I was afraid of breaking something else.
I'll try removing it and restoring the check. If it works I'll add it to my final PR when I address all of your comments. Are you sure it's safe to install those implicit null labels? Why was that code put there then?
Thanks.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It should be safe.
Back when I wrote this code I thought we could avoid making unnecessary changes in the RIB because implicit-null labels are never sent on the wire. But it turns out that we need to keep track of implicit-null labels in the RIB because of this issue you brought up. rt_netlink.c
and zebra_mpls_openbsd.c
have additional checks that will ensure that the implicit-null labels are never installed in the kernel.
@rwestphal About the branching I completely disagree. This PR is addressing something that was removed in a previous commit, as you said here "we assume that zebra will do that for us". So without this PR stable/3.0 is with no doubt broken. You say nobody uses it. Well, you already know that we do, but if that's true, why would it matter then to accept this PR here? I see very inconsistent to accept in stable branch the removal of a check but not its substitute. It makes no sense to me. |
My point is that with or without that commit VPLS doesn't work on stable/3.0. That commit just prepares the ground for the pseudowire manager, reverting it for example wouldn't change anything. For me it's questionable if your PR is adding a new feature or fixing a bug, it's kinda doing both. Generally speaking I'd prefer to avoid big changes on a stable branch. But since the code is well contained I'll speak with the other maintainers and see if we can add an exception here. |
some more issues that need to be worked on a bit more. |
As we talked in Slack before, In my VPLS test setup things are not going quite right because of this problem. One other problem is that nexthop resolution is being performed only when the pseudowire is installed. If the route and/or label used to reach the pseudowire's remote endpoint changes, we need to reinstall the pseudowire in the kernel/hardware. With that said, we have two possibilities here: Approach #2 is more responsive but potentially more expensive. One other problem with #2 is that the installation of a pseudowire can fail for other reasons other than failed nexthop resolution (e.g. hardware running out of resources). In this case, we can wait too long to re-attempt to install a pseudowire if the RIB is not being changed. Maybe implementing a hybrid of #1 and #2 would be the way to go, so we're good in all cases. Does anyone have an opinion on this? |
Update: I talked to @eqvinox yesterday and he suggested that using our NHT code might be appropriate to solve the pseudowire nexthop resolution problem. I'm investigating this idea right now. |
Implemented here nexthop tracking in ldpd. Now ldpd registers the nexthop of the pseudowires with zebra and keeps track if they are resolvable or not. When the nexthop resolution for a pseudowire changes, ldpd will send a message to zebra asking to reinstall or uninstall the pseudowire. The only issue here is that ldpd needs labeled routes for its pseudowires remote endpoints (bgpd should have the same requirement for MPLS VPN routes). In other words, a resolved nexthop is only valid if it's labeled, otherwise the pseudowire can't be installed. To address this issue I did some small changes in the ZEBRA_NEXTHOP_UPDATE message to include the label of the nexthops as well. So far so good, but there's a problem. When we add a label to a route, zebra doesn't notify its NHT clients that this route was updated. Apparently the problem comes down to this line: https://github.com/FRRouting/frr/blob/ce7fce36b/zebra/zebra_rnh.c#L870 We do set More precisely, the NHT call trace is usually like this:
With that said, I propose to remove the aforementioned line ( Any thoughts? I'm not super sure if doing this is safe or not so I'd appreciate feedback from others. |
To close the loop from a private Conversation @rwestphal and I had last night. I do not believe modifying zebra_rnh.c is the right thing to do. Currently when labels change for a route entry we are not considering that a change in the nexthop so we are not calling the rnh code correctly. We should be modifying rib_process( and really nexthop_active_update/nexthop_active..) to be able to notice when labels are changed in the nexthop |
Replaced by #710 |
When Zebra receives a PW from ldpd, it tries to install it in kernel and
in case of failure notifies back to ldpd daemon and enqueues the PW for
retry.
The installation to kernel is not yet implemented as Linux kernel
doesn't have support for it yet. It will be done through a module hook,
so it can be outsourced to a remote dataplane.
Signed-off-by: ßingen bingen@voltanet.io