1 #include <stdio.h>
2
3 #include <stdint.h>
4 #include <stdlib.h>
5 #include <unistd.h>
6 #include <assert.h>
7
8 #ifdef DARWIN
9 #include <netinet/if_ether.h>
10 #include <netinet/tcp.h>
11 #else
12 #include <linux/if_ether.h>
13 #include <linux/tcp.h>
14 #endif
15 #include <string.h>
16 #include <netinet/ip.h>
17
18 #include "mtcp.h"
19 #include "arp.h"
20 #include "eth_out.h"
21 #include "debug.h"
22 #include "mos_api.h"
23 #include "config.h"
24
25 #ifndef TRUE
26 #define TRUE (1)
27 #endif
28
29 #ifndef FALSE
30 #define FALSE (0)
31 #endif
32
33 #ifndef ERROR
34 #define ERROR (-1)
35 #endif
36
37 #define MAX(a, b) ((a)>(b)?(a):(b))
38 #define MIN(a, b) ((a)<(b)?(a):(b))
39
40 #define MAX_WINDOW_SIZE 65535
41
42 /*----------------------------------------------------------------------------*/
43 enum ETH_BUFFER_RETURN {BUF_RET_MAYBE, BUF_RET_ALWAYS};
44 /*----------------------------------------------------------------------------*/
45 int
FlushSendChunkBuf(mtcp_manager_t mtcp,int nif)46 FlushSendChunkBuf(mtcp_manager_t mtcp, int nif)
47 {
48 return 0;
49 }
50 /*----------------------------------------------------------------------------*/
51 inline void
FillOutPacketEthContext(struct pkt_ctx * pctx,uint32_t cur_ts,int out_ifidx,struct ethhdr * ethh,int eth_len)52 FillOutPacketEthContext(struct pkt_ctx *pctx, uint32_t cur_ts, int out_ifidx,
53 struct ethhdr *ethh, int eth_len)
54 {
55 pctx->p.cur_ts = cur_ts;
56 pctx->p.in_ifidx = -1;
57 pctx->out_ifidx = out_ifidx;
58 pctx->p.ethh = ethh;
59 pctx->p.eth_len = eth_len;
60 }
61 /*----------------------------------------------------------------------------*/
62 uint8_t *
EthernetOutput(struct mtcp_manager * mtcp,struct pkt_ctx * pctx,uint16_t h_proto,int nif,unsigned char * dst_haddr,uint16_t iplen,uint32_t cur_ts)63 EthernetOutput(struct mtcp_manager *mtcp, struct pkt_ctx *pctx,
64 uint16_t h_proto, int nif, unsigned char* dst_haddr, uint16_t iplen,
65 uint32_t cur_ts)
66 {
67 uint8_t *buf;
68 struct ethhdr *ethh;
69 int i;
70
71 /*
72 * -sanity check-
73 * return early if no interface is set (if routing entry does not exist)
74 */
75 if (nif < 0) {
76 TRACE_INFO("No interface set!\n");
77 return NULL;
78 }
79
80 if (!mtcp->iom->get_wptr) {
81 TRACE_INFO("get_wptr() in io_module is undefined.");
82 return NULL;
83 }
84 buf = mtcp->iom->get_wptr(mtcp->ctx, nif, iplen + ETHERNET_HEADER_LEN);
85 if (!buf) {
86 TRACE_DBG("Failed to get available write buffer\n");
87 return NULL;
88 }
89
90 ethh = (struct ethhdr *)buf;
91 for (i = 0; i < ETH_ALEN; i++) {
92 ethh->h_source[i] = g_config.mos->netdev_table->ent[nif]->haddr[i];
93 ethh->h_dest[i] = dst_haddr[i];
94 }
95 ethh->h_proto = htons(h_proto);
96
97 if (pctx)
98 FillOutPacketEthContext(pctx, cur_ts, nif,
99 ethh, iplen + ETHERNET_HEADER_LEN);
100
101 return (uint8_t *)(ethh + 1);
102 }
103 /*----------------------------------------------------------------------------*/
104 void
ForwardEthernetFrame(struct mtcp_manager * mtcp,struct pkt_ctx * pctx)105 ForwardEthernetFrame(struct mtcp_manager *mtcp, struct pkt_ctx *pctx)
106 {
107 uint8_t *buf;
108
109 if (g_config.mos->nic_forward_table != NULL) {
110 pctx->out_ifidx =
111 g_config.mos->nic_forward_table->nic_fwd_table[pctx->p.in_ifidx];
112
113 if (pctx->out_ifidx == -1) {
114 TRACE_DBG("Could not find outgoing index (index)!\n");
115 return;
116 }
117
118 if (!mtcp->iom->get_wptr) {
119 TRACE_INFO("get_wptr() in io_module is undefined.");
120 return;
121 }
122
123 buf = mtcp->iom->get_wptr(mtcp->ctx, pctx->out_ifidx, pctx->p.eth_len);
124
125 if (!buf) {
126 TRACE_DBG("Failed to get available write buffer\n");
127 return;
128 }
129
130 memcpy(buf, pctx->p.ethh, pctx->p.eth_len);
131 } else {
132 TRACE_DBG("Ethernet forwarding table entry does not exist.\n");
133 }
134 }
135 /*----------------------------------------------------------------------------*/
136