source: asp3_tinet_ecnl_rx/trunk/asp3_dcre/tinet/net/ethernet.c@ 342

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

syscallが関数呼びになるよう変更
他更新

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-csrc;charset=UTF-8
File size: 14.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: ethernet.c 1524 2018-04-25 13:48:23Z coas-nagasima $
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_set_link_up -- リンクしたときにNICから呼び出される
198 */
199void
200ether_set_link_up()
201{
202 if (!(ether_ifnet.flags & IF_FLAG_LINK_UP)) {
203 ether_ifnet.flags |= IF_FLAG_LINK_UP;
204
205 if (ether_ifnet.flags & IF_FLAG_UP) {
206#if defined(_IP4_CFG) && defined(SUPPORT_ETHER)
207 /* ARP再構築? */
208#endif /* #if defined(_IP4_CFG) && defined(SUPPORT_ETHER) */
209
210#ifdef SUPPORT_IGMP
211 /* IGMP参加 */
212#endif /* #ifdef SUPPORT_IGMP */
213 }
214 if (ether_ifnet.link_callback) {
215 (ether_ifnet.link_callback)(&ether_ifnet);
216 }
217 }
218 }
219
220/**
221 * ether_set_link_up -- リンクが切断したときにNICから呼び出される
222 */
223void
224ether_set_link_down()
225{
226 if (ether_ifnet.flags & IF_FLAG_LINK_UP) {
227 ether_ifnet.flags &= ~IF_FLAG_LINK_UP;
228 if (ether_ifnet.link_callback) {
229 (ether_ifnet.link_callback)(&ether_ifnet);
230 }
231 }
232 }
233
234/*
235 * ether_set_up -- DHCPでアドレスが設定されたとき呼び出される
236 */
237
238void
239ether_set_up()
240{
241 if (!(ether_ifnet.flags & IF_FLAG_UP)) {
242 ether_ifnet.flags |= IF_FLAG_UP;
243 if (ether_ifnet.link_callback) {
244 (ether_ifnet.link_callback)(&ether_ifnet);
245 }
246 }
247 }
248
249/*
250 * ether_set_down -- DHCPでアドレスが解放されたとき呼び出される
251 */
252
253void
254ether_set_down()
255{
256 if (ether_ifnet.flags & IF_FLAG_UP) {
257 ether_ifnet.flags &= ~IF_FLAG_UP;
258 if (ether_ifnet.link_callback) {
259 (ether_ifnet.link_callback)(&ether_ifnet);
260 }
261 }
262 }
263
264/*
265 * ether_set_link_callback -- リンク状態変化時のコールバック登録
266 */
267
268void
269ether_set_link_callback(ether_status_callback_fn link_callback)
270{
271 ether_ifnet.link_callback = link_callback;
272 if (ether_ifnet.link_callback) {
273 (ether_ifnet.link_callback)(&ether_ifnet);
274 }
275 }
276
277/*
278 * ether_raw_output -- Ethernet インタフェースの出力関数、MAC アドレス解決無し
279 */
280
281ER
282ether_raw_output (T_NET_BUF *output, TMO tmout)
283{
284 ER error = E_OK;
285
286 /* Ethernet 出力キューに投入する。*/
287 if ((error = tsnd_dtq(DTQ_ETHER_OUTPUT, (intptr_t)output, tmout)) != E_OK) {
288 NET_COUNT_ETHER(net_count_ether.out_err_packets, 1);
289 NET_COUNT_MIB(if_stats.ifOutDiscards, 1);
290
291 /* IF でネットワークバッファを開放しないフラグをチェックする。*/
292 if ((output->flags & NB_FLG_NOREL_IFOUT) == 0) {
293 syscall(rel_net_buf(output));
294 }
295 else {
296 output->flags &= (uint8_t)~NB_FLG_NOREL_IFOUT;
297 }
298 IF_ETHER_NIC_RESET(IF_ETHER_NIC_GET_SOFTC());
299 }
300 return error;
301 }
302
303/*
304 * ether_output -- Ethernet インタフェースの出力関数、MAC アドレス解決有り
305 */
306
307ER
308ether_output (T_NET_BUF *output, const void *dst, T_IF_ADDR *gw, TMO tmout)
309{
310 T_IF_SOFTC *ic;
311 ER error = E_OK;
312 T_ETHER_HDR *eth;
313
314 /* 送信元 MAC アドレスを設定する。*/
315 ic = IF_ETHER_NIC_GET_SOFTC();
316 eth = GET_ETHER_HDR(output);
317 memcpy(eth->shost, ic->ifaddr.lladdr, ETHER_ADDR_LEN);
318
319 switch(ntohs(eth->type)) {
320
321#if defined(_IP4_CFG)
322
323 case ETHER_TYPE_IP: /* IPv4 */
324#ifdef ETHER_CFG_MULTICAST
325 /* マルチキャストアドレスの場合 */
326 if(IN4_IS_ADDR_MULTICAST(*(uint32_t*)dst)){
327 /* イーサネットのマルチキャストアドレスへの変換 */
328 ether_map_ipv4_multicast((T_ETHER_ADDR *)&eth->dhost, *(T_IN4_ADDR*)dst);
329 error = ether_raw_output(output, tmout);
330 break;
331 }
332#endif
333 if (arp_resolve(&ic->ifaddr, output, *(uint32_t*)dst)) { /* true ならアドレス解決済 */
334 error = ether_raw_output(output, tmout);
335 }
336 break;
337
338#endif /* of #if defined(_IP4_CFG) */
339
340#if defined(_IP6_CFG)
341
342 case ETHER_TYPE_IPV6: /* IPv6 */
343 error = nd6_storelladdr((T_ETHER_ADDR*)eth->dhost,
344 (const T_IN6_ADDR*)dst, gw);
345 if (error == E_OK)
346 error = ether_raw_output(output, tmout);
347
348 /* IF でネットワークバッファを開放しないフラグをチェックする。*/
349 else if ((output->flags & NB_FLG_NOREL_IFOUT) == 0) {
350 syscall(rel_net_buf(output));
351 }
352 else {
353 output->flags &= (uint8_t)~NB_FLG_NOREL_IFOUT;
354 }
355 break;
356
357#endif /* of #if defined(_IP6_CFG) */
358
359 default:
360 NET_COUNT_MIB(if_stats.ifOutErrors, 1);
361
362 /* IF でネットワークバッファを開放しないフラグをチェックする。*/
363 if ((output->flags & NB_FLG_NOREL_IFOUT) == 0) {
364 syscall(rel_net_buf(output));
365 }
366 else {
367 output->flags &= (uint8_t)~NB_FLG_NOREL_IFOUT;
368 }
369 error = E_PAR;
370 break;
371 }
372
373 if (error != E_OK)
374 NET_COUNT_ETHER(net_count_ether.out_err_packets, 1);
375 return error;
376 }
377
378/*
379 * Ethernet 出力タスク
380 */
381
382void
383ether_output_task(intptr_t exinf)
384{
385 T_IF_SOFTC *ic;
386 T_NET_BUF *output;
387 ID tskid;
388
389 get_tid(&tskid);
390 syslog(LOG_NOTICE, "[ETHER OUTPUT:%d] started.", tskid);
391
392 ic = IF_ETHER_NIC_GET_SOFTC();
393
394 while (true) {
395 while (rcv_dtq(DTQ_ETHER_OUTPUT, (intptr_t*)&output) == E_OK) {
396 NET_COUNT_ETHER(net_count_ether.out_octets, output->len);
397 NET_COUNT_MIB(if_stats.ifOutOctets, output->len + 8);
398 NET_COUNT_ETHER(net_count_ether.out_packets, 1);
399
400#ifdef SUPPORT_MIB
401 if ((*(GET_ETHER_HDR(output)->dhost) & ETHER_MCAST_ADDR) == 0) {
402 NET_COUNT_MIB(if_stats.ifOutUcastPkts, 1);
403 }
404 else {
405 NET_COUNT_MIB(if_stats.ifOutNUcastPkts, 1);
406 }
407#endif /* of #ifdef SUPPORT_MIB */
408
409 syscall(wai_sem(ic->semid_txb_ready));
410
411 IF_ETHER_NIC_START(ic, output);
412
413#ifndef ETHER_NIC_CFG_RELEASE_NET_BUF
414
415 if ((output->flags & NB_FLG_NOREL_IFOUT) == 0) {
416 syscall(rel_net_buf(output));
417 }
418 else {
419 output->flags &= (uint8_t)~NB_FLG_NOREL_IFOUT;
420
421#ifdef SUPPORT_TCP
422 sig_sem(SEM_TCP_POST_OUTPUT);
423#endif /* of #ifdef SUPPORT_TCP */
424 }
425
426#endif /* of #ifndef ETHER_NIC_CFG_RELEASE_NET_BUF */
427
428 }
429 }
430 }
431
432/*
433 * Ethernet 入力タスク
434 */
435
436void
437ether_input_task(intptr_t exinf)
438{
439 T_IF_SOFTC *ic;
440 T_NET_BUF *input;
441 T_ETHER_HDR *eth;
442 ID tskid;
443 uint16_t proto;
444 uint8_t rcount = 0;
445
446 /* ネットワークインタフェース管理を初期化する。*/
447 ifinit();
448
449 /* イーサネットネットワークインタフェース管理を初期化する。*/
450
451#if defined(_IP4_CFG)
452
453 ether_ifnet.in4_ifaddr.addr = IPV4_ADDR_LOCAL; /* IPv4 アドレス */
454 ether_ifnet.in4_ifaddr.mask = IPV4_ADDR_LOCAL_MASK; /* サブネットマスク */
455
456#endif /* of #if defined(_IP4_CFG) */
457
458 /* NIC を初期化する。*/
459 ic = IF_ETHER_NIC_GET_SOFTC();
460 IF_ETHER_NIC_PROBE(ic);
461 IF_ETHER_NIC_INIT(ic);
462
463 /* Ethernet 出力タスクを起動する */
464 syscall(act_tsk(ETHER_OUTPUT_TASK));
465
466 /* ネットワークタイマタスクを起動する */
467 syscall(act_tsk(NET_TIMER_TASK));
468
469 get_tid(&tskid);
470
471 syslog(LOG_NOTICE, "[ETHER INPUT:%2d] started on MAC Addr: %s.",
472 tskid, mac2str(NULL, ic->ifaddr.lladdr));
473
474#if defined(_IP4_CFG)
475
476 /* ARP を初期化する。*/
477 arp_init();
478
479#endif /* of #if defined(_IP4_CFG) */
480
481 ether_ifnet.ic = ic;
482
483 /* 乱数生成を初期化する。*/
484 net_srand(0);
485
486 while (true) {
487 syscall(wai_sem(ic->semid_rxb_ready));
488 if ((input = IF_ETHER_NIC_READ(ic)) != NULL) {
489 NET_COUNT_ETHER(net_count_ether.in_octets, input->len);
490 NET_COUNT_MIB(if_stats.ifInOctets, input->len + 8);
491 NET_COUNT_ETHER(net_count_ether.in_packets, 1);
492 eth = GET_ETHER_HDR(input);
493 proto = ntohs(eth->type);
494
495 /* 乱数生成を初期化する。*/
496 if (rcount == 0) {
497
498#ifdef ETHER_CFG_COLLECT_ADDR
499 memcpy(ether_collect_addr.lladdr, eth->shost,
500 sizeof(ether_collect_addr.lladdr));
501#endif /* of #ifdef ETHER_CFG_COLLECT_ADDR */
502
503 net_srand(0);
504 }
505 rcount ++;
506
507
508#ifdef SUPPORT_MIB
509 if ((*eth->dhost & ETHER_MCAST_ADDR) == 0) {
510 NET_COUNT_MIB(if_stats.ifInUcastPkts, 1);
511 }
512 else {
513 NET_COUNT_MIB(if_stats.ifInNUcastPkts, 1);
514 }
515#endif /* of #ifdef SUPPORT_MIB */
516
517#if defined(_IP4_CFG) && defined(ETHER_CFG_ACCEPT_ALL)
518
519 if ((*eth->dhost & ETHER_MCAST_ADDR) && *eth->dhost != 0xff) {
520
521#ifdef ETHER_CFG_MCAST_WARNING
522
523 if (proto <= 1500)
524 proto = ntohs(*(uint16_t*)&(GET_8022SNAP_HDR(input)->type));
525 syslog(LOG_WARNING, "[ETHER] mcast addr from: %s, to: %s, proto: 0x%04x.",
526 mac2str(NULL, eth->shost), mac2str(NULL, eth->dhost), proto);
527
528#endif /* of #ifdef ETHER_CFG_MCAST_WARNING */
529
530 NET_COUNT_ETHER(net_count_ether.in_err_packets, 1);
531 NET_COUNT_MIB(if_stats.ifInErrors, 1);
532 syscall(rel_net_buf(input));
533 continue;
534 }
535
536#endif /* of #if defined(_IP4_CFG) && defined(ETHER_CFG_ACCEPT_ALL) */
537
538 switch(proto) {
539
540#if defined(_IP4_CFG)
541
542 case ETHER_TYPE_IP: /* IP */
543 ip_input(input);
544 break;
545
546 case ETHER_TYPE_ARP: /* ARP */
547 arp_input(&ic->ifaddr, input);
548 break;
549
550#endif /* of #if defined(_IP4_CFG) */
551
552#if defined(_IP6_CFG)
553
554 case ETHER_TYPE_IPV6: /* IPv6 */
555 ip6_input(input);
556 break;
557
558#endif /* of #if defined(_IP6_CFG) */
559
560 default:
561
562#ifdef ETHER_CFG_UNEXP_WARNING
563
564#ifdef ETHER_CFG_802_WARNING
565
566 if (proto <= 1500)
567 ieee_802_input(input);
568 else
569 syslog(LOG_NOTICE, "[ETHER] unexp proto from: %s, proto: 0x%04x.",
570 mac2str(NULL, GET_ETHER_HDR(input)->shost), proto);
571
572#else /* of #ifdef ETHER_CFG_802_WARNING */
573
574 syslog(LOG_INFO, "[ETHER] unexp proto from: %s, proto: 0x%04x.",
575 mac2str(NULL, GET_ETHER_HDR(input)->shost), proto);
576
577#endif /* of #ifdef ETHER_CFG_802_WARNING */
578
579#endif /* of #ifdef ETHER_CFG_UNEXP_WARNING */
580
581 NET_COUNT_ETHER(net_count_ether.in_err_packets, 1);
582 NET_COUNT_MIB(if_stats.ifUnknownProtos, 1);
583 syscall(rel_net_buf(input));
584 break;
585 }
586 }
587 }
588 }
589
590#endif /* of #ifdef SUPPORT_ETHER */
Note: See TracBrowser for help on using the repository browser.