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
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
|
//
// packet buffer management
//
#define MBUF_SIZE 2048
#define MBUF_DEFAULT_HEADROOM 128
struct mbuf {
struct mbuf *next; // the next mbuf in the chain
char *head; // the current start position of the buffer
unsigned int len; // the length of the buffer
char buf[MBUF_SIZE]; // the backing store
};
char *mbufpull(struct mbuf *m, unsigned int len);
char *mbufpush(struct mbuf *m, unsigned int len);
char *mbufput(struct mbuf *m, unsigned int len);
char *mbuftrim(struct mbuf *m, unsigned int len);
// The above functions manipulate the size and position of the buffer:
// <- push <- trim
// -> pull -> put
// [-headroom-][------buffer------][-tailroom-]
// |----------------MBUF_SIZE-----------------|
//
// These marcos automatically typecast and determine the size of header structs.
// In most situations you should use these instead of the raw ops above.
#define mbufpullhdr(mbuf, hdr) (typeof(hdr)*)mbufpull(mbuf, sizeof(hdr))
#define mbufpushhdr(mbuf, hdr) (typeof(hdr)*)mbufpush(mbuf, sizeof(hdr))
#define mbufputhdr(mbuf, hdr) (typeof(hdr)*)mbufput(mbuf, sizeof(hdr))
#define mbuftrimhdr(mbuf, hdr) (typeof(hdr)*)mbuftrim(mbuf, sizeof(hdr))
struct mbuf *mbufalloc(unsigned int headroom);
void mbuffree(struct mbuf *m);
struct mbufq {
struct mbuf *head; // the first element in the queue
struct mbuf *tail; // the last element in the queue
};
void mbufq_pushtail(struct mbufq *q, struct mbuf *m);
struct mbuf *mbufq_pophead(struct mbufq *q);
int mbufq_empty(struct mbufq *q);
void mbufq_init(struct mbufq *q);
//
// endianness support
//
static inline uint16 bswaps(uint16 val)
{
return (((val & 0x00ffU) << 8) |
((val & 0xff00U) >> 8));
}
static inline uint32 bswapl(uint32 val)
{
return (((val & 0x000000ffUL) << 24) |
((val & 0x0000ff00UL) << 8) |
((val & 0x00ff0000UL) >> 8) |
((val & 0xff000000UL) >> 24));
}
// Use these macros to convert network bytes to the native byte order.
// Note that Risc-V uses little endian while network order is big endian.
#define ntohs bswaps
#define ntohl bswapl
#define htons bswaps
#define htonl bswapl
//
// useful networking headers
//
#define ETHADDR_LEN 6
// an Ethernet packet header (start of the packet).
struct eth {
uint8 dhost[ETHADDR_LEN];
uint8 shost[ETHADDR_LEN];
uint16 type;
} __attribute__((packed));
#define ETHTYPE_IP 0x0800 // Internet protocol
#define ETHTYPE_ARP 0x0806 // Address resolution protocol
// an IP packet header (comes after an Ethernet header).
struct ip {
uint8 ip_vhl; // version << 4 | header length >> 2
uint8 ip_tos; // type of service
uint16 ip_len; // total length
uint16 ip_id; // identification
uint16 ip_off; // fragment offset field
uint8 ip_ttl; // time to live
uint8 ip_p; // protocol
uint16 ip_sum; // checksum
uint32 ip_src, ip_dst;
};
#define IPPROTO_ICMP 1 // Control message protocol
#define IPPROTO_TCP 6 // Transmission control protocol
#define IPPROTO_UDP 17 // User datagram protocol
#define MAKE_IP_ADDR(a, b, c, d) \
(((uint32)a << 24) | ((uint32)b << 16) | \
((uint32)c << 8) | (uint32)d)
// a UDP packet header (comes after an IP header).
struct udp {
uint16 sport; // source port
uint16 dport; // destination port
uint16 ulen; // length, including udp header, not including IP header
uint16 sum; // checksum
};
// an ARP packet (comes after an Ethernet header).
struct arp {
uint16 hrd; // format of hardware address
uint16 pro; // format of protocol address
uint8 hln; // length of hardware address
uint8 pln; // length of protocol address
uint16 op; // operation
char sha[ETHADDR_LEN]; // sender hardware address
uint32 sip; // sender IP address
char tha[ETHADDR_LEN]; // target hardware address
uint32 tip; // target IP address
} __attribute__((packed));
#define ARP_HRD_ETHER 1 // Ethernet
enum {
ARP_OP_REQUEST = 1, // requests hw addr given protocol addr
ARP_OP_REPLY = 2, // replies a hw addr given protocol addr
};
// an DNS packet (comes after an UDP header).
struct dns {
uint16 id; // request ID
uint8 rd: 1; // recursion desired
uint8 tc: 1; // truncated
uint8 aa: 1; // authoritive
uint8 opcode: 4;
uint8 qr: 1; // query/response
uint8 rcode: 4; // response code
uint8 cd: 1; // checking disabled
uint8 ad: 1; // authenticated data
uint8 z: 1;
uint8 ra: 1; // recursion available
uint16 qdcount; // number of question entries
uint16 ancount; // number of resource records in answer section
uint16 nscount; // number of NS resource records in authority section
uint16 arcount; // number of resource records in additional records
} __attribute__((packed));
struct dns_question {
uint16 qtype;
uint16 qclass;
} __attribute__((packed));
#define ARECORD (0x0001)
#define QCLASS (0x0001)
struct dns_data {
uint16 type;
uint16 class;
uint32 ttl;
uint16 len;
} __attribute__((packed));
|