@@ -785,7 +785,8 @@ static int bpf_tcp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len,
785
785
i ++ ;
786
786
if (i == MAX_SKB_FRAGS )
787
787
i = 0 ;
788
- put_page (page );
788
+ if (!md -> skb )
789
+ put_page (page );
789
790
}
790
791
if (copied == len )
791
792
break ;
@@ -794,6 +795,8 @@ static int bpf_tcp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len,
794
795
795
796
if (!sg -> length && md -> sg_start == md -> sg_end ) {
796
797
list_del (& md -> list );
798
+ if (md -> skb )
799
+ consume_skb (md -> skb );
797
800
kfree (md );
798
801
}
799
802
}
@@ -1045,27 +1048,72 @@ static int smap_verdict_func(struct smap_psock *psock, struct sk_buff *skb)
1045
1048
__SK_DROP ;
1046
1049
}
1047
1050
1051
+ static int smap_do_ingress (struct smap_psock * psock , struct sk_buff * skb )
1052
+ {
1053
+ struct sock * sk = psock -> sock ;
1054
+ int copied = 0 , num_sg ;
1055
+ struct sk_msg_buff * r ;
1056
+
1057
+ r = kzalloc (sizeof (struct sk_msg_buff ), __GFP_NOWARN | GFP_ATOMIC );
1058
+ if (unlikely (!r ))
1059
+ return - EAGAIN ;
1060
+
1061
+ if (!sk_rmem_schedule (sk , skb , skb -> len )) {
1062
+ kfree (r );
1063
+ return - EAGAIN ;
1064
+ }
1065
+
1066
+ sg_init_table (r -> sg_data , MAX_SKB_FRAGS );
1067
+ num_sg = skb_to_sgvec (skb , r -> sg_data , 0 , skb -> len );
1068
+ if (unlikely (num_sg < 0 )) {
1069
+ kfree (r );
1070
+ return num_sg ;
1071
+ }
1072
+ sk_mem_charge (sk , skb -> len );
1073
+ copied = skb -> len ;
1074
+ r -> sg_start = 0 ;
1075
+ r -> sg_end = num_sg == MAX_SKB_FRAGS ? 0 : num_sg ;
1076
+ r -> skb = skb ;
1077
+ list_add_tail (& r -> list , & psock -> ingress );
1078
+ sk -> sk_data_ready (sk );
1079
+ return copied ;
1080
+ }
1081
+
1048
1082
static void smap_do_verdict (struct smap_psock * psock , struct sk_buff * skb )
1049
1083
{
1084
+ struct smap_psock * peer ;
1050
1085
struct sock * sk ;
1086
+ __u32 in ;
1051
1087
int rc ;
1052
1088
1053
1089
rc = smap_verdict_func (psock , skb );
1054
1090
switch (rc ) {
1055
1091
case __SK_REDIRECT :
1056
1092
sk = do_sk_redirect_map (skb );
1057
- if (likely (sk )) {
1058
- struct smap_psock * peer = smap_psock_sk (sk );
1059
-
1060
- if (likely (peer &&
1061
- test_bit (SMAP_TX_RUNNING , & peer -> state ) &&
1062
- !sock_flag (sk , SOCK_DEAD ) &&
1063
- sock_writeable (sk ))) {
1064
- skb_set_owner_w (skb , sk );
1065
- skb_queue_tail (& peer -> rxqueue , skb );
1066
- schedule_work (& peer -> tx_work );
1067
- break ;
1068
- }
1093
+ if (!sk ) {
1094
+ kfree_skb (skb );
1095
+ break ;
1096
+ }
1097
+
1098
+ peer = smap_psock_sk (sk );
1099
+ in = (TCP_SKB_CB (skb )-> bpf .flags ) & BPF_F_INGRESS ;
1100
+
1101
+ if (unlikely (!peer || sock_flag (sk , SOCK_DEAD ) ||
1102
+ !test_bit (SMAP_TX_RUNNING , & peer -> state ))) {
1103
+ kfree_skb (skb );
1104
+ break ;
1105
+ }
1106
+
1107
+ if (!in && sock_writeable (sk )) {
1108
+ skb_set_owner_w (skb , sk );
1109
+ skb_queue_tail (& peer -> rxqueue , skb );
1110
+ schedule_work (& peer -> tx_work );
1111
+ break ;
1112
+ } else if (in &&
1113
+ atomic_read (& sk -> sk_rmem_alloc ) <= sk -> sk_rcvbuf ) {
1114
+ skb_queue_tail (& peer -> rxqueue , skb );
1115
+ schedule_work (& peer -> tx_work );
1116
+ break ;
1069
1117
}
1070
1118
/* Fall through and free skb otherwise */
1071
1119
case __SK_DROP :
@@ -1127,15 +1175,23 @@ static void smap_tx_work(struct work_struct *w)
1127
1175
}
1128
1176
1129
1177
while ((skb = skb_dequeue (& psock -> rxqueue ))) {
1178
+ __u32 flags ;
1179
+
1130
1180
rem = skb -> len ;
1131
1181
off = 0 ;
1132
1182
start :
1183
+ flags = (TCP_SKB_CB (skb )-> bpf .flags ) & BPF_F_INGRESS ;
1133
1184
do {
1134
- if (likely (psock -> sock -> sk_socket ))
1135
- n = skb_send_sock_locked (psock -> sock ,
1136
- skb , off , rem );
1137
- else
1185
+ if (likely (psock -> sock -> sk_socket )) {
1186
+ if (flags )
1187
+ n = smap_do_ingress (psock , skb );
1188
+ else
1189
+ n = skb_send_sock_locked (psock -> sock ,
1190
+ skb , off , rem );
1191
+ } else {
1138
1192
n = - EINVAL ;
1193
+ }
1194
+
1139
1195
if (n <= 0 ) {
1140
1196
if (n == - EAGAIN ) {
1141
1197
/* Retry when space is available */
@@ -1153,7 +1209,9 @@ static void smap_tx_work(struct work_struct *w)
1153
1209
rem -= n ;
1154
1210
off += n ;
1155
1211
} while (rem );
1156
- kfree_skb (skb );
1212
+
1213
+ if (!flags )
1214
+ kfree_skb (skb );
1157
1215
}
1158
1216
out :
1159
1217
release_sock (psock -> sock );
0 commit comments