2 #include <netmpls/mpls.h>
4 #include "zebra/zebra_mpls.h"
5 #include "zebra/debug.h"
12 extern struct zebra_privs_t zserv_privs
;
20 kernel_send_rtmsg (int action
, mpls_label_t in_label
, zebra_nhlfe_t
*nhlfe
)
24 struct sockaddr_mpls sa_label_in
, sa_label_out
;
25 struct sockaddr_in nexthop
;
29 if (IS_ZEBRA_DEBUG_KERNEL
)
30 zlog_debug ("kernel_send_rtmsg: 0x%x, label=%u", action
, in_label
);
32 /* initialize header */
33 bzero(&hdr
, sizeof (hdr
));
34 hdr
.rtm_version
= RTM_VERSION
;
36 hdr
.rtm_type
= action
;
37 hdr
.rtm_flags
= RTF_UP
;
38 hdr
.rtm_fmask
= RTF_MPLS
;
39 hdr
.rtm_seq
= kr_state
.rtseq
++; /* overflow doesn't matter */
40 hdr
.rtm_msglen
= sizeof (hdr
);
41 hdr
.rtm_hdrlen
= sizeof (struct rt_msghdr
);
44 iov
[iovcnt
].iov_base
= &hdr
;
45 iov
[iovcnt
++].iov_len
= sizeof (hdr
);
48 bzero(&sa_label_in
, sizeof (sa_label_in
));
49 sa_label_in
.smpls_len
= sizeof (sa_label_in
);
50 sa_label_in
.smpls_family
= AF_MPLS
;
51 sa_label_in
.smpls_label
= htonl(in_label
<< MPLS_LABEL_OFFSET
);
53 hdr
.rtm_flags
|= RTF_MPLS
| RTF_MPATH
;
54 hdr
.rtm_addrs
|= RTA_DST
;
55 hdr
.rtm_msglen
+= sizeof (sa_label_in
);
57 iov
[iovcnt
].iov_base
= &sa_label_in
;
58 iov
[iovcnt
++].iov_len
= sizeof (sa_label_in
);
61 bzero(&nexthop
, sizeof (nexthop
));
62 nexthop
.sin_len
= sizeof (nexthop
);
63 nexthop
.sin_family
= AF_INET
;
64 nexthop
.sin_addr
= nhlfe
->nexthop
->gate
.ipv4
;
66 hdr
.rtm_flags
|= RTF_GATEWAY
;
67 hdr
.rtm_addrs
|= RTA_GATEWAY
;
68 hdr
.rtm_msglen
+= sizeof (nexthop
);
70 iov
[iovcnt
].iov_base
= &nexthop
;
71 iov
[iovcnt
++].iov_len
= sizeof (nexthop
);
73 /* If action is RTM_DELETE we have to get rid of MPLS infos */
74 if (action
!= RTM_DELETE
)
76 bzero(&sa_label_out
, sizeof (sa_label_out
));
77 sa_label_out
.smpls_len
= sizeof (sa_label_out
);
78 sa_label_out
.smpls_family
= AF_MPLS
;
79 sa_label_out
.smpls_label
=
80 htonl(nhlfe
->nexthop
->nh_label
->label
[0] << MPLS_LABEL_OFFSET
);
82 hdr
.rtm_addrs
|= RTA_SRC
;
83 hdr
.rtm_flags
|= RTF_MPLS
;
84 hdr
.rtm_msglen
+= sizeof (sa_label_out
);
86 iov
[iovcnt
].iov_base
= &sa_label_out
;
87 iov
[iovcnt
++].iov_len
= sizeof (sa_label_out
);
89 if (nhlfe
->nexthop
->nh_label
->label
[0] == MPLS_LABEL_IMPLNULL
)
90 hdr
.rtm_mpls
= MPLS_OP_POP
;
92 hdr
.rtm_mpls
= MPLS_OP_SWAP
;
95 if (zserv_privs
.change(ZPRIVS_RAISE
))
96 zlog_err ("Can't raise privileges");
97 ret
= writev (kr_state
.fd
, iov
, iovcnt
);
98 if (zserv_privs
.change(ZPRIVS_LOWER
))
99 zlog_err ("Can't lower privileges");
102 zlog_err ("kernel_send_rtmsg: %s", safe_strerror (errno
));
108 kernel_lsp_cmd (int action
, zebra_lsp_t
*lsp
)
110 zebra_nhlfe_t
*nhlfe
;
111 struct nexthop
*nexthop
= NULL
;
114 for (nhlfe
= lsp
->nhlfe_list
; nhlfe
; nhlfe
= nhlfe
->next
)
116 nexthop
= nhlfe
->nexthop
;
120 if (MULTIPATH_NUM
!= 0 && nexthop_num
>= MULTIPATH_NUM
)
124 if (NHLFE_FAMILY(nhlfe
) == AF_INET6
)
127 if (((action
== RTM_ADD
|| action
== RTM_CHANGE
) &&
128 (CHECK_FLAG (nhlfe
->flags
, NHLFE_FLAG_SELECTED
) &&
129 CHECK_FLAG (nexthop
->flags
, NEXTHOP_FLAG_ACTIVE
))) ||
130 (action
== RTM_DELETE
&&
131 (CHECK_FLAG (nhlfe
->flags
, NHLFE_FLAG_INSTALLED
) &&
132 CHECK_FLAG (nexthop
->flags
, NEXTHOP_FLAG_FIB
))))
136 kernel_send_rtmsg (action
, lsp
->ile
.in_label
, nhlfe
);
137 if (action
== RTM_ADD
|| action
== RTM_CHANGE
)
139 SET_FLAG (nhlfe
->flags
, NHLFE_FLAG_INSTALLED
);
140 SET_FLAG (nexthop
->flags
, NEXTHOP_FLAG_FIB
);
144 UNSET_FLAG (nhlfe
->flags
, NHLFE_FLAG_INSTALLED
);
145 UNSET_FLAG (nexthop
->flags
, NEXTHOP_FLAG_FIB
);
154 kernel_add_lsp (zebra_lsp_t
*lsp
)
156 if (!lsp
|| !lsp
->best_nhlfe
) // unexpected
159 return kernel_lsp_cmd (RTM_ADD
, lsp
);
163 kernel_upd_lsp (zebra_lsp_t
*lsp
)
165 if (!lsp
|| !lsp
->best_nhlfe
) // unexpected
168 return kernel_lsp_cmd (RTM_CHANGE
, lsp
);
172 kernel_del_lsp (zebra_lsp_t
*lsp
)
174 if (!lsp
) // unexpected
177 return kernel_lsp_cmd (RTM_DELETE
, lsp
);
180 #define MAX_RTSOCK_BUF 128 * 1024
182 mpls_kernel_init (void)
184 int rcvbuf
, default_rcvbuf
;
187 if ((kr_state
.fd
= socket(AF_ROUTE
, SOCK_RAW
, 0)) == -1) {
188 zlog_warn("%s: socket", __func__
);
192 /* grow receive buffer, don't wanna miss messages */
193 optlen
= sizeof (default_rcvbuf
);
194 if (getsockopt(kr_state
.fd
, SOL_SOCKET
, SO_RCVBUF
,
195 &default_rcvbuf
, &optlen
) == -1)
196 zlog_warn("kr_init getsockopt SOL_SOCKET SO_RCVBUF");
198 for (rcvbuf
= MAX_RTSOCK_BUF
;
199 rcvbuf
> default_rcvbuf
&&
200 setsockopt(kr_state
.fd
, SOL_SOCKET
, SO_RCVBUF
,
201 &rcvbuf
, sizeof (rcvbuf
)) == -1 && errno
== ENOBUFS
;