@@ -177,6 +177,35 @@ static u32 convert_skb_access(int skb_field, int dst_reg, int src_reg,
177177 * insn ++ = BPF_LDX_MEM (BPF_H , dst_reg , src_reg ,
178178 offsetof(struct sk_buff , queue_mapping ));
179179 break ;
180+
181+ case SKF_AD_PROTOCOL :
182+ BUILD_BUG_ON (FIELD_SIZEOF (struct sk_buff , protocol ) != 2 );
183+
184+ /* dst_reg = *(u16 *) (src_reg + offsetof(protocol)) */
185+ * insn ++ = BPF_LDX_MEM (BPF_H , dst_reg , src_reg ,
186+ offsetof(struct sk_buff , protocol ));
187+ /* dst_reg = ntohs(dst_reg) [emitting a nop or swap16] */
188+ * insn ++ = BPF_ENDIAN (BPF_FROM_BE , dst_reg , 16 );
189+ break ;
190+
191+ case SKF_AD_VLAN_TAG :
192+ case SKF_AD_VLAN_TAG_PRESENT :
193+ BUILD_BUG_ON (FIELD_SIZEOF (struct sk_buff , vlan_tci ) != 2 );
194+ BUILD_BUG_ON (VLAN_TAG_PRESENT != 0x1000 );
195+
196+ /* dst_reg = *(u16 *) (src_reg + offsetof(vlan_tci)) */
197+ * insn ++ = BPF_LDX_MEM (BPF_H , dst_reg , src_reg ,
198+ offsetof(struct sk_buff , vlan_tci ));
199+ if (skb_field == SKF_AD_VLAN_TAG ) {
200+ * insn ++ = BPF_ALU32_IMM (BPF_AND , dst_reg ,
201+ ~VLAN_TAG_PRESENT );
202+ } else {
203+ /* dst_reg >>= 12 */
204+ * insn ++ = BPF_ALU32_IMM (BPF_RSH , dst_reg , 12 );
205+ /* dst_reg &= 1 */
206+ * insn ++ = BPF_ALU32_IMM (BPF_AND , dst_reg , 1 );
207+ }
208+ break ;
180209 }
181210
182211 return insn - insn_buf ;
@@ -190,13 +219,8 @@ static bool convert_bpf_extensions(struct sock_filter *fp,
190219
191220 switch (fp -> k ) {
192221 case SKF_AD_OFF + SKF_AD_PROTOCOL :
193- BUILD_BUG_ON (FIELD_SIZEOF (struct sk_buff , protocol ) != 2 );
194-
195- /* A = *(u16 *) (CTX + offsetof(protocol)) */
196- * insn ++ = BPF_LDX_MEM (BPF_H , BPF_REG_A , BPF_REG_CTX ,
197- offsetof(struct sk_buff , protocol ));
198- /* A = ntohs(A) [emitting a nop or swap16] */
199- * insn = BPF_ENDIAN (BPF_FROM_BE , BPF_REG_A , 16 );
222+ cnt = convert_skb_access (SKF_AD_PROTOCOL , BPF_REG_A , BPF_REG_CTX , insn );
223+ insn += cnt - 1 ;
200224 break ;
201225
202226 case SKF_AD_OFF + SKF_AD_PKTTYPE :
@@ -242,22 +266,15 @@ static bool convert_bpf_extensions(struct sock_filter *fp,
242266 break ;
243267
244268 case SKF_AD_OFF + SKF_AD_VLAN_TAG :
245- case SKF_AD_OFF + SKF_AD_VLAN_TAG_PRESENT :
246- BUILD_BUG_ON (FIELD_SIZEOF (struct sk_buff , vlan_tci ) != 2 );
247- BUILD_BUG_ON (VLAN_TAG_PRESENT != 0x1000 );
269+ cnt = convert_skb_access (SKF_AD_VLAN_TAG ,
270+ BPF_REG_A , BPF_REG_CTX , insn );
271+ insn += cnt - 1 ;
272+ break ;
248273
249- /* A = *(u16 *) (CTX + offsetof(vlan_tci)) */
250- * insn ++ = BPF_LDX_MEM (BPF_H , BPF_REG_A , BPF_REG_CTX ,
251- offsetof(struct sk_buff , vlan_tci ));
252- if (fp -> k == SKF_AD_OFF + SKF_AD_VLAN_TAG ) {
253- * insn = BPF_ALU32_IMM (BPF_AND , BPF_REG_A ,
254- ~VLAN_TAG_PRESENT );
255- } else {
256- /* A >>= 12 */
257- * insn ++ = BPF_ALU32_IMM (BPF_RSH , BPF_REG_A , 12 );
258- /* A &= 1 */
259- * insn = BPF_ALU32_IMM (BPF_AND , BPF_REG_A , 1 );
260- }
274+ case SKF_AD_OFF + SKF_AD_VLAN_TAG_PRESENT :
275+ cnt = convert_skb_access (SKF_AD_VLAN_TAG_PRESENT ,
276+ BPF_REG_A , BPF_REG_CTX , insn );
277+ insn += cnt - 1 ;
261278 break ;
262279
263280 case SKF_AD_OFF + SKF_AD_PAY_OFFSET :
@@ -1215,6 +1232,17 @@ static u32 sk_filter_convert_ctx_access(int dst_reg, int src_reg, int ctx_off,
12151232
12161233 case offsetof(struct __sk_buff , queue_mapping ):
12171234 return convert_skb_access (SKF_AD_QUEUE , dst_reg , src_reg , insn );
1235+
1236+ case offsetof(struct __sk_buff , protocol ):
1237+ return convert_skb_access (SKF_AD_PROTOCOL , dst_reg , src_reg , insn );
1238+
1239+ case offsetof(struct __sk_buff , vlan_present ):
1240+ return convert_skb_access (SKF_AD_VLAN_TAG_PRESENT ,
1241+ dst_reg , src_reg , insn );
1242+
1243+ case offsetof(struct __sk_buff , vlan_tci ):
1244+ return convert_skb_access (SKF_AD_VLAN_TAG ,
1245+ dst_reg , src_reg , insn );
12181246 }
12191247
12201248 return insn - insn_buf ;
0 commit comments