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

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

ASP3版ECNLを追加

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