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

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

mruby版ECNLプロトタイピング・ツールを追加

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
  • Property svn:mime-type set to text/x-csrc
File size: 13.1 KB
Line 
1/*
2 * TINET (TCP/IP Protocol Stack)
3 *
4 * Copyright (C) 2001-2009 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 270 2017-02-09 04:03:47Z 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_var.h>
78#include <net/net_buf.h>
79#include <net/net_timer.h>
80#include <net/net_count.h>
81
82#include <netinet/in.h>
83#include <netinet/in_var.h>
84#include <netinet/if_ether.h>
85#include <netinet6/if6_ether.h>
86#include <netinet6/nd6.h>
87
88#include <net/if_var.h>
89#include <net/if6_var.h>
90
91#ifdef SUPPORT_ETHER
92
93/*
94 * 変数
95 */
96
97#if defined(SUPPORT_INET4)
98
99const uint8_t ether_broad_cast_addr[ETHER_ADDR_LEN] = {
100 UINT_C(0xff), UINT_C(0xff), UINT_C(0xff),
101 UINT_C(0xff), UINT_C(0xff), UINT_C(0xff)
102 };
103
104#endif /* of #if defined(SUPPORT_INET4) */
105
106/*
107 * 変数
108 */
109
110/* ネットワークインタフェース構造体 */
111
112#if defined(SUPPORT_INET4)
113
114static T_IFNET ether_ifnet = {
115 NULL, /* ネットワークインタフェースのソフトウェア情
116å ± */
117 {
118 IPV4_ADDR_LOCAL, /* IPv4 アドレス */
119 IPV4_ADDR_LOCAL_MASK, /* サブネットマスク */
120 },
121 };
122
123#endif /* of #if defined(SUPPORT_INET4) */
124
125#if defined(SUPPORT_INET6)
126
127static T_IFNET ether_ifnet = {
128 NULL, /* ネットワークインタフェースのソフトウェア情
129å ± */
130 {0}, /* IPv6 アドレス情
131å ± */
132 {0}, /* マルチキャスト IPv6 アドレス */
133 0, /* フラグ */
134 };
135
136#endif /* of #if defined(SUPPORT_INET6) */
137
138#ifdef SUPPORT_MIB
139
140/*
141 * SNMP の 管理情
142報ベース (MIB)
143 */
144
145T_IF_STATS if_stats;
146
147#endif /* of #ifdef SUPPORT_MIB */
148
149#ifdef ETHER_CFG_802_WARNING
150
151/*
152 * 関数
153 */
154
155static void ieee_802_input (T_NET_BUF *input);
156
157/*
158 * ieee_802_input -- IEEE 802.3 å…
159¥åŠ›å‡¦ç†
160 */
161
162static void
163ieee_802_input (T_NET_BUF *input)
164{
165 T_8023MAC_HDR *mhdr;
166 T_8022SNAP_HDR *shdr;
167
168 mhdr = GET_8023MAC_HDR(input);
169 shdr = GET_8022SNAP_HDR(input);
170 syslog(LOG_WARNING, "[ETHER] unexp 802.3 from: %s, proto: 0x%04x.",
171 mac2str(NULL, mhdr->shost), ntohs(*(uint16_t*)&shdr->type));
172 }
173
174#endif /* of #ifdef ETHER_CFG_802_WARNING */
175
176/*
177 * ether_get_ifnet -- ネットワークインタフェース構造体を返す。
178 */
179
180T_IFNET *
181ether_get_ifnet (void)
182{
183 return &ether_ifnet;
184 }
185
186#if defined(SUPPORT_INET6)
187
188/*
189 * ether_in6_resolve_multicast -- イーサネットのマルチキャストアドレスへの変換
190 */
191
192ER
193ether_in6_resolve_multicast (T_ETHER_ADDR *ifaddr, T_IN6_ADDR *maddr)
194{
195 /* マルチキャストアドレスかチェックする。*/
196 if (!IN6_IS_ADDR_MULTICAST(maddr))
197 return E_PAR;
198
199 /* イーサネットのマルチキャストアドレスへの変換 */
200 ether_map_ipv6_multicast(ifaddr, maddr);
201
202 return E_OK;
203 }
204
205#endif /* of #if defined(SUPPORT_INET6) */
206
207/**
208 * Called by a driver when its link goes up
209 */
210void ether_set_link_up(T_IFNET *ether)
211{
212 if (!(ether->flags & IF_FLAG_LINK_UP)) {
213 ether->flags |= IF_FLAG_LINK_UP;
214
215 if (ether->flags & IF_FLAG_UP) {
216#if LWIP_ARP
217 /* For Ethernet network interfaces, we would like to send a "gratuitous ARP" */
218 if (ether->flags & IF_FLAG_ETHARP) {
219 etharp_gratuitous(ether);
220 }
221#endif /* LWIP_ARP */
222 }
223 if (ether->link_callback) {
224 (ether->link_callback)(ether);
225 }
226 }
227}
228
229/**
230 * Called by a driver when its link goes down
231 */
232void ether_set_link_down(T_IFNET *ether)
233{
234 if (ether->flags & IF_FLAG_LINK_UP) {
235 ether->flags &= ~IF_FLAG_LINK_UP;
236 if (ether->link_callback) {
237 (ether->link_callback)(ether);
238 }
239 }
240}
241
242/**
243 * Set callback to be called when link is brought up/down
244 */
245void ether_set_link_callback(ether_status_callback_fn link_callback)
246{
247 ether_ifnet.link_callback = link_callback;
248}
249
250/*
251 * ether_raw_output -- Ethernet インタフェースの出力関数、MAC アドレス解決無し
252 */
253
254ER
255ether_raw_output (T_NET_BUF *output, TMO tmout)
256{
257 ER error = E_OK;
258
259 /* Ethernet 出力キューに投å…
260¥ã™ã‚‹ã€‚*/
261 if ((error = tsnd_dtq(DTQ_ETHER_OUTPUT, (intptr_t)output, tmout)) != E_OK) {
262 NET_COUNT_ETHER(net_count_ether.out_err_packets, 1);
263 NET_COUNT_MIB(if_stats.ifOutDiscards, 1);
264
265 /* IF でネットワークバッファを開放しないフラグをチェックする。*/
266 if ((output->flags & NB_FLG_NOREL_IFOUT) == 0) {
267 syscall(rel_net_buf(output));
268 }
269 else {
270 output->flags &= (uint8_t)~NB_FLG_NOREL_IFOUT;
271 }
272 IF_ETHER_NIC_RESET(IF_ETHER_NIC_GET_SOFTC());
273 }
274 return error;
275 }
276
277/*
278 * ether_output -- Ethernet インタフェースの出力関数、MAC アドレス解決有り
279 */
280
281ER
282ether_output (T_NET_BUF *output, void *dst, T_IF_ADDR *gw, TMO tmout)
283{
284 T_IF_SOFTC *ic;
285 ER error = E_OK;
286 T_ETHER_HDR *eth;
287
288 /* 送信å…
289ƒ MAC アドレスを設定する。*/
290 ic = IF_ETHER_NIC_GET_SOFTC();
291 eth = GET_ETHER_HDR(output);
292 memcpy(eth->shost, ic->ifaddr.lladdr, ETHER_ADDR_LEN);
293
294 switch(ntohs(eth->type)) {
295
296#if defined(SUPPORT_INET4)
297
298 case ETHER_TYPE_IP: /* IPv4 */
299#ifdef ETHER_CFG_MULTICAST
300 /* マルチキャストアドレスの場合 */
301 if(IN4_IS_ADDR_MULTICAST(*(uint32_t*)dst)){
302 /* イーサネットのマルチキャストアドレスへの変換 */
303 ether_map_ipv4_multicast((T_ETHER_ADDR *)&eth->dhost, *(T_IN4_ADDR*)dst);
304 error = ether_raw_output(output, tmout);
305 break;
306 }
307#endif
308 if (arp_resolve(&ic->ifaddr, output, *(uint32_t*)dst)) { /* true ならアドレス解決済 */
309 error = ether_raw_output(output, tmout);
310 }
311 break;
312
313#endif /* of #if defined(SUPPORT_INET4) */
314
315#if defined(SUPPORT_INET6)
316
317 case ETHER_TYPE_IPV6: /* IPv6 */
318 error = nd6_storelladdr((T_ETHER_ADDR*)GET_ETHER_HDR(output)->dhost,
319 (T_IN6_ADDR*)dst, gw);
320 if (error == E_OK)
321 error = ether_raw_output(output, tmout);
322
323 /* IF でネットワークバッファを開放しないフラグをチェックする。*/
324 else if ((output->flags & NB_FLG_NOREL_IFOUT) == 0) {
325 syscall(rel_net_buf(output));
326 }
327 else {
328 output->flags &= (uint8_t)~NB_FLG_NOREL_IFOUT;
329 }
330 break;
331
332#endif /* of #if defined(SUPPORT_INET6) */
333
334 default:
335 NET_COUNT_MIB(if_stats.ifOutErrors, 1);
336
337 /* IF でネットワークバッファを開放しないフラグをチェックする。*/
338 if ((output->flags & NB_FLG_NOREL_IFOUT) == 0) {
339 syscall(rel_net_buf(output));
340 }
341 else {
342 output->flags &= (uint8_t)~NB_FLG_NOREL_IFOUT;
343 }
344 error = E_PAR;
345 break;
346 }
347
348 if (error != E_OK)
349 NET_COUNT_ETHER(net_count_ether.out_err_packets, 1);
350 return error;
351 }
352
353/*
354 * Ethernet 出力タスク
355 */
356
357void
358ether_output_task(intptr_t exinf)
359{
360 T_IF_SOFTC *ic;
361 T_NET_BUF *output;
362 ID tskid;
363
364 get_tid(&tskid);
365 syslog(LOG_NOTICE, "[ETHER OUTPUT:%d] started.", tskid);
366
367 ic = IF_ETHER_NIC_GET_SOFTC();
368
369 while (true) {
370 while (rcv_dtq(DTQ_ETHER_OUTPUT, (intptr_t*)&output) == E_OK) {
371 NET_COUNT_ETHER(net_count_ether.out_octets, output->len);
372 NET_COUNT_MIB(if_stats.ifOutOctets, output->len + 8);
373 NET_COUNT_ETHER(net_count_ether.out_packets, 1);
374
375#ifdef SUPPORT_MIB
376 if ((*(GET_ETHER_HDR(output)->dhost) & ETHER_MCAST_ADDR) == 0) {
377 NET_COUNT_MIB(if_stats.ifOutUcastPkts, 1);
378 }
379 else {
380 NET_COUNT_MIB(if_stats.ifOutNUcastPkts, 1);
381 }
382#endif /* of #ifdef SUPPORT_MIB */
383
384 syscall(wai_sem(ic->semid_txb_ready));
385
386 IF_ETHER_NIC_START(ic, output);
387
388#ifndef ETHER_NIC_CFG_RELEASE_NET_BUF
389
390 if ((output->flags & NB_FLG_NOREL_IFOUT) == 0) {
391 syscall(rel_net_buf(output));
392 }
393 else {
394 output->flags &= (uint8_t)~NB_FLG_NOREL_IFOUT;
395
396#ifdef SUPPORT_TCP
397 sig_sem(SEM_TCP_POST_OUTPUT);
398#endif /* of #ifdef SUPPORT_TCP */
399 }
400
401#endif /* of #ifndef ETHER_NIC_CFG_RELEASE_NET_BUF */
402
403 }
404 }
405 }
406
407/*
408 * Ethernet å…
409¥åŠ›ã‚¿ã‚¹ã‚¯
410 */
411
412void
413ether_input_task(intptr_t exinf)
414{
415 T_IF_SOFTC *ic;
416 T_NET_BUF *input;
417 T_ETHER_HDR *eth;
418 ID tskid;
419 uint16_t proto;
420
421 /* ネットワークインタフェース管理を初期化する。*/
422 ifinit();
423
424 /* NIC を初期化する。*/
425 ic = IF_ETHER_NIC_GET_SOFTC();
426 IF_ETHER_NIC_PROBE(ic);
427 IF_ETHER_NIC_INIT(ic);
428
429 /* Ethernet 出力タスクを起動する */
430 syscall(act_tsk(ETHER_OUTPUT_TASK));
431
432 /* ネットワークタイマタスクを起動する */
433 syscall(act_tsk(NET_TIMER_TASK));
434
435 get_tid(&tskid);
436
437 syslog(LOG_NOTICE, "[ETHER INPUT:%2d] started on MAC Addr: %s.",
438 tskid, mac2str(NULL, ic->ifaddr.lladdr));
439
440#if defined(SUPPORT_INET4)
441
442 /* ARP を初期化する。*/
443 arp_init();
444
445#endif /* of #if defined(SUPPORT_INET4) */
446
447 ether_ifnet.ic = ic;
448
449 while (true) {
450 syscall(wai_sem(ic->semid_rxb_ready));
451 if ((input = IF_ETHER_NIC_READ(ic)) != NULL) {
452 NET_COUNT_ETHER(net_count_ether.in_octets, input->len);
453 NET_COUNT_MIB(if_stats.ifInOctets, input->len + 8);
454 NET_COUNT_ETHER(net_count_ether.in_packets, 1);
455 eth = GET_ETHER_HDR(input);
456 proto = ntohs(eth->type);
457
458#ifdef SUPPORT_MIB
459 if ((*eth->dhost & ETHER_MCAST_ADDR) == 0) {
460 NET_COUNT_MIB(if_stats.ifInUcastPkts, 1);
461 }
462 else {
463 NET_COUNT_MIB(if_stats.ifInNUcastPkts, 1);
464 }
465#endif /* of #ifdef SUPPORT_MIB */
466
467#if defined(SUPPORT_INET4) && defined(ETHER_CFG_ACCEPT_ALL)
468
469 if ((*eth->dhost & ETHER_MCAST_ADDR) && *eth->dhost != 0xff) {
470
471#ifdef ETHER_CFG_MCAST_WARNING
472
473 if (proto <= 1500)
474 proto = ntohs(*(uint16_t*)&(GET_8022SNAP_HDR(input)->type));
475 syslog(LOG_WARNING, "[ETHER] mcast addr from: %s, to: %s, proto: 0x%04x.",
476 mac2str(NULL, eth->shost), mac2str(NULL, eth->dhost), proto);
477
478#endif /* of #ifdef ETHER_CFG_MCAST_WARNING */
479
480 NET_COUNT_ETHER(net_count_ether.in_err_packets, 1);
481 NET_COUNT_MIB(if_stats.ifInErrors, 1);
482 syscall(rel_net_buf(input));
483 continue;
484 }
485
486#endif /* of #if defined(SUPPORT_INET4) && defined(ETHER_CFG_ACCEPT_ALL) */
487
488 switch(proto) {
489
490#if defined(SUPPORT_INET4)
491
492 case ETHER_TYPE_IP: /* IP */
493 ip_input(input);
494 break;
495
496 case ETHER_TYPE_ARP: /* ARP */
497 arp_input(&ic->ifaddr, input);
498 break;
499
500#endif /* of #if defined(SUPPORT_INET4) */
501
502#if defined(SUPPORT_INET6)
503
504 case ETHER_TYPE_IPV6: /* IPv6 */
505 ip6_input(input);
506 break;
507
508#endif /* of #if defined(SUPPORT_INET6) */
509
510 default:
511
512#ifdef ETHER_CFG_UNEXP_WARNING
513
514#ifdef ETHER_CFG_802_WARNING
515
516 if (proto <= 1500)
517 ieee_802_input(input);
518 else
519 syslog(LOG_NOTICE, "[ETHER] unexp proto from: %s, proto: 0x%04x.",
520 mac2str(NULL, GET_ETHER_HDR(input)->shost), proto);
521
522#else /* of #ifdef ETHER_CFG_802_WARNING */
523
524 syslog(LOG_INFO, "[ETHER] unexp proto from: %s, proto: 0x%04x.",
525 mac2str(NULL, GET_ETHER_HDR(input)->shost), proto);
526
527#endif /* of #ifdef ETHER_CFG_802_WARNING */
528
529#endif /* of #ifdef ETHER_CFG_UNEXP_WARNING */
530
531 NET_COUNT_ETHER(net_count_ether.in_err_packets, 1);
532 NET_COUNT_MIB(if_stats.ifUnknownProtos, 1);
533 syscall(rel_net_buf(input));
534 break;
535 }
536 }
537 }
538 }
539
540#endif /* of #ifdef SUPPORT_ETHER */
Note: See TracBrowser for help on using the repository browser.