3232#include <uapi/linux/tc_act/tc_ife.h>
3333#include <net/tc_act/tc_ife.h>
3434#include <linux/etherdevice.h>
35+ #include <net/ife.h>
3536
3637#define IFE_TAB_MASK 15
3738
@@ -46,23 +47,6 @@ static const struct nla_policy ife_policy[TCA_IFE_MAX + 1] = {
4647 [TCA_IFE_TYPE ] = { .type = NLA_U16 },
4748};
4849
49- /* Caller takes care of presenting data in network order
50- */
51- static int ife_tlv_meta_encode (void * skbdata , u16 attrtype , u16 dlen ,
52- const void * dval )
53- {
54- u32 * tlv = (u32 * )(skbdata );
55- u16 totlen = nla_total_size (dlen ); /*alignment + hdr */
56- char * dptr = (char * )tlv + NLA_HDRLEN ;
57- u32 htlv = attrtype << 16 | (dlen + NLA_HDRLEN );
58-
59- * tlv = htonl (htlv );
60- memset (dptr , 0 , totlen - NLA_HDRLEN );
61- memcpy (dptr , dval , dlen );
62-
63- return totlen ;
64- }
65-
6650int ife_encode_meta_u16 (u16 metaval , void * skbdata , struct tcf_meta_info * mi )
6751{
6852 u16 edata = 0 ;
@@ -637,69 +621,59 @@ int find_decode_metaid(struct sk_buff *skb, struct tcf_ife_info *ife,
637621 return 0 ;
638622}
639623
640- struct ifeheadr {
641- __be16 metalen ;
642- u8 tlv_data [];
643- };
644-
645- struct meta_tlvhdr {
646- __be16 type ;
647- __be16 len ;
648- };
649-
650624static int tcf_ife_decode (struct sk_buff * skb , const struct tc_action * a ,
651625 struct tcf_result * res )
652626{
653627 struct tcf_ife_info * ife = to_ife (a );
654628 int action = ife -> tcf_action ;
655- struct ifeheadr * ifehdr = ( struct ifeheadr * ) skb -> data ;
656- int ifehdrln = ( int ) ifehdr -> metalen ;
657- struct meta_tlvhdr * tlv = ( struct meta_tlvhdr * )( ifehdr -> tlv_data ) ;
629+ u8 * ifehdr_end ;
630+ u8 * tlv_data ;
631+ u16 metalen ;
658632
659633 spin_lock (& ife -> tcf_lock );
660634 bstats_update (& ife -> tcf_bstats , skb );
661635 tcf_lastuse_update (& ife -> tcf_tm );
662636 spin_unlock (& ife -> tcf_lock );
663637
664- ifehdrln = ntohs (ifehdrln );
665- if (unlikely (!pskb_may_pull (skb , ifehdrln ))) {
638+ if (skb_at_tc_ingress (skb ))
639+ skb_push (skb , skb -> dev -> hard_header_len );
640+
641+ tlv_data = ife_decode (skb , & metalen );
642+ if (unlikely (!tlv_data )) {
666643 spin_lock (& ife -> tcf_lock );
667644 ife -> tcf_qstats .drops ++ ;
668645 spin_unlock (& ife -> tcf_lock );
669646 return TC_ACT_SHOT ;
670647 }
671648
672- skb_set_mac_header (skb , ifehdrln );
673- __skb_pull (skb , ifehdrln );
674- skb -> protocol = eth_type_trans (skb , skb -> dev );
675- ifehdrln -= IFE_METAHDRLEN ;
676-
677- while (ifehdrln > 0 ) {
678- u8 * tlvdata = (u8 * )tlv ;
679- u16 mtype = tlv -> type ;
680- u16 mlen = tlv -> len ;
681- u16 alen ;
649+ ifehdr_end = tlv_data + metalen ;
650+ for (; tlv_data < ifehdr_end ; tlv_data = ife_tlv_meta_next (tlv_data )) {
651+ u8 * curr_data ;
652+ u16 mtype ;
653+ u16 dlen ;
682654
683- mtype = ntohs (mtype );
684- mlen = ntohs (mlen );
685- alen = NLA_ALIGN (mlen );
655+ curr_data = ife_tlv_meta_decode (tlv_data , & mtype , & dlen , NULL );
686656
687- if (find_decode_metaid (skb , ife , mtype , (mlen - NLA_HDRLEN ),
688- (void * )(tlvdata + NLA_HDRLEN ))) {
657+ if (find_decode_metaid (skb , ife , mtype , dlen , curr_data )) {
689658 /* abuse overlimits to count when we receive metadata
690659 * but dont have an ops for it
691660 */
692- pr_info_ratelimited ("Unknown metaid %d alnlen %d\n" ,
693- mtype , mlen );
661+ pr_info_ratelimited ("Unknown metaid %d dlen %d\n" ,
662+ mtype , dlen );
694663 ife -> tcf_qstats .overlimits ++ ;
695664 }
665+ }
696666
697- tlvdata += alen ;
698- ifehdrln -= alen ;
699- tlv = (struct meta_tlvhdr * )tlvdata ;
667+ if (WARN_ON (tlv_data != ifehdr_end )) {
668+ spin_lock (& ife -> tcf_lock );
669+ ife -> tcf_qstats .drops ++ ;
670+ spin_unlock (& ife -> tcf_lock );
671+ return TC_ACT_SHOT ;
700672 }
701673
674+ skb -> protocol = eth_type_trans (skb , skb -> dev );
702675 skb_reset_network_header (skb );
676+
703677 return action ;
704678}
705679
@@ -727,18 +701,18 @@ static int tcf_ife_encode(struct sk_buff *skb, const struct tc_action *a,
727701 struct tcf_ife_info * ife = to_ife (a );
728702 int action = ife -> tcf_action ;
729703 struct ethhdr * oethh ; /* outer ether header */
730- struct ethhdr * iethh ; /* inner eth header */
731704 struct tcf_meta_info * e ;
732705 /*
733706 OUTERHDR:TOTMETALEN:{TLVHDR:Metadatum:TLVHDR..}:ORIGDATA
734707 where ORIGDATA = original ethernet header ...
735708 */
736709 u16 metalen = ife_get_sz (skb , ife );
737710 int hdrm = metalen + skb -> dev -> hard_header_len + IFE_METAHDRLEN ;
738- unsigned int skboff = skb -> dev -> hard_header_len ;
711+ unsigned int skboff = 0 ;
739712 int new_len = skb -> len + hdrm ;
740713 bool exceed_mtu = false;
741- int err ;
714+ void * ife_meta ;
715+ int err = 0 ;
742716
743717 if (!skb_at_tc_ingress (skb )) {
744718 if (new_len > skb -> dev -> mtu )
@@ -765,35 +739,18 @@ static int tcf_ife_encode(struct sk_buff *skb, const struct tc_action *a,
765739 return TC_ACT_SHOT ;
766740 }
767741
768- err = skb_cow_head (skb , hdrm );
769- if (unlikely (err )) {
770- ife -> tcf_qstats .drops ++ ;
771- spin_unlock (& ife -> tcf_lock );
772- return TC_ACT_SHOT ;
773- }
774-
775742 if (skb_at_tc_ingress (skb ))
776743 skb_push (skb , skb -> dev -> hard_header_len );
777744
778- iethh = (struct ethhdr * )skb -> data ;
779- __skb_push (skb , hdrm );
780- memcpy (skb -> data , iethh , skb -> mac_len );
781- skb_reset_mac_header (skb );
782- oethh = eth_hdr (skb );
783-
784- /*total metadata length */
785- metalen += IFE_METAHDRLEN ;
786- metalen = htons (metalen );
787- memcpy ((skb -> data + skboff ), & metalen , IFE_METAHDRLEN );
788- skboff += IFE_METAHDRLEN ;
745+ ife_meta = ife_encode (skb , metalen );
789746
790747 /* XXX: we dont have a clever way of telling encode to
791748 * not repeat some of the computations that are done by
792749 * ops->presence_check...
793750 */
794751 list_for_each_entry (e , & ife -> metalist , metalist ) {
795752 if (e -> ops -> encode ) {
796- err = e -> ops -> encode (skb , (void * )(skb -> data + skboff ),
753+ err = e -> ops -> encode (skb , (void * )(ife_meta + skboff ),
797754 e );
798755 }
799756 if (err < 0 ) {
@@ -804,15 +761,12 @@ static int tcf_ife_encode(struct sk_buff *skb, const struct tc_action *a,
804761 }
805762 skboff += err ;
806763 }
764+ oethh = (struct ethhdr * )skb -> data ;
807765
808766 if (!is_zero_ether_addr (ife -> eth_src ))
809767 ether_addr_copy (oethh -> h_source , ife -> eth_src );
810- else
811- ether_addr_copy (oethh -> h_source , iethh -> h_source );
812768 if (!is_zero_ether_addr (ife -> eth_dst ))
813769 ether_addr_copy (oethh -> h_dest , ife -> eth_dst );
814- else
815- ether_addr_copy (oethh -> h_dest , iethh -> h_dest );
816770 oethh -> h_proto = htons (ife -> eth_type );
817771
818772 if (skb_at_tc_ingress (skb ))
0 commit comments