summaryrefslogtreecommitdiff
path: root/stack/src/interface.c
blob: 5f53ab1a69d2963abd0f9719b7e863f7329e486d (plain)
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
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
#include <sk_stack.h>
#include <sk_ucb.h>
#include <mr_common.h>
#include <unistd.h>
#include <mr_buffer.h>
#include "sk_udp.h"

static struct sk_app_instance * sk_default_app_instance;
static struct sk_instance * sk_default_instance;

void sk_default_instance_set(struct sk_instance * instance, 
	struct sk_app_instance * app_instance)
{
	sk_default_instance = instance;
	sk_default_app_instance = app_instance;
}

int marsio_socket(int family, int type, int protocol)
{
	if (unlikely(family != AF_INET && family != AF_INET6))
		return -EINVAL;
	if (unlikely(type != SOCK_DGRAM))
		return -EINVAL;

	assert(sk_default_app_instance != NULL);
	struct sk_ucb * ucb = sk_ucb_create(sk_default_app_instance);
	if (unlikely(ucb == NULL)) return -1;
	return sk_ucb_get_index(ucb);
}

int marsio_connect(int fd, const struct sockaddr * addr, socklen_t addrlen)
{
	if (addr->sa_family != AF_INET) return -EINVAL;
	struct sockaddr_in * sockaddr_in = (struct sockaddr_in *)addr;
	
	assert(sk_default_app_instance != NULL);
	struct sk_ucb * ucb = sk_ucb_lookup_by_index(sk_default_app_instance, fd);
	if (unlikely(ucb == NULL)) return -EINVAL;
	
	return sk_ucb_connect(ucb, sockaddr_in);
}

int marsio_bind(int fd, const struct sockaddr * addr, socklen_t addrlen)
{
	if (addr->sa_family != AF_INET) return -EINVAL;
	struct sockaddr_in * sockaddr_in = (struct sockaddr_in *)addr;

	assert(sk_default_app_instance != NULL);
	struct sk_ucb * ucb = sk_ucb_lookup_by_index(sk_default_app_instance, fd);
	if (unlikely(ucb == NULL)) return -EINVAL;
	return sk_ucb_bind(ucb, sockaddr_in);
}

#define SK_UDP_MAGIC_CHECK		0

#ifdef __GNUC__
#define container_of(ptr, type, member) ({                      \
		const typeof(((type *)0)->member) *__mptr = (ptr);		\
		(type *)((char *)__mptr - offsetof(type,member));})
#else
#define container_of(ptr, type,member) \
		((type *)((char *)(ptr) - offsetof(type, member)))
#endif

/* UDP���Ļ�������ͬһ�����ϵĻ�������ʾͬһ��UDP���� */
struct marsio_udp_buff
{
	/* ��������ʼ��ַ */
	void * start;
	/* ���������� */
	unsigned int len;
	/* ��һ�黺������ַ */
	struct marsio_udp_buff * next;
	/* ��һ������ʼ��ַ */
	struct marsio_udp_buff * next_pkt;
};

struct internal_udp_buff
{
#if SK_UDP_MAGIC_CHECK
	char magic_0[2];
#endif
	struct rte_mbuf * mbuf;
#if SK_UDP_MAGIC_CHECK
	char magic_1[2];
#endif
	struct marsio_udp_buff buff;
};


/* ���º���Ϊ����MARSIO-3�汾��ʵ�֣��¹���Ӧ��ʹ�����º��� */
/* BUFF�ṹ����ת������ */
static inline struct marsio_udp_buff * __buff_from_internal_buff(struct internal_udp_buff * in_buff)
{
	return &(in_buff->buff);
}

static inline struct internal_udp_buff * __internal_buff_from_buff(struct marsio_udp_buff * buff)
{
	return container_of(buff, struct internal_udp_buff, buff);
}

static inline struct rte_mbuf * __mbuf_from_buff(struct marsio_udp_buff * buff)
{
	return __internal_buff_from_buff(buff)->mbuf;
}

struct marsio_udp_buff * marsio_udp_alloc()
{
	struct rte_mbuf * mbuf = rte_pktmbuf_alloc(sk_default_app_instance->def_direct_pktmbuf_pool);
	if (unlikely(mbuf == NULL)) return NULL;

	uint8_t ctrlzone_id = sk_default_app_instance->instance->ctrlzone_id_soqinfo;
	struct internal_udp_buff * in_buff = (struct internal_udp_buff *)mr_buffer_ctrlzone(mbuf, ctrlzone_id);
	assert(in_buff != NULL);

	in_buff->mbuf = mbuf;
	in_buff->buff.start = rte_pktmbuf_mtod(mbuf, void *);
	in_buff->buff.len = mbuf->buf_len - mbuf->data_off;
	in_buff->buff.next = NULL;
	in_buff->buff.next_pkt = NULL;
	return __buff_from_internal_buff(in_buff);
}

void marsio_udp_free(struct marsio_udp_buff * udp_buff)
{
	struct rte_mbuf * mbuf = __mbuf_from_buff(udp_buff);
	rte_pktmbuf_free(mbuf);
	return;
}

/* ����UDP Buff�ṹ�������ӵ�MBUF�ṹ*/
static inline struct rte_mbuf * update_rte_mbuf(struct marsio_udp_buff * buff_head)
{
	struct marsio_udp_buff * now_buff_head = buff_head;
	struct rte_mbuf * mbuf_chain_head = __mbuf_from_buff(buff_head);

	// ��һ������ʼ��
	mbuf_chain_head->pkt_len = buff_head->len;
	mbuf_chain_head->data_len = buff_head->len;
	mbuf_chain_head->nb_segs = 1;

	// ����BUFF�ṹ����MBUF����
	while (now_buff_head != NULL)
	{

#if SK_UDP_MAGIC_CHECK
		struct internal_udp_buff * __check_in_buff = __internal_buff_from_buff(now_buff_head);
		__magic_check(__check_in_buff);
#endif

		struct rte_mbuf * mbuf_now = __mbuf_from_buff(now_buff_head);
		if (mbuf_now != mbuf_chain_head) rte_pktmbuf_chain(mbuf_chain_head, mbuf_now);
		now_buff_head = now_buff_head->next;
	}

	return mbuf_chain_head;
}

static ssize_t __udp_sendto_burst(int marsio_fd, struct marsio_udp_buff * buff[], 
	unsigned int nr_buff, int flags, struct sockaddr * to, socklen_t addrlen)
{
	// ���ҵ�ǰ��FD��Ӧ��UCB
	struct sk_ucb * ucb = sk_ucb_lookup_by_index(sk_default_app_instance, marsio_fd);
	if (unlikely(ucb == NULL)) return -EINVAL;

	// ��ַת����MBUFת��
	struct sockaddr_in * sockaddr_in = (struct sockaddr_in *)to;
	if (unlikely(sockaddr_in->sin_family != AF_INET)) return -EINVAL;

	struct rte_mbuf * mbufs[MR_BURST_MAX];
	for(int i = 0; i < nr_buff; i++)
	{
		mbufs[i] = update_rte_mbuf(buff[i]);
	}

	// ��ѯĿ��Destinfo
	struct sk_destinfo * destinfo = sk_ucb_destinfo_get(ucb);
	if (destinfo != NULL) goto send;

	destinfo = sk_destinfo_create_by_route(sk_default_app_instance, sockaddr_in->sin_addr);
	if (unlikely(destinfo == NULL)) goto errout;
	
send:
	return sk_udp_send_burst(sk_default_app_instance, flags, destinfo, mbufs,
		nr_buff, 0);
	
errout:


	return 0;
}

ssize_t marsio_udp_sendto_chain(int marsio_fd, struct marsio_udp_buff * chain_head, int nb_buff,
	int flags, struct sockaddr * to[], socklen_t addrlen[], int nb_sockaddrs)
{
	int nb_chain_pkts = 0;
	struct marsio_udp_buff * buff_array[MR_BURST_MAX];

	if (unlikely(nb_buff > RTE_DIM(buff_array))) return -ENOBUFS;
	for (struct marsio_udp_buff * __head = chain_head; __head != NULL; __head = __head->next_pkt)
	{
		buff_array[nb_chain_pkts++] = __head;
	}

	// ��֧�ִ���1��Ŀ���ַ
	if (nb_sockaddrs > 1) return -EINVAL;
	return __udp_sendto_burst(marsio_fd, buff_array, nb_chain_pkts, flags, to[0], addrlen[0]);
}