From: kbuild test robot <lkp@intel.com>
To: "Toke Høiland-Jørgensen" <toke@toke.dk>
Cc: kbuild-all@01.org, netdev@vger.kernel.org, cake@lists.bufferbloat.net
Subject: Re: [PATCH net-next v7 3/7] sch_cake: Add optional ACK filter
Date: Thu, 3 May 2018 16:26:44 +0800 [thread overview]
Message-ID: <201805031629.vXyGm7Ql%fengguang.wu@intel.com> (raw)
In-Reply-To: <152527387324.14936.10258520847821060114.stgit@alrua-kau>
Hi Toke,
Thank you for the patch! Perhaps something to improve:
[auto build test WARNING on net-next/master]
url: https://github.com/0day-ci/linux/commits/Toke-H-iland-J-rgensen/sched-Add-Common-Applications-Kept-Enhanced-cake-qdisc/20180503-073002
coccinelle warnings: (new ones prefixed by >>)
>> net/sched/sch_cake.c:1047:6-13: ERROR: PTR_ERR applied after initialization to constant on line 822
vim +1047 net/sched/sch_cake.c
812
813 static struct sk_buff *cake_ack_filter(struct cake_sched_data *q,
814 struct cake_flow *flow)
815 {
816 bool thisconn_redundant_seen = false, thisconn_seen_last = false;
817 bool aggressive = q->ack_filter == CAKE_ACK_AGGRESSIVE;
818 bool otherconn_ack_seen = false;
819 struct sk_buff *skb_check, *skb_check_prev;
820 struct sk_buff *otherconn_checked_to = NULL;
821 struct sk_buff *thisconn_checked_to = NULL;
822 struct sk_buff *thisconn_ack = NULL;
823 const struct ipv6hdr *ipv6h, *ipv6h_check;
824 const struct tcphdr *tcph, *tcph_check;
825 const struct iphdr *iph, *iph_check;
826 const struct sk_buff *skb;
827 struct ipv6hdr _iph, _iph_check;
828 struct tcphdr _tcph_check;
829 unsigned char _tcph[64]; /* need to hold maximum hdr size */
830 int seglen;
831
832 /* no other possible ACKs to filter */
833 if (flow->head == flow->tail)
834 return NULL;
835
836 skb = flow->tail;
837 tcph = cake_get_tcphdr(skb, _tcph, sizeof(_tcph));
838 iph = cake_get_iphdr(skb, &_iph);
839 if (!tcph)
840 return NULL;
841
842 /* the 'triggering' packet need only have the ACK flag set.
843 * also check that SYN is not set, as there won't be any previous ACKs.
844 */
845 if ((tcp_flag_word(tcph) &
846 (TCP_FLAG_ACK | TCP_FLAG_SYN)) != TCP_FLAG_ACK)
847 return NULL;
848
849 /* the 'triggering' ACK is at the end of the queue,
850 * we have already returned if it is the only packet in the flow.
851 * stop before last packet in queue, don't compare trigger ACK to itself
852 * start where we finished last time if recorded in ->ackcheck
853 * otherwise start from the the head of the flow queue.
854 */
855 skb_check_prev = flow->ackcheck;
856 skb_check = flow->ackcheck ?: flow->head;
857
858 while (skb_check->next) {
859 bool pure_ack, thisconn;
860
861 /* don't increment if at head of flow queue (_prev == NULL) */
862 if (skb_check_prev) {
863 skb_check_prev = skb_check;
864 skb_check = skb_check->next;
865 if (!skb_check->next)
866 break;
867 } else {
868 skb_check_prev = ERR_PTR(-1);
869 }
870
871 iph_check = cake_get_iphdr(skb_check, &_iph_check);
872 tcph_check = cake_get_tcphdr(skb_check, &_tcph_check,
873 sizeof(_tcph_check));
874
875 if (!tcph_check || iph->version != iph_check->version)
876 continue;
877
878 if (iph->version == 4) {
879 seglen = ntohs(iph_check->tot_len) -
880 (4 * iph_check->ihl);
881
882 thisconn = (iph_check->saddr == iph->saddr &&
883 iph_check->daddr == iph->daddr);
884 } else if (iph->version == 6) {
885 ipv6h = (struct ipv6hdr *)iph;
886 ipv6h_check = (struct ipv6hdr *)iph_check;
887 seglen = ntohs(ipv6h_check->payload_len);
888
889 thisconn = (!ipv6_addr_cmp(&ipv6h_check->saddr,
890 &ipv6h->saddr) &&
891 !ipv6_addr_cmp(&ipv6h_check->daddr,
892 &ipv6h->daddr));
893 } else {
894 WARN_ON(1); /* shouldn't happen */
895 continue;
896 }
897
898 /* stricter criteria apply to ACKs that we may filter
899 * 3 reserved flags must be unset to avoid future breakage
900 * ECE/CWR/NS can be safely ignored
901 * ACK must be set
902 * All other flags URG/PSH/RST/SYN/FIN must be unset
903 * 0x0FFF0000 = all TCP flags (confirm ACK=1, others zero)
904 * 0x01C00000 = NS/CWR/ECE (safe to ignore)
905 * 0x0E3F0000 = 0x0FFF0000 & ~0x01C00000
906 * must be 'pure' ACK, contain zero bytes of segment data
907 * options are ignored
908 */
909 if ((tcp_flag_word(tcph_check) &
910 (TCP_FLAG_ACK | TCP_FLAG_SYN)) != TCP_FLAG_ACK)
911 continue;
912
913 else if (((tcp_flag_word(tcph_check) &
914 cpu_to_be32(0x0E3F0000)) != TCP_FLAG_ACK) ||
915 ((seglen - __tcp_hdrlen(tcph_check)) != 0))
916 pure_ack = false;
917
918 else
919 pure_ack = true;
920
921 /* if we find an ACK belonging to a different connection
922 * continue checking for other ACKs this round however
923 * restart checking from the other connection next time.
924 */
925 if (thisconn && (tcph_check->source != tcph->source ||
926 tcph_check->dest != tcph->dest))
927 thisconn = false;
928
929 /* new ack sequence must be greater
930 */
931 if (thisconn &&
932 ((int32_t)(ntohl(tcph_check->ack_seq) -
933 ntohl(tcph->ack_seq)) > 0))
934 continue;
935
936 /* DupACKs with an equal sequence number shouldn't be filtered,
937 * but we can filter if the triggering packet is a SACK
938 */
939 if (thisconn &&
940 (ntohl(tcph_check->ack_seq) == ntohl(tcph->ack_seq))) {
941 /* inspired by tcp_parse_options in tcp_input.c */
942 bool sack = false;
943 int length = __tcp_hdrlen(tcph) - sizeof(struct tcphdr);
944 const u8 *ptr = (const u8 *)(tcph + 1);
945
946 while (length > 0) {
947 int opcode = *ptr++;
948 int opsize;
949
950 if (opcode == TCPOPT_EOL)
951 break;
952 if (opcode == TCPOPT_NOP) {
953 length--;
954 continue;
955 }
956 opsize = *ptr++;
957 if (opsize < 2 || opsize > length)
958 break;
959 if (opcode == TCPOPT_SACK) {
960 sack = true;
961 break;
962 }
963 ptr += opsize - 2;
964 length -= opsize;
965 }
966 if (!sack)
967 continue;
968 }
969
970 /* somewhat complicated control flow for 'conservative'
971 * ACK filtering that aims to be more polite to slow-start and
972 * in the presence of packet loss.
973 * does not filter if there is one 'redundant' ACK in the queue.
974 * 'data' ACKs won't be filtered but do count as redundant ACKs.
975 */
976 if (thisconn) {
977 thisconn_seen_last = true;
978 /* if aggressive and this is a data ack we can skip
979 * checking it next time.
980 */
981 thisconn_checked_to = (aggressive && !pure_ack) ?
982 skb_check : skb_check_prev;
983 /* the first pure ack for this connection.
984 * record where it is, but only break if aggressive
985 * or already seen data ack from the same connection
986 */
987 if (pure_ack && !thisconn_ack) {
988 thisconn_ack = skb_check_prev;
989 if (aggressive || thisconn_redundant_seen)
990 break;
991 /* data ack or subsequent pure ack */
992 } else {
993 thisconn_redundant_seen = true;
994 /* this is the second ack for this connection
995 * break to filter the first pure ack
996 */
997 if (thisconn_ack)
998 break;
999 }
1000 /* track packets from non-matching tcp connections that will
1001 * need evaluation on the next run.
1002 * if there are packets from both the matching connection and
1003 * others that requre checking next run, track which was updated
1004 * last and return the older of the two to ensure full coverage.
1005 * if a non-matching pure ack has been seen, cannot skip any
1006 * further on the next run so don't update.
1007 */
1008 } else if (!otherconn_ack_seen) {
1009 thisconn_seen_last = false;
1010 if (pure_ack) {
1011 otherconn_ack_seen = true;
1012 /* if aggressive we don't care about old data,
1013 * start from the pure ack.
1014 * otherwise if there is a previous data ack,
1015 * start checking from it next time.
1016 */
1017 if (aggressive || !otherconn_checked_to)
1018 otherconn_checked_to = skb_check_prev;
1019 } else {
1020 otherconn_checked_to = aggressive ?
1021 skb_check : skb_check_prev;
1022 }
1023 }
1024 }
1025
1026 /* skb_check is reused at this point
1027 * it is the pure ACK to be filtered (if any)
1028 */
1029 skb_check = NULL;
1030
1031 /* next time start checking from the older/nearest to head of unfiltered
1032 * but important tcp packets from this connection and other connections.
1033 * if none seen, start after the last packet evaluated in the loop.
1034 */
1035 if (thisconn_checked_to && otherconn_checked_to)
1036 flow->ackcheck = thisconn_seen_last ?
1037 otherconn_checked_to : thisconn_checked_to;
1038 else if (thisconn_checked_to)
1039 flow->ackcheck = thisconn_checked_to;
1040 else if (otherconn_checked_to)
1041 flow->ackcheck = otherconn_checked_to;
1042 else
1043 flow->ackcheck = skb_check_prev;
1044
1045 /* if filtering, remove the pure ACK from the flow queue */
1046 if (thisconn_ack && (aggressive || thisconn_redundant_seen)) {
> 1047 if (PTR_ERR(thisconn_ack) == -1) {
1048 skb_check = flow->head;
1049 flow->head = flow->head->next;
1050 } else {
1051 skb_check = thisconn_ack->next;
1052 thisconn_ack->next = thisconn_ack->next->next;
1053 }
1054 }
1055
1056 /* we just filtered that ack, fix up the list */
1057 if (flow->ackcheck == skb_check)
1058 flow->ackcheck = thisconn_ack;
1059 /* check the entire flow queue next time */
1060 if (PTR_ERR(flow->ackcheck) == -1)
1061 flow->ackcheck = NULL;
1062
1063 return skb_check;
1064 }
1065
---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation
next prev parent reply other threads:[~2018-05-03 8:27 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-05-02 15:10 [PATCH net-next v7 0/7] sched: Add Common Applications Kept Enhanced (cake) qdisc Toke Høiland-Jørgensen
2018-05-02 15:11 ` [PATCH net-next v7 1/7] " Toke Høiland-Jørgensen
2018-05-03 5:05 ` kbuild test robot
2018-05-03 5:05 ` [PATCH] sched: fix semicolon.cocci warnings kbuild test robot
2018-05-03 15:24 ` [PATCH net-next v7 1/7] sched: Add Common Applications Kept Enhanced (cake) qdisc David Miller
2018-05-03 15:28 ` Toke Høiland-Jørgensen
2018-05-02 15:11 ` [PATCH net-next v7 2/7] sch_cake: Add ingress mode Toke Høiland-Jørgensen
2018-05-02 15:11 ` [PATCH net-next v7 3/7] sch_cake: Add optional ACK filter Toke Høiland-Jørgensen
2018-05-03 8:26 ` kbuild test robot [this message]
2018-05-02 15:11 ` [PATCH net-next v7 4/7] sch_cake: Add NAT awareness to packet classifier Toke Høiland-Jørgensen
2018-05-02 15:11 ` [PATCH net-next v7 5/7] sch_cake: Add DiffServ handling Toke Høiland-Jørgensen
2018-05-02 15:11 ` [PATCH net-next v7 6/7] sch_cake: Add overhead compensation support to the rate shaper Toke Høiland-Jørgensen
2018-05-02 15:11 ` [PATCH net-next v7 7/7] sch_cake: Conditionally split GSO segments Toke Høiland-Jørgensen
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=201805031629.vXyGm7Ql%fengguang.wu@intel.com \
--to=lkp@intel.com \
--cc=cake@lists.bufferbloat.net \
--cc=kbuild-all@01.org \
--cc=netdev@vger.kernel.org \
--cc=toke@toke.dk \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.