source: azure_iot_hub/trunk/asp3_dcre/tinet/net/ethernet.c@ 388

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

Azure IoT Hub Device C SDK を使ったサンプルの追加

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