66#include "nl-default.h"
77
88#include <linux/nexthop.h>
9+ #include <linux/lwtunnel.h>
10+ #include <linux/mpls_iptunnel.h>
911
1012#include <netlink/route/nh.h>
1113#include <netlink/hashtable.h>
@@ -29,6 +31,7 @@ struct rtnl_nh {
2931 nl_nh_group_t * nh_group ;
3032 uint32_t nh_oif ;
3133 struct nl_addr * nh_gateway ;
34+ struct rtnl_nh_encap * nh_encap ;
3235
3336 /* Resilient nexthop group parameters */
3437 uint16_t res_grp_buckets ;
@@ -50,6 +53,7 @@ struct rtnl_nh {
5053#define NH_ATTR_RES_BUCKETS (1 << 10)
5154#define NH_ATTR_RES_IDLE_TIMER (1 << 11)
5255#define NH_ATTR_RES_UNBALANCED_TIMER (1 << 12)
56+ #define NH_ATTR_ENCAP (1 << 13)
5357/** @endcond */
5458
5559struct nla_policy rtnl_nh_policy [NHA_MAX + 1 ] = {
@@ -60,6 +64,8 @@ struct nla_policy rtnl_nh_policy[NHA_MAX + 1] = {
6064 [NHA_BLACKHOLE ] = { .type = NLA_UNSPEC },
6165 [NHA_OIF ] = { .type = NLA_U32 },
6266 [NHA_RES_GROUP ] = { .type = NLA_NESTED },
67+ [NHA_ENCAP ] = { .type = NLA_NESTED },
68+ [NHA_ENCAP_TYPE ] = { .type = NLA_U16 },
6369};
6470
6571static struct nl_cache_ops rtnl_nh_ops ;
@@ -155,6 +161,13 @@ static int nh_clone(struct nl_object *_src, struct nl_object *_dst)
155161 dst -> res_grp_unbalanced_timer = src -> res_grp_unbalanced_timer ;
156162 dst -> ce_mask = src -> ce_mask ;
157163
164+ if (src -> nh_encap ) {
165+ dst -> nh_encap = rtnl_nh_encap_clone (src -> nh_encap );
166+ if (!dst -> nh_encap )
167+ return - NLE_NOMEM ;
168+ dst -> ce_mask |= NH_ATTR_ENCAP ;
169+ }
170+
158171 if (src -> nh_gateway ) {
159172 dst -> nh_gateway = nl_addr_clone (src -> nh_gateway );
160173 if (!dst -> nh_gateway ) {
@@ -174,10 +187,10 @@ static int nh_clone(struct nl_object *_src, struct nl_object *_dst)
174187static void nh_free (struct nl_object * obj )
175188{
176189 struct rtnl_nh * nh = nl_object_priv (obj );
177- nl_addr_put (nh -> nh_gateway );
178190
179- if (nh -> nh_group )
180- rtnl_nh_grp_put (nh -> nh_group );
191+ nl_addr_put (nh -> nh_gateway );
192+ rtnl_nh_encap_free (nh -> nh_encap );
193+ rtnl_nh_grp_put (nh -> nh_group );
181194}
182195
183196void rtnl_nh_put (struct rtnl_nh * nh )
@@ -237,6 +250,52 @@ struct nl_addr *rtnl_nh_get_gateway(struct rtnl_nh *nexthop)
237250 return nexthop -> nh_gateway ;
238251}
239252
253+ /**
254+ * Set nexthop encapsulation
255+ * @arg nh Nexthop object
256+ * @arg encap Encapsulation descriptor
257+ *
258+ * Assigns ownership of the encapsulation object to the nexthop. Any
259+ * previously configured encapsulation is released. Passing a NULL
260+ * encapsulation clears the encapsulation on the nexthop.
261+ *
262+ * On failure, the function consumes and frees encap.
263+ *
264+ * @return 0 on success, or the appropriate error-code on failure.
265+ */
266+ int rtnl_nh_set_encap (struct rtnl_nh * nh , struct rtnl_nh_encap * encap )
267+ {
268+ if (!nh ) {
269+ rtnl_nh_encap_free (encap );
270+ return - NLE_INVAL ;
271+ }
272+
273+ if (encap && !encap -> ops ) {
274+ rtnl_nh_encap_free (encap );
275+ return - NLE_INVAL ;
276+ }
277+
278+ rtnl_nh_encap_free (nh -> nh_encap );
279+
280+ if (encap ) {
281+ nh -> nh_encap = encap ;
282+ nh -> ce_mask |= NH_ATTR_ENCAP ;
283+ } else {
284+ nh -> nh_encap = NULL ;
285+ nh -> ce_mask &= ~NH_ATTR_ENCAP ;
286+ }
287+
288+ return 0 ;
289+ }
290+
291+ struct rtnl_nh_encap * rtnl_nh_get_encap (struct rtnl_nh * nh )
292+ {
293+ if (!nh || !(nh -> ce_mask & NH_ATTR_ENCAP ))
294+ return NULL ;
295+
296+ return nh -> nh_encap ;
297+ }
298+
240299int rtnl_nh_set_fdb (struct rtnl_nh * nexthop , int value )
241300{
242301 if (value )
@@ -547,6 +606,27 @@ static int rtnl_nh_build_msg(struct nl_msg *msg, struct rtnl_nh *nh)
547606 if (nh -> ce_mask & NH_ATTR_FLAG_BLACKHOLE )
548607 NLA_PUT_FLAG (msg , NHA_BLACKHOLE );
549608
609+ if (nh -> ce_mask & NH_ATTR_ENCAP ) {
610+ struct nlattr * encap ;
611+
612+ if (!nh -> nh_encap || !nh -> nh_encap -> ops )
613+ return - NLE_INVAL ;
614+
615+ NLA_PUT_U16 (msg , NHA_ENCAP_TYPE , nh -> nh_encap -> ops -> encap_type );
616+
617+ encap = nla_nest_start (msg , NHA_ENCAP );
618+ if (!encap )
619+ goto nla_put_failure ;
620+
621+ if (nh -> nh_encap -> ops -> build_msg ) {
622+ int err = nh -> nh_encap -> ops -> build_msg (
623+ msg , nh -> nh_encap -> priv );
624+ if (err < 0 )
625+ return err ;
626+ }
627+ nla_nest_end (msg , encap );
628+ }
629+
550630 /* Nexthop group */
551631 if (nh -> ce_mask & NH_ATTR_GROUP ) {
552632 struct nexthop_grp * grp ;
@@ -758,6 +838,19 @@ static int nexthop_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who,
758838 nexthop -> ce_mask |= NH_ATTR_GROUP_TYPE ;
759839 }
760840
841+ if (tb [NHA_ENCAP ] && tb [NHA_ENCAP_TYPE ]) {
842+ _nl_auto_rtnl_nh_encap struct rtnl_nh_encap * nh_encap = NULL ;
843+
844+ err = nh_encap_parse_msg (tb [NHA_ENCAP ], tb [NHA_ENCAP_TYPE ],
845+ & nh_encap );
846+ if (err < 0 )
847+ return err ;
848+
849+ err = rtnl_nh_set_encap (nexthop , _nl_steal_pointer (& nh_encap ));
850+ if (err < 0 )
851+ return err ;
852+ }
853+
761854 if (tb [NHA_BLACKHOLE ]) {
762855 nexthop -> ce_mask |= NH_ATTR_FLAG_BLACKHOLE ;
763856 }
@@ -870,6 +963,9 @@ static void nh_dump_line(struct nl_object *obj, struct nl_dump_params *dp)
870963 nl_dump (dp , " via %s" ,
871964 nl_addr2str (nh -> nh_gateway , buf , sizeof (buf )));
872965
966+ if (nh -> ce_mask & NH_ATTR_ENCAP && nh -> nh_encap )
967+ nh_encap_dump (nh -> nh_encap , dp );
968+
873969 if (nh -> ce_mask & NH_ATTR_FLAG_BLACKHOLE )
874970 nl_dump (dp , " blackhole" );
875971
@@ -930,6 +1026,8 @@ static uint64_t nh_compare(struct nl_object *a, struct nl_object *b,
9301026 diff |= _DIFF (NH_ATTR_RES_UNBALANCED_TIMER ,
9311027 src -> res_grp_unbalanced_timer !=
9321028 dst -> res_grp_unbalanced_timer );
1029+ diff |= _DIFF (NH_ATTR_ENCAP ,
1030+ nh_encap_compare (src -> nh_encap , dst -> nh_encap ));
9331031#undef _DIFF
9341032
9351033 return diff ;
0 commit comments