source: asp3_gr_sakura/trunk/tinet/net/ethernet.c@ 318

Last change on this file since 318 was 318, checked in by coas-nagasima, 7 years ago

プロパティの文字コードにUTF-8を追加、キーワードを削除

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-csrc; charset=UTF-8
File size: 12.5 KB
Line 
1/*
2 * TINET (TCP/IP Protocol Stack)
3 *
4 * Copyright (C) 2001-2017 by Dep. of Computer Science and Engineering
5 * Tomakomai National College of Technology, JAPAN
6 *
7 * 上記著作権者は,以下の (1)~(4) の条件か,Free Software Foundation
8 * によって公表されている GNU General Public License の Version 2 に記
9 * 述されている条件を満たす場合に限り,本ソフトウェア(本ソフトウェア
10 * を改変したものを含む.以下同じ)を使用・複製・改変・再配布(以下,
11 * 利用と呼ぶ)することを無償で許諾する.
12 * (1) 本ソフトウェアをソースコードの形で利用する場合には,上記の著作
13 * 権表示,この利用条件および下記の無保証規定が,そのままの形でソー
14 * スコード中に含まれていること.
15 * (2) 本ソフトウェアを,ライブラリ形式など,他のソフトウェア開発に使
16 * 用できる形で再配布する場合には,再配布に伴うドキュメント(利用
17 * 者マニュアルなど)に,上記の著作権表示,この利用条件および下記
18 * の無保証規定を掲載すること.
19 * (3) 本ソフトウェアを,機器に組み込むなど,他のソフトウェア開発に使
20 * 用できない形で再配布する場合には,次の条件を満たすこと.
21 * (a) 再配布に伴うドキュメント(利用者マニュアルなど)に,上記の著
22 * 作権表示,この利用条件および下記の無保証規定を掲載すること.
23 * (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
24 * 害からも,上記著作権者およびTOPPERSプロジェクトを免責すること.
25 *
26 * 本ソフトウェアは,無保証で提供されているものである.上記著作権者お
27 * よびTOPPERSプロジェクトは,本ソフトウェアに関して,その適用可能性も
28 * 含めて,いかなる保証も行わない.また,本ソフトウェアの利用により直
29 * 接的または間接的に生じたいかなる損害に関しても,その責任を負わない.
30 *
31 * @(#) $Id$
32 */
33
34/*
35 * Ethernet 処理タスクの本体
36 */
37
38#include <string.h>
39
40#ifdef TARGET_KERNEL_ASP
41
42#include <kernel.h>
43#include <sil.h>
44#include <t_syslog.h>
45#include "kernel_cfg.h"
46
47#endif /* of #ifdef TARGET_KERNEL_ASP */
48
49#ifdef TARGET_KERNEL_JSP
50
51#include <s_services.h>
52#include <t_services.h>
53#include "kernel_id.h"
54
55#endif /* of #ifdef TARGET_KERNEL_JSP */
56
57#include <tinet_defs.h>
58#include <tinet_config.h>
59
60#include <net/if.h>
61#include <net/ethernet.h>
62#include <net/if_llc.h>
63#include <net/if_arp.h>
64#include <net/net.h>
65#include <net/net_endian.h>
66#include <net/net_var.h>
67#include <net/net_buf.h>
68#include <net/net_timer.h>
69#include <net/net_count.h>
70
71#include <netinet/in.h>
72#include <netinet/in_var.h>
73#include <netinet/if_ether.h>
74
75#include <netinet6/if6_ether.h>
76#include <netinet6/nd6.h>
77
78#include <net/if_var.h>
79
80#ifdef SUPPORT_ETHER
81
82/*
83 * 変数
84 */
85
86#if defined(_IP4_CFG)
87
88const uint8_t ether_broad_cast_addr[ETHER_ADDR_LEN] = {
89 UINT_C(0xff), UINT_C(0xff), UINT_C(0xff),
90 UINT_C(0xff), UINT_C(0xff), UINT_C(0xff)
91 };
92
93#endif /* of #if defined(_IP4_CFG) */
94
95/*
96 * 変数
97 */
98
99/* ネットワークインタフェース構造体 */
100
101static T_IFNET ether_ifnet;
102
103#ifdef SUPPORT_MIB
104
105/* SNMP の 管理情報ベース (MIB) */
106
107T_IF_STATS if_stats;
108
109#endif /* of #ifdef SUPPORT_MIB */
110
111#ifdef ETHER_CFG_802_WARNING
112
113/*
114 * 関数
115 */
116
117static void ieee_802_input (T_NET_BUF *input);
118
119/*
120 * ieee_802_input -- IEEE 802.3 入力処理
121 */
122
123static void
124ieee_802_input (T_NET_BUF *input)
125{
126 T_8023MAC_HDR *mhdr;
127 T_8022SNAP_HDR *shdr;
128
129 mhdr = GET_8023MAC_HDR(input);
130 shdr = GET_8022SNAP_HDR(input);
131 syslog(LOG_WARNING, "[ETHER] unexp 802.3 from: %s, proto: 0x%04x.",
132 mac2str(NULL, mhdr->shost), ntohs(*(uint16_t*)&shdr->type));
133 }
134
135#endif /* of #ifdef ETHER_CFG_802_WARNING */
136
137/*
138 * ether_srand -- 乱数を初期値を返す。
139 */
140
141uint32_t
142ether_srand (void)
143{
144 T_IF_SOFTC *ic;
145 uint32_t rval;
146
147 ic = IF_ETHER_NIC_GET_SOFTC();
148 rval = (ic->ifaddr.lladdr[2] << 24)
149 + (ic->ifaddr.lladdr[3] << 16)
150 + (ic->ifaddr.lladdr[4] << 8)
151 + (ic->ifaddr.lladdr[5] );
152
153#ifdef ETHER_CFG_COLLECT_ADDR
154
155 rval += (ether_collect_addr.lladdr[2] << 24)
156 + (ether_collect_addr.lladdr[3] << 16)
157 + (ether_collect_addr.lladdr[4] << 8)
158 + (ether_collect_addr.lladdr[5] );
159
160#endif /* of #ifdef ETHER_CFG_COLLECT_ADDR */
161
162 return rval;
163 }
164
165/*
166 * ether_get_ifnet -- ネットワークインタフェース構造体を返す。
167 */
168
169T_IFNET *
170ether_get_ifnet (void)
171{
172 return &ether_ifnet;
173 }
174
175#if defined(_IP6_CFG)
176
177/*
178 * ether_in6_resolve_multicast -- イーサネットのマルチキャストアドレスへの変換
179 */
180
181ER
182ether_in6_resolve_multicast (T_ETHER_ADDR *ifaddr, const T_IN6_ADDR *maddr)
183{
184 /* マルチキャストアドレスかチェックする。*/
185 if (!IN6_IS_ADDR_MULTICAST(maddr))
186 return E_PAR;
187
188 /* イーサネットのマルチキャストアドレスへの変換 */
189 ether_map_ipv6_multicast(ifaddr, maddr);
190
191 return E_OK;
192 }
193
194#endif /* of #if defined(_IP6_CFG) */
195
196/*
197 * ether_raw_output -- Ethernet インタフェースの出力関数、MAC アドレス解決無し
198 */
199
200ER
201ether_raw_output (T_NET_BUF *output, TMO tmout)
202{
203 ER error = E_OK;
204
205 /* Ethernet 出力キューに投入する。*/
206 if ((error = tsnd_dtq(DTQ_ETHER_OUTPUT, (intptr_t)output, tmout)) != E_OK) {
207 NET_COUNT_ETHER(net_count_ether.out_err_packets, 1);
208 NET_COUNT_MIB(if_stats.ifOutDiscards, 1);
209
210 /* IF でネットワークバッファを開放しないフラグをチェックする。*/
211 if ((output->flags & NB_FLG_NOREL_IFOUT) == 0) {
212 syscall(rel_net_buf(output));
213 }
214 else {
215 output->flags &= (uint8_t)~NB_FLG_NOREL_IFOUT;
216 }
217 IF_ETHER_NIC_RESET(IF_ETHER_NIC_GET_SOFTC());
218 }
219 return error;
220 }
221
222/*
223 * ether_output -- Ethernet インタフェースの出力関数、MAC アドレス解決有り
224 */
225
226ER
227ether_output (T_NET_BUF *output, const void *dst, T_IF_ADDR *gw, TMO tmout)
228{
229 T_IF_SOFTC *ic;
230 ER error = E_OK;
231
232 /* 送信元 MAC アドレスを設定する。*/
233 ic = IF_ETHER_NIC_GET_SOFTC();
234 memcpy(GET_ETHER_HDR(output)->shost, ic->ifaddr.lladdr, ETHER_ADDR_LEN);
235
236 switch(ntohs(GET_ETHER_HDR(output)->type)) {
237
238#if defined(_IP4_CFG)
239
240 case ETHER_TYPE_IP: /* IPv4 */
241 if (arp_resolve(&ic->ifaddr, output, *(uint32_t*)dst)) { /* true ならアドレス解決済 */
242 error = ether_raw_output(output, tmout);
243 }
244 break;
245
246#endif /* of #if defined(_IP4_CFG) */
247
248#if defined(_IP6_CFG)
249
250 case ETHER_TYPE_IPV6: /* IPv6 */
251 error = nd6_storelladdr((T_ETHER_ADDR*)GET_ETHER_HDR(output)->dhost,
252 (const T_IN6_ADDR*)dst, gw);
253 if (error == E_OK)
254 error = ether_raw_output(output, tmout);
255
256 /* IF でネットワークバッファを開放しないフラグをチェックする。*/
257 else if ((output->flags & NB_FLG_NOREL_IFOUT) == 0) {
258 syscall(rel_net_buf(output));
259 }
260 else {
261 output->flags &= (uint8_t)~NB_FLG_NOREL_IFOUT;
262 }
263 break;
264
265#endif /* of #if defined(_IP6_CFG) */
266
267 default:
268 NET_COUNT_MIB(if_stats.ifOutErrors, 1);
269
270 /* IF でネットワークバッファを開放しないフラグをチェックする。*/
271 if ((output->flags & NB_FLG_NOREL_IFOUT) == 0) {
272 syscall(rel_net_buf(output));
273 }
274 else {
275 output->flags &= (uint8_t)~NB_FLG_NOREL_IFOUT;
276 }
277 error = E_PAR;
278 break;
279 }
280
281 if (error != E_OK)
282 NET_COUNT_ETHER(net_count_ether.out_err_packets, 1);
283 return error;
284 }
285
286/*
287 * Ethernet 出力タスク
288 */
289
290void
291ether_output_task(intptr_t exinf)
292{
293 T_IF_SOFTC *ic;
294 T_NET_BUF *output;
295 ID tskid;
296
297 get_tid(&tskid);
298 syslog(LOG_NOTICE, "[ETHER OUTPUT:%d] started.", tskid);
299
300 ic = IF_ETHER_NIC_GET_SOFTC();
301
302 while (true) {
303 while (rcv_dtq(DTQ_ETHER_OUTPUT, (intptr_t*)&output) == E_OK) {
304 NET_COUNT_ETHER(net_count_ether.out_octets, output->len);
305 NET_COUNT_MIB(if_stats.ifOutOctets, output->len + 8);
306 NET_COUNT_ETHER(net_count_ether.out_packets, 1);
307
308#ifdef SUPPORT_MIB
309 if ((*(GET_ETHER_HDR(output)->dhost) & ETHER_MCAST_ADDR) == 0) {
310 NET_COUNT_MIB(if_stats.ifOutUcastPkts, 1);
311 }
312 else {
313 NET_COUNT_MIB(if_stats.ifOutNUcastPkts, 1);
314 }
315#endif /* of #ifdef SUPPORT_MIB */
316
317 syscall(wai_sem(ic->semid_txb_ready));
318
319 IF_ETHER_NIC_START(ic, output);
320
321#ifndef ETHER_NIC_CFG_RELEASE_NET_BUF
322
323 if ((output->flags & NB_FLG_NOREL_IFOUT) == 0) {
324 syscall(rel_net_buf(output));
325 }
326 else {
327 output->flags &= (uint8_t)~NB_FLG_NOREL_IFOUT;
328
329#ifdef SUPPORT_TCP
330 sig_sem(SEM_TCP_POST_OUTPUT);
331#endif /* of #ifdef SUPPORT_TCP */
332 }
333
334#endif /* of #ifndef ETHER_NIC_CFG_RELEASE_NET_BUF */
335
336 }
337 }
338 }
339
340/*
341 * Ethernet 入力タスク
342 */
343
344void
345ether_input_task(intptr_t exinf)
346{
347 T_IF_SOFTC *ic;
348 T_NET_BUF *input;
349 T_ETHER_HDR *eth;
350 ID tskid;
351 uint16_t proto;
352 uint8_t rcount = 0;
353
354 /* ネットワークインタフェース管理を初期化する。*/
355 ifinit();
356
357 /* イーサネットネットワークインタフェース管理を初期化する。*/
358
359#if defined(_IP4_CFG)
360
361 ether_ifnet.in4_ifaddr.addr = IPV4_ADDR_LOCAL; /* IPv4 アドレス */
362 ether_ifnet.in4_ifaddr.mask = IPV4_ADDR_LOCAL_MASK; /* サブネットマスク */
363
364#endif /* of #if defined(_IP4_CFG) */
365
366 /* NIC を初期化する。*/
367 ic = IF_ETHER_NIC_GET_SOFTC();
368 IF_ETHER_NIC_PROBE(ic);
369 IF_ETHER_NIC_INIT(ic);
370
371 /* Ethernet 出力タスクを起動する */
372 syscall(act_tsk(ETHER_OUTPUT_TASK));
373
374 /* ネットワークタイマタスクを起動する */
375 syscall(act_tsk(NET_TIMER_TASK));
376
377 get_tid(&tskid);
378
379 syslog(LOG_NOTICE, "[ETHER INPUT:%2d] started on MAC Addr: %s.",
380 tskid, mac2str(NULL, ic->ifaddr.lladdr));
381
382#if defined(_IP4_CFG)
383
384 /* ARP を初期化する。*/
385 arp_init();
386
387#endif /* of #if defined(_IP4_CFG) */
388
389 ether_ifnet.ic = ic;
390
391 /* 乱数生成を初期化する。*/
392 net_srand(0);
393
394 while (true) {
395 syscall(wai_sem(ic->semid_rxb_ready));
396 if ((input = IF_ETHER_NIC_READ(ic)) != NULL) {
397 NET_COUNT_ETHER(net_count_ether.in_octets, input->len);
398 NET_COUNT_MIB(if_stats.ifInOctets, input->len + 8);
399 NET_COUNT_ETHER(net_count_ether.in_packets, 1);
400 eth = GET_ETHER_HDR(input);
401 proto = ntohs(eth->type);
402
403 /* 乱数生成を初期化する。*/
404 if (rcount == 0) {
405
406#ifdef ETHER_CFG_COLLECT_ADDR
407 memcpy(ether_collect_addr.lladdr, eth->shost,
408 sizeof(ether_collect_addr.lladdr));
409#endif /* of #ifdef ETHER_CFG_COLLECT_ADDR */
410
411 net_srand(0);
412 }
413 rcount ++;
414
415
416#ifdef SUPPORT_MIB
417 if ((*eth->dhost & ETHER_MCAST_ADDR) == 0) {
418 NET_COUNT_MIB(if_stats.ifInUcastPkts, 1);
419 }
420 else {
421 NET_COUNT_MIB(if_stats.ifInNUcastPkts, 1);
422 }
423#endif /* of #ifdef SUPPORT_MIB */
424
425#if defined(_IP4_CFG) && defined(ETHER_CFG_ACCEPT_ALL)
426
427 if ((*eth->dhost & ETHER_MCAST_ADDR) && *eth->dhost != 0xff) {
428
429#ifdef ETHER_CFG_MCAST_WARNING
430
431 if (proto <= 1500)
432 proto = ntohs(*(uint16_t*)&(GET_8022SNAP_HDR(input)->type));
433 syslog(LOG_WARNING, "[ETHER] mcast addr from: %s, to: %s, proto: 0x%04x.",
434 mac2str(NULL, eth->shost), mac2str(NULL, eth->dhost), proto);
435
436#endif /* of #ifdef ETHER_CFG_MCAST_WARNING */
437
438 NET_COUNT_ETHER(net_count_ether.in_err_packets, 1);
439 NET_COUNT_MIB(if_stats.ifInErrors, 1);
440 syscall(rel_net_buf(input));
441 continue;
442 }
443
444#endif /* of #if defined(_IP4_CFG) && defined(ETHER_CFG_ACCEPT_ALL) */
445
446 switch(proto) {
447
448#if defined(_IP4_CFG)
449
450 case ETHER_TYPE_IP: /* IP */
451 ip_input(input);
452 break;
453
454 case ETHER_TYPE_ARP: /* ARP */
455 arp_input(&ic->ifaddr, input);
456 break;
457
458#endif /* of #if defined(_IP4_CFG) */
459
460#if defined(_IP6_CFG)
461
462 case ETHER_TYPE_IPV6: /* IPv6 */
463 ip6_input(input);
464 break;
465
466#endif /* of #if defined(_IP6_CFG) */
467
468 default:
469
470#ifdef ETHER_CFG_UNEXP_WARNING
471
472#ifdef ETHER_CFG_802_WARNING
473
474 if (proto <= 1500)
475 ieee_802_input(input);
476 else
477 syslog(LOG_NOTICE, "[ETHER] unexp proto from: %s, proto: 0x%04x.",
478 mac2str(NULL, GET_ETHER_HDR(input)->shost), proto);
479
480#else /* of #ifdef ETHER_CFG_802_WARNING */
481
482 syslog(LOG_INFO, "[ETHER] unexp proto from: %s, proto: 0x%04x.",
483 mac2str(NULL, GET_ETHER_HDR(input)->shost), proto);
484
485#endif /* of #ifdef ETHER_CFG_802_WARNING */
486
487#endif /* of #ifdef ETHER_CFG_UNEXP_WARNING */
488
489 NET_COUNT_ETHER(net_count_ether.in_err_packets, 1);
490 NET_COUNT_MIB(if_stats.ifUnknownProtos, 1);
491 syscall(rel_net_buf(input));
492 break;
493 }
494 }
495 }
496 }
497
498#endif /* of #ifdef SUPPORT_ETHER */
Note: See TracBrowser for help on using the repository browser.