-
Notifications
You must be signed in to change notification settings - Fork 10
/
rx.h
140 lines (111 loc) · 3.62 KB
/
rx.h
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
135
136
137
138
139
#ifndef __RX_H__
#define __RX_H__
#include "tx.h"
struct iso_rx_stats {
u64 rx_bytes;
u64 rx_packets;
};
struct iso_rx_context {
ktime_t vq_last_update_time;
spinlock_t vq_spinlock;
struct list_head vq_list;
struct hlist_head vq_bucket[ISO_MAX_VQ_BUCKETS];
atomic_t vq_active_rate;
struct list_head list;
struct net_device *netdev;
/* Hierarchical RCP state */
struct iso_rx_stats __percpu *stats;
struct iso_rx_stats global_stats;
struct iso_rx_stats global_stats_last;
ktime_t last_stats_update_time;
ktime_t last_rcp_time;
u32 rcp_rate;
u32 rx_rate;
};
struct iso_rx_context *iso_rxctx_dev(const struct net_device *dev);
#ifndef QDISC
extern struct iso_rx_context global_rxcontext;
#endif
extern struct list_head rxctx_list;
#define for_each_rx_context(rxctx) list_for_each_entry_safe(rxctx, rxctx_next, &rxctx_list, list)
int iso_rx_init(struct iso_rx_context *);
void iso_rx_exit(struct iso_rx_context *);
enum iso_verdict iso_rx(struct sk_buff *skb, const struct net_device *out, struct iso_rx_context *rxctx);
static inline iso_class_t iso_rx_classify(struct sk_buff *);
int iso_vq_install(char *, struct iso_rx_context *);
static inline int iso_generate_feedback(int bit, struct sk_buff *pkt);
static inline int iso_is_generated_feedback(struct sk_buff *);
/* Create a feebdack packet and prepare for transmission. Returns 1 if successful. */
static inline int iso_generate_feedback(int bit, struct sk_buff *pkt) {
struct sk_buff *skb;
struct ethhdr *eth_to, *eth_from;
struct iphdr *iph_to, *iph_from;
eth_from = eth_hdr(pkt);
if(unlikely(eth_from->h_proto != __constant_htons(ETH_P_IP)))
return 0;
/* XXX: netdev_alloc_skb's meant to allocate packets for receiving.
* Is it okay to use for transmitting?
*/
skb = netdev_alloc_skb(pkt->dev, ISO_FEEDBACK_PACKET_SIZE);
if(likely(skb)) {
skb_set_queue_mapping(skb, 0);
skb->len = ISO_FEEDBACK_PACKET_SIZE;
skb->protocol = __constant_htons(ETH_P_IP);
skb->pkt_type = PACKET_OUTGOING;
skb_reset_mac_header(skb);
skb_set_tail_pointer(skb, ISO_FEEDBACK_PACKET_SIZE);
eth_to = eth_hdr(skb);
memcpy(eth_to->h_source, eth_from->h_dest, ETH_ALEN);
memcpy(eth_to->h_dest, eth_from->h_source, ETH_ALEN);
eth_to->h_proto = eth_from->h_proto;
skb_pull(skb, ETH_HLEN);
skb_reset_network_header(skb);
iph_to = ip_hdr(skb);
iph_from = ip_hdr(pkt);
iph_to->ihl = 5;
iph_to->version = 4;
iph_to->tos = 0x2 | (bit ? ISO_ECN_REFLECT_MASK : 0);
iph_to->tot_len = __constant_htons(ISO_FEEDBACK_HEADER_SIZE);
iph_to->id = bit; //iph_from->id;
iph_to->frag_off = 0;
iph_to->ttl = ISO_FEEDBACK_PACKET_TTL;
iph_to->protocol = (u8)ISO_FEEDBACK_PACKET_IPPROTO;
iph_to->saddr = iph_from->daddr;
iph_to->daddr = iph_from->saddr;
/* NB: this function doesn't "send" the packet */
ip_send_check(iph_to);
#if defined(QDISC) || defined(DIRECT)
skb_push(skb, ETH_HLEN);
#endif
/* Driver owns the buffer now; we don't need to free it */
skb_xmit(skb);
return 1;
}
return 0;
}
static inline int iso_is_generated_feedback(struct sk_buff *skb) {
struct ethhdr *eth;
struct iphdr *iph;
eth = eth_hdr(skb);
if(likely(eth->h_proto == __constant_htons(ETH_P_IP))) {
iph = ip_hdr(skb);
if(unlikely(iph->protocol == ISO_FEEDBACK_PACKET_IPPROTO))
return 1;
}
return 0;
}
static inline int iso_is_feedback_marked(struct sk_buff *skb) {
struct ethhdr *eth;
struct iphdr *iph;
eth = eth_hdr(skb);
if(likely(eth->h_proto == __constant_htons(ETH_P_IP))) {
iph = ip_hdr(skb);
if(unlikely(iph->protocol == ISO_FEEDBACK_PACKET_IPPROTO))
return (iph->id);
}
return 0;
}
#endif /* __RX_H__ */
/* Local Variables: */
/* indent-tabs-mode:t */
/* End: */