source: EcnlProtoTool/trunk/asp3_dcre/tinet/net/ethernet.c@ 331

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

prototoolに関連するプロジェクトをnewlibからmuslを使うよう変更・更新
ntshellをnewlibの下位の実装から、muslのsyscallの実装に変更・更新
以下のOSSをアップデート
・mruby-1.3.0
・musl-1.1.18
・onigmo-6.1.3
・tcc-0.9.27
以下のOSSを追加
・openssl-1.1.0e
・curl-7.57.0
・zlib-1.2.11
以下のmrbgemsを追加
・iij/mruby-digest
・iij/mruby-env
・iij/mruby-errno
・iij/mruby-iijson
・iij/mruby-ipaddr
・iij/mruby-mock
・iij/mruby-require
・iij/mruby-tls-openssl

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