41
41
#include <net/addrconf.h>
42
42
#include <net/xfrm.h>
43
43
#include <net/net_namespace.h>
44
+ #include <net/dst_metadata.h>
44
45
#include <net/netns/generic.h>
45
46
#include <linux/etherdevice.h>
46
47
@@ -56,6 +57,7 @@ static const struct net_device_ops xfrmi_netdev_ops;
56
57
struct xfrmi_net {
57
58
/* lists for storing interfaces in use */
58
59
struct xfrm_if __rcu * xfrmi [XFRMI_HASH_SIZE ];
60
+ struct xfrm_if __rcu * collect_md_xfrmi ;
59
61
};
60
62
61
63
#define for_each_xfrmi_rcu (start , xi ) \
@@ -77,17 +79,23 @@ static struct xfrm_if *xfrmi_lookup(struct net *net, struct xfrm_state *x)
77
79
return xi ;
78
80
}
79
81
82
+ xi = rcu_dereference (xfrmn -> collect_md_xfrmi );
83
+ if (xi && (xi -> dev -> flags & IFF_UP ))
84
+ return xi ;
85
+
80
86
return NULL ;
81
87
}
82
88
83
- static struct xfrm_if * xfrmi_decode_session (struct sk_buff * skb ,
84
- unsigned short family )
89
+ static bool xfrmi_decode_session (struct sk_buff * skb ,
90
+ unsigned short family ,
91
+ struct xfrm_if_decode_session_result * res )
85
92
{
86
93
struct net_device * dev ;
94
+ struct xfrm_if * xi ;
87
95
int ifindex = 0 ;
88
96
89
97
if (!secpath_exists (skb ) || !skb -> dev )
90
- return NULL ;
98
+ return false ;
91
99
92
100
switch (family ) {
93
101
case AF_INET6 :
@@ -107,11 +115,18 @@ static struct xfrm_if *xfrmi_decode_session(struct sk_buff *skb,
107
115
}
108
116
109
117
if (!dev || !(dev -> flags & IFF_UP ))
110
- return NULL ;
118
+ return false ;
111
119
if (dev -> netdev_ops != & xfrmi_netdev_ops )
112
- return NULL ;
120
+ return false ;
113
121
114
- return netdev_priv (dev );
122
+ xi = netdev_priv (dev );
123
+ res -> net = xi -> net ;
124
+
125
+ if (xi -> p .collect_md )
126
+ res -> if_id = xfrm_input_state (skb )-> if_id ;
127
+ else
128
+ res -> if_id = xi -> p .if_id ;
129
+ return true;
115
130
}
116
131
117
132
static void xfrmi_link (struct xfrmi_net * xfrmn , struct xfrm_if * xi )
@@ -157,7 +172,10 @@ static int xfrmi_create(struct net_device *dev)
157
172
if (err < 0 )
158
173
goto out ;
159
174
160
- xfrmi_link (xfrmn , xi );
175
+ if (xi -> p .collect_md )
176
+ rcu_assign_pointer (xfrmn -> collect_md_xfrmi , xi );
177
+ else
178
+ xfrmi_link (xfrmn , xi );
161
179
162
180
return 0 ;
163
181
@@ -185,7 +203,10 @@ static void xfrmi_dev_uninit(struct net_device *dev)
185
203
struct xfrm_if * xi = netdev_priv (dev );
186
204
struct xfrmi_net * xfrmn = net_generic (xi -> net , xfrmi_net_id );
187
205
188
- xfrmi_unlink (xfrmn , xi );
206
+ if (xi -> p .collect_md )
207
+ RCU_INIT_POINTER (xfrmn -> collect_md_xfrmi , NULL );
208
+ else
209
+ xfrmi_unlink (xfrmn , xi );
189
210
}
190
211
191
212
static void xfrmi_scrub_packet (struct sk_buff * skb , bool xnet )
@@ -214,6 +235,7 @@ static int xfrmi_rcv_cb(struct sk_buff *skb, int err)
214
235
struct xfrm_state * x ;
215
236
struct xfrm_if * xi ;
216
237
bool xnet ;
238
+ int link ;
217
239
218
240
if (err && !secpath_exists (skb ))
219
241
return 0 ;
@@ -224,6 +246,7 @@ static int xfrmi_rcv_cb(struct sk_buff *skb, int err)
224
246
if (!xi )
225
247
return 1 ;
226
248
249
+ link = skb -> dev -> ifindex ;
227
250
dev = xi -> dev ;
228
251
skb -> dev = dev ;
229
252
@@ -254,6 +277,17 @@ static int xfrmi_rcv_cb(struct sk_buff *skb, int err)
254
277
}
255
278
256
279
xfrmi_scrub_packet (skb , xnet );
280
+ if (xi -> p .collect_md ) {
281
+ struct metadata_dst * md_dst ;
282
+
283
+ md_dst = metadata_dst_alloc (0 , METADATA_XFRM , GFP_ATOMIC );
284
+ if (!md_dst )
285
+ return - ENOMEM ;
286
+
287
+ md_dst -> u .xfrm_info .if_id = x -> if_id ;
288
+ md_dst -> u .xfrm_info .link = link ;
289
+ skb_dst_set (skb , (struct dst_entry * )md_dst );
290
+ }
257
291
dev_sw_netstats_rx_add (dev , skb -> len );
258
292
259
293
return 0 ;
@@ -269,10 +303,23 @@ xfrmi_xmit2(struct sk_buff *skb, struct net_device *dev, struct flowi *fl)
269
303
struct net_device * tdev ;
270
304
struct xfrm_state * x ;
271
305
int err = -1 ;
306
+ u32 if_id ;
272
307
int mtu ;
273
308
309
+ if (xi -> p .collect_md ) {
310
+ struct xfrm_md_info * md_info = skb_xfrm_md_info (skb );
311
+
312
+ if (unlikely (!md_info ))
313
+ return - EINVAL ;
314
+
315
+ if_id = md_info -> if_id ;
316
+ fl -> flowi_oif = md_info -> link ;
317
+ } else {
318
+ if_id = xi -> p .if_id ;
319
+ }
320
+
274
321
dst_hold (dst );
275
- dst = xfrm_lookup_with_ifid (xi -> net , dst , fl , NULL , 0 , xi -> p . if_id );
322
+ dst = xfrm_lookup_with_ifid (xi -> net , dst , fl , NULL , 0 , if_id );
276
323
if (IS_ERR (dst )) {
277
324
err = PTR_ERR (dst );
278
325
dst = NULL ;
@@ -283,7 +330,7 @@ xfrmi_xmit2(struct sk_buff *skb, struct net_device *dev, struct flowi *fl)
283
330
if (!x )
284
331
goto tx_err_link_failure ;
285
332
286
- if (x -> if_id != xi -> p . if_id )
333
+ if (x -> if_id != if_id )
287
334
goto tx_err_link_failure ;
288
335
289
336
tdev = dst -> dev ;
@@ -633,6 +680,9 @@ static void xfrmi_netlink_parms(struct nlattr *data[],
633
680
634
681
if (data [IFLA_XFRM_IF_ID ])
635
682
parms -> if_id = nla_get_u32 (data [IFLA_XFRM_IF_ID ]);
683
+
684
+ if (data [IFLA_XFRM_COLLECT_METADATA ])
685
+ parms -> collect_md = true;
636
686
}
637
687
638
688
static int xfrmi_newlink (struct net * src_net , struct net_device * dev ,
@@ -645,14 +695,27 @@ static int xfrmi_newlink(struct net *src_net, struct net_device *dev,
645
695
int err ;
646
696
647
697
xfrmi_netlink_parms (data , & p );
648
- if (!p .if_id ) {
649
- NL_SET_ERR_MSG (extack , "if_id must be non zero" );
650
- return - EINVAL ;
651
- }
698
+ if (p .collect_md ) {
699
+ struct xfrmi_net * xfrmn = net_generic (net , xfrmi_net_id );
652
700
653
- xi = xfrmi_locate (net , & p );
654
- if (xi )
655
- return - EEXIST ;
701
+ if (p .link || p .if_id ) {
702
+ NL_SET_ERR_MSG (extack , "link and if_id must be zero" );
703
+ return - EINVAL ;
704
+ }
705
+
706
+ if (rtnl_dereference (xfrmn -> collect_md_xfrmi ))
707
+ return - EEXIST ;
708
+
709
+ } else {
710
+ if (!p .if_id ) {
711
+ NL_SET_ERR_MSG (extack , "if_id must be non zero" );
712
+ return - EINVAL ;
713
+ }
714
+
715
+ xi = xfrmi_locate (net , & p );
716
+ if (xi )
717
+ return - EEXIST ;
718
+ }
656
719
657
720
xi = netdev_priv (dev );
658
721
xi -> p = p ;
@@ -682,12 +745,22 @@ static int xfrmi_changelink(struct net_device *dev, struct nlattr *tb[],
682
745
return - EINVAL ;
683
746
}
684
747
748
+ if (p .collect_md ) {
749
+ NL_SET_ERR_MSG (extack , "collect_md can't be changed" );
750
+ return - EINVAL ;
751
+ }
752
+
685
753
xi = xfrmi_locate (net , & p );
686
754
if (!xi ) {
687
755
xi = netdev_priv (dev );
688
756
} else {
689
757
if (xi -> dev != dev )
690
758
return - EEXIST ;
759
+ if (xi -> p .collect_md ) {
760
+ NL_SET_ERR_MSG (extack ,
761
+ "device can't be changed to collect_md" );
762
+ return - EINVAL ;
763
+ }
691
764
}
692
765
693
766
return xfrmi_update (xi , & p );
@@ -700,6 +773,8 @@ static size_t xfrmi_get_size(const struct net_device *dev)
700
773
nla_total_size (4 ) +
701
774
/* IFLA_XFRM_IF_ID */
702
775
nla_total_size (4 ) +
776
+ /* IFLA_XFRM_COLLECT_METADATA */
777
+ nla_total_size (0 ) +
703
778
0 ;
704
779
}
705
780
@@ -709,7 +784,8 @@ static int xfrmi_fill_info(struct sk_buff *skb, const struct net_device *dev)
709
784
struct xfrm_if_parms * parm = & xi -> p ;
710
785
711
786
if (nla_put_u32 (skb , IFLA_XFRM_LINK , parm -> link ) ||
712
- nla_put_u32 (skb , IFLA_XFRM_IF_ID , parm -> if_id ))
787
+ nla_put_u32 (skb , IFLA_XFRM_IF_ID , parm -> if_id ) ||
788
+ (xi -> p .collect_md && nla_put_flag (skb , IFLA_XFRM_COLLECT_METADATA )))
713
789
goto nla_put_failure ;
714
790
return 0 ;
715
791
@@ -725,8 +801,10 @@ static struct net *xfrmi_get_link_net(const struct net_device *dev)
725
801
}
726
802
727
803
static const struct nla_policy xfrmi_policy [IFLA_XFRM_MAX + 1 ] = {
728
- [IFLA_XFRM_LINK ] = { .type = NLA_U32 },
729
- [IFLA_XFRM_IF_ID ] = { .type = NLA_U32 },
804
+ [IFLA_XFRM_UNSPEC ] = { .strict_start_type = IFLA_XFRM_COLLECT_METADATA },
805
+ [IFLA_XFRM_LINK ] = { .type = NLA_U32 },
806
+ [IFLA_XFRM_IF_ID ] = { .type = NLA_U32 },
807
+ [IFLA_XFRM_COLLECT_METADATA ] = { .type = NLA_FLAG },
730
808
};
731
809
732
810
static struct rtnl_link_ops xfrmi_link_ops __read_mostly = {
@@ -762,6 +840,9 @@ static void __net_exit xfrmi_exit_batch_net(struct list_head *net_exit_list)
762
840
xip = & xi -> next )
763
841
unregister_netdevice_queue (xi -> dev , & list );
764
842
}
843
+ xi = rtnl_dereference (xfrmn -> collect_md_xfrmi );
844
+ if (xi )
845
+ unregister_netdevice_queue (xi -> dev , & list );
765
846
}
766
847
unregister_netdevice_many (& list );
767
848
rtnl_unlock ();
0 commit comments