6b13f685e
김민수
BSP 최초 추가
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
|
#ifndef _UDPLITE_H
#define _UDPLITE_H
#include <net/ip6_checksum.h>
#define UDPLITE_SEND_CSCOV 10 /* sender partial coverage (as sent) */
#define UDPLITE_RECV_CSCOV 11 /* receiver partial coverage (threshold ) */
extern struct proto udplite_prot;
extern struct udp_table udplite_table;
static __inline__ int udplite_getfrag(void *from, char *to, int offset,
int len, int odd, struct sk_buff *skb)
{
return memcpy_fromiovecend(to, (struct iovec *) from, offset, len);
}
static inline int udplite_sk_init(struct sock *sk)
{
udp_sk(sk)->pcflag = UDPLITE_BIT;
return 0;
}
static inline int udplite_checksum_init(struct sk_buff *skb, struct udphdr *uh)
{
u16 cscov;
if (uh->check == 0) {
LIMIT_NETDEBUG(KERN_DEBUG "UDPLite: zeroed checksum field
");
return 1;
}
cscov = ntohs(uh->len);
if (cscov == 0)
;
else if (cscov < 8 || cscov > skb->len) {
LIMIT_NETDEBUG(KERN_DEBUG "UDPLite: bad csum coverage %d/%d
",
cscov, skb->len);
return 1;
} else if (cscov < skb->len) {
UDP_SKB_CB(skb)->partial_cov = 1;
UDP_SKB_CB(skb)->cscov = cscov;
if (skb->ip_summed == CHECKSUM_COMPLETE)
skb->ip_summed = CHECKSUM_NONE;
}
return 0;
}
static inline __wsum udplite_csum_outgoing(struct sock *sk, struct sk_buff *skb)
{
const struct udp_sock *up = udp_sk(skb->sk);
int cscov = up->len;
__wsum csum = 0;
if (up->pcflag & UDPLITE_SEND_CC) {
if (up->pcslen < up->len) {
if (0 < up->pcslen)
cscov = up->pcslen;
udp_hdr(skb)->len = htons(up->pcslen);
}
}
skb->ip_summed = CHECKSUM_NONE;
skb_queue_walk(&sk->sk_write_queue, skb) {
const int off = skb_transport_offset(skb);
const int len = skb->len - off;
csum = skb_checksum(skb, off, (cscov > len)? len : cscov, csum);
if ((cscov -= len) <= 0)
break;
}
return csum;
}
static inline __wsum udplite_csum(struct sk_buff *skb)
{
const struct udp_sock *up = udp_sk(skb->sk);
const int off = skb_transport_offset(skb);
int len = skb->len - off;
if ((up->pcflag & UDPLITE_SEND_CC) && up->pcslen < len) {
if (0 < up->pcslen)
len = up->pcslen;
udp_hdr(skb)->len = htons(up->pcslen);
}
skb->ip_summed = CHECKSUM_NONE;
return skb_checksum(skb, off, len, 0);
}
void udplite4_register(void);
int udplite_get_port(struct sock *sk, unsigned short snum,
int (*scmp)(const struct sock *, const struct sock *));
#endif /* _UDPLITE_H */
|