Skip to content
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

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 37 additions & 0 deletions ldpd/l2vpn.c
Original file line number Diff line number Diff line change
Expand Up @@ -600,3 +600,40 @@ ldpe_l2vpn_pw_exit(struct l2vpn_pw *pw)
tnbr_check(leconf, tnbr);
}
}

/**
* Update PW status
*
* @return 0 on success, 1 on failure
*/
int
l2vpn_pw_status_update (struct kpw *kpw)
{
struct l2vpn *l2vpn;
struct l2vpn_pw *pw;

/* Find L2VPN */
l2vpn = l2vpn_find(ldeconf, kpw->vpn_name);
if (!l2vpn) {
log_warn("%s: No L2VPN found for %s", __func__, kpw->vpn_name);
return 1;
}

/* Find PW */
pw = l2vpn_pw_find(l2vpn, kpw->ifname);
if (!pw) {
log_warn("%s: No PW found for VPN %s and interface %s",
__func__, kpw->vpn_name, kpw->ifname);
return 1;
}

kpw->af = pw->af;
memcpy(&kpw->nexthop, &pw->addr, sizeof (union ldpd_addr));
/* Update status */
if (kpw->flags & F_PW_STATUS_UP)
pw->flags |= F_PW_STATUS_UP;
else
pw->flags &= ~F_PW_STATUS_UP;

return 0;
}
17 changes: 17 additions & 0 deletions ldpd/lde.c
Original file line number Diff line number Diff line change
Expand Up @@ -456,6 +456,7 @@ lde_dispatch_parent(struct thread *thread)
ssize_t n;
int shut = 0;
struct fec fec;
struct kpw kpw; /* for PW status update */

iev->ev_read = NULL;

Expand Down Expand Up @@ -629,6 +630,12 @@ lde_dispatch_parent(struct thread *thread)
}
memcpy(&ldp_debug, imsg.data, sizeof(ldp_debug));
break;
case IMSG_PW_UPDATE:
memcpy (&kpw, imsg.data, sizeof (struct kpw));
if (l2vpn_pw_status_update (&kpw) != 0) {
log_warnx("%s: Error updating PW status", __func__);
}
break;
default:
log_debug("%s: unexpected imsg %d", __func__,
imsg.hdr.type);
Expand Down Expand Up @@ -769,13 +776,18 @@ lde_send_change_klabel(struct fec_node *fn, struct fec_nh *fnh)
pw->flags |= F_PW_STATUS_UP;

memset(&kpw, 0, sizeof(kpw));
strncpy (kpw.ifname, pw->ifname, IF_NAMESIZE);
kpw.ifindex = pw->ifindex;
kpw.pw_type = fn->fec.u.pwid.type;
kpw.lsr_id = pw->lsr_id;
kpw.af = pw->af;
kpw.nexthop = pw->addr;
kpw.local_label = fn->local_label;
kpw.remote_label = fnh->remote_label;
kpw.flags = pw->flags;
kpw.pwid = pw->pwid;
strncpy (kpw.vpn_name, pw->l2vpn->name, L2VPN_NAME_LEN);
kpw.ac_port_ifindex = 0; // TODO: LIST_FIRST(&pw->l2vpn->if_list)->ifindex;

lde_imsg_compose_parent(IMSG_KPWLABEL_CHANGE, 0, &kpw,
sizeof(kpw));
Expand Down Expand Up @@ -826,13 +838,18 @@ lde_send_delete_klabel(struct fec_node *fn, struct fec_nh *fnh)
pw->flags &= ~F_PW_STATUS_UP;

memset(&kpw, 0, sizeof(kpw));
strncpy (kpw.ifname, pw->ifname, IF_NAMESIZE);
kpw.ifindex = pw->ifindex;
kpw.pw_type = fn->fec.u.pwid.type;
kpw.lsr_id = pw->lsr_id;
kpw.af = pw->af;
kpw.nexthop = pw->addr;
kpw.local_label = fn->local_label;
kpw.remote_label = fnh->remote_label;
kpw.flags = pw->flags;
kpw.pwid = pw->pwid;
strncpy (kpw.vpn_name, pw->l2vpn->name, L2VPN_NAME_LEN);
kpw.ac_port_ifindex = 0; //TODO: LIST_FIRST(&pw->l2vpn->if_list)->ifindex;

lde_imsg_compose_parent(IMSG_KPWLABEL_DELETE, 0, &kpw,
sizeof(kpw));
Expand Down
4 changes: 4 additions & 0 deletions ldpd/lde.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
#include "openbsd-tree.h"
#include "if.h"

#define RETRY_SYNC_PW_INTERVAL 5 /* in seconds */
Copy link
Member

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


enum fec_type {
FEC_TYPE_IPV4,
FEC_TYPE_IPV6,
Expand Down Expand Up @@ -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);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

unused prototype

void lde_kernel_insert(struct fec *, int, union ldpd_addr *,
ifindex_t, uint8_t, int, void *);
void lde_kernel_remove(struct fec *, int, union ldpd_addr *,
Expand Down Expand Up @@ -235,5 +238,6 @@ void l2vpn_recv_pw_status_wcard(struct lde_nbr *,
struct notify_msg *);
void l2vpn_pw_ctl(pid_t);
void l2vpn_binding_ctl(pid_t);
int l2vpn_pw_status_update (struct kpw *kpw);

#endif /* _LDE_H_ */
89 changes: 89 additions & 0 deletions ldpd/ldp_zebra.c
Original file line number Diff line number Diff line change
Expand Up @@ -153,17 +153,65 @@ kr_delete(struct kroute *kr)
return (zebra_send_mpls_labels(ZEBRA_MPLS_LABELS_DELETE, kr));
}

static int
zebra_send_kpw(u_char cmd, struct zclient *zclient, struct kpw *kpw)
{
struct stream *s;

debug_zebra_out("ILM %s PW %u (%s) ifindex %hu, type %d. %s -> nexthop %s label %s",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ILM?

(cmd == ZEBRA_KPW_ADD) ? "add" : "delete",
kpw->pwid, kpw->vpn_name, kpw->ifindex,
kpw->pw_type, log_label(kpw->local_label),
log_addr(kpw->af, &kpw->nexthop), log_label(kpw->remote_label));

/* Reset stream. */
s = zclient->obuf;
stream_reset(s);

zclient_create_header(s, cmd, VRF_DEFAULT);
stream_write (s, kpw->ifname, IF_NAMESIZE);
stream_putw(s, kpw->ifindex);
stream_putl(s, kpw->pw_type);
stream_putl(s, kpw->lsr_id.s_addr);
stream_putl(s, kpw->af);
switch (kpw->af) {
case AF_INET:
stream_put_in_addr(s, &kpw->nexthop.v4);
break;
case AF_INET6:
stream_write (s, (u_char *)&kpw->nexthop.v6, 16);
break;
default:
fatalx("zebra_send_kpw: unknown af");
}
stream_putl(s, kpw->local_label);
stream_putl(s, kpw->remote_label);
stream_putc(s, kpw->flags);
stream_putl(s, kpw->pwid);
stream_write(s, kpw->vpn_name, L2VPN_NAME_LEN);
stream_putw(s, kpw->ac_port_ifindex);

/* Put length at the first point of the stream. */
stream_putw_at(s, 0, stream_get_endp(s));

return (zclient_send_message(zclient));
}

int
kmpw_set(struct kpw *kpw)
{
zebra_send_kpw (ZEBRA_KPW_ADD, zclient, kpw);
Copy link
Member

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));

/* TODO */

return (0);
}

int
kmpw_unset(struct kpw *kpw)
{
zebra_send_kpw (ZEBRA_KPW_DELETE, zclient, kpw);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here

/* TODO */

return (0);
}

Expand Down Expand Up @@ -477,6 +525,46 @@ ldp_zebra_read_route(int command, struct zclient *zclient, zebra_size_t length,
return (0);
}

/**
* Receive PW status update from Zebra and send it to LDE process.
*
* Params and return type are the ones required by zclient interface.
*
* @param command It will always be ZEBRA_PW_STATUS_UPDATE
* @param zclient To get input stream from
* @param length
* @param vrf_id
* @return 0 on success
*/
static int
ldp_zebra_read_pw_status_update (int command, struct zclient *zclient,
zebra_size_t length, vrf_id_t vrf_id)
{
struct stream *s;
uint8_t status;
Copy link
Member

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

struct kpw kpw;

memset (&kpw, 0, sizeof (struct kpw));

/* Get input stream. */
s = zclient->ibuf;

/* Get data. */
stream_get (kpw.ifname, s, IF_NAMESIZE);
/* ifindex = stream_getw (s); */
/* pwid = stream_getl (s); */
stream_get (kpw.vpn_name, s, L2VPN_NAME_LEN);
status = stream_getc (s);
if (status)
kpw.flags |= F_PW_STATUS_UP;
else
kpw.flags &= ~F_PW_STATUS_UP;

main_imsg_compose_lde (IMSG_PW_UPDATE, 0, &kpw, sizeof (kpw));

return 0;
}

static void
ldp_zebra_connected(struct zclient *zclient)
{
Expand Down Expand Up @@ -507,6 +595,7 @@ ldp_zebra_init(struct thread_master *master)
zclient->redistribute_route_ipv4_del = ldp_zebra_read_route;
zclient->redistribute_route_ipv6_add = ldp_zebra_read_route;
zclient->redistribute_route_ipv6_del = ldp_zebra_read_route;
zclient->pw_status_update = ldp_zebra_read_pw_status_update;
}

void
Expand Down
8 changes: 7 additions & 1 deletion ldpd/ldpd.h
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,8 @@ enum imsg_type {
IMSG_LOG,
IMSG_ACL_CHECK,
IMSG_GET_LABEL_CHUNK,
IMSG_RELEASE_LABEL_CHUNK
IMSG_RELEASE_LABEL_CHUNK,
IMSG_PW_UPDATE
};

union ldpd_addr {
Expand Down Expand Up @@ -531,13 +532,18 @@ struct kroute {
};

struct kpw {
char ifname[IF_NAMESIZE];
unsigned short ifindex;
int pw_type;
struct in_addr lsr_id;
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;
};
Copy link
Member

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 kaddr {
Expand Down
2 changes: 2 additions & 0 deletions lib/log.c
Original file line number Diff line number Diff line change
Expand Up @@ -967,6 +967,8 @@ static const struct zebra_desc_table command_types[] = {
DESC_ENTRY (ZEBRA_LABEL_MANAGER_CONNECT),
DESC_ENTRY (ZEBRA_GET_LABEL_CHUNK),
DESC_ENTRY (ZEBRA_RELEASE_LABEL_CHUNK),
DESC_ENTRY (ZEBRA_KPW_ADD),
DESC_ENTRY (ZEBRA_KPW_DELETE),
};
#undef DESC_ENTRY

Expand Down
4 changes: 4 additions & 0 deletions lib/zclient.c
Original file line number Diff line number Diff line change
Expand Up @@ -1899,6 +1899,10 @@ zclient_read (struct thread *thread)
if (zclient->interface_link_params)
(*zclient->interface_link_params) (command, zclient, length);
break;
case ZEBRA_PW_STATUS_UPDATE:
if (zclient->pw_status_update)
(*zclient->pw_status_update) (command, zclient, length, vrf_id);
break;
default:
break;
}
Expand Down
4 changes: 4 additions & 0 deletions lib/zclient.h
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,9 @@ typedef enum {
ZEBRA_LABEL_MANAGER_CONNECT,
ZEBRA_GET_LABEL_CHUNK,
ZEBRA_RELEASE_LABEL_CHUNK,
ZEBRA_KPW_ADD,
Copy link
Member

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.

ZEBRA_KPW_DELETE,
ZEBRA_PW_STATUS_UPDATE,
} zebra_message_types_t;

struct redist_proto
Expand Down Expand Up @@ -164,6 +167,7 @@ struct zclient
int (*redistribute_route_ipv4_del) (int, struct zclient *, uint16_t, vrf_id_t);
int (*redistribute_route_ipv6_add) (int, struct zclient *, uint16_t, vrf_id_t);
int (*redistribute_route_ipv6_del) (int, struct zclient *, uint16_t, vrf_id_t);
int (*pw_status_update) (int, struct zclient *, uint16_t, vrf_id_t);
};

/* Zebra API message flag. */
Expand Down
5 changes: 3 additions & 2 deletions zebra/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ zebra_SOURCES = \
zebra_ptm.c zebra_rnh.c zebra_ptm_redistribute.c \
zebra_ns.c zebra_vrf.c zebra_static.c zebra_mpls.c zebra_mpls_vty.c \
zebra_mroute.c \
label_manager.c \
label_manager.c zebra_pw.c \
# end

testzebra_SOURCES = test_main.c zebra_rib.c interface.c connected.c debug.c \
Expand All @@ -49,7 +49,8 @@ noinst_HEADERS = \
rt_netlink.h zebra_fpm_private.h zebra_rnh.h \
zebra_ptm_redistribute.h zebra_ptm.h zebra_routemap.h \
zebra_ns.h zebra_vrf.h ioctl_solaris.h zebra_static.h zebra_mpls.h \
kernel_netlink.h if_netlink.h zebra_mroute.h label_manager.h
kernel_netlink.h if_netlink.h zebra_mroute.h label_manager.h zebra_pw.h \
# end

zebra_LDADD = $(otherobj) ../lib/libfrr.la $(LIBCAP)

Expand Down
1 change: 1 addition & 0 deletions zebra/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -314,6 +314,7 @@ main (int argc, char **argv)

zebra_mpls_init ();
zebra_mpls_vty_init ();
zebra_pw_init ();

/* For debug purpose. */
/* SET_FLAG (zebra_debug_event, ZEBRA_DEBUG_EVENT); */
Expand Down
Loading