// // 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));