FreeBSD 日本語マニュアル検索 (jman/japropos/jwhatis)


日本語 man コマンド類 (ja-man-1.1j_5) と日本語 man ドキュメント (ja-man-doc-5.4 (5.4-RELEASE 用) など) をインストールすると、以下のような man コマンド閲覧、キーワード検索が コンソールからできるようになります。

4.11-RELEASE-K, 5.4-RELEASE-K, 5.5-RELEASE-K, 6.0-RELEASE-K から 6.4-RELEASE-K, 7.0-RELEASE-K から 7.4-RELEASE-K, 8.0-RELEASE-K から 8.4-RELEASE-K, 9.0-RELEASE-K から 9.3-RELEASE-K, 10.0-RELEASE-K から 10.3-RELEASE-K, 11.0-RELEASE-K から 11.4-RELEASE-K, 12.0-RELEASE-K, 12.1-RELEASE-K は、 プライベート版 (小金丸が編集してまとめたもの) ですが、 より多くの翻訳したファイルが含まれています。 (5.4-RELEASE-K から 6.4-RELEASE-K, 7.0-RELEASE-K から 7.4-RELEASE-K, 8.0-RELEASE-K から 8.4-RELEASE-K, 9.0-RELEASE-K から 9.3-RELEASE-K, 10.0-RELEASE-K から 10.3-RELEASE-K, 11.0-RELEASE-K から 11.4-RELEASE-K, 12.0-RELEASE-K から 12.3-RELEASE-K, 13.0-RELEASE-K から 13.2-RELEASE-K は、全翻訳済み)

13.3-STABLE-K, 15.0-CURRENT-K は現在、作成中で日々更新されています。



検索コマンド: man apropos whatis
コマンド/キーワード:
日本語マニュアル RELEASE :
セクション:
Table of Contents
名称 | 書式 | 解説 | 関連項目 | 歴史 | 作者
MULTICAST(4)       FreeBSD カーネルインタフェースマニュアル       MULTICAST(4)

名称
     multicast -- マルチキャスト経路制御

書式
     options MROUTING

     #include <sys/types.h>
     #include <sys/socket.h>
     #include <netinet/in.h>
     #include <netinet/ip_mroute.h>
     #include <netinet6/ip6_mroute.h>

     int
     getsockopt(int s, IPPROTO_IP, MRT_INIT, void *optval, socklen_t *optlen);

     int
     setsockopt(int s, IPPROTO_IP, MRT_INIT, const void *optval,
           socklen_t optlen);

     int
     getsockopt(int s, IPPROTO_IPV6, MRT6_INIT, void *optval,
           socklen_t *optlen);

     int
     setsockopt(int s, IPPROTO_IPV6, MRT6_INIT, const void *optval,
           socklen_t optlen);

解説
     マルチキャスト経路制御は、マルチポイントネットワークでデータパケットを効
     率的に一連のマルチキャストリスナに伝播するために使用されます。ユニキャス
     トがすべてのリスナにデータを複製するために使用されるなら、いくつかのネッ
     トワークリンクは、同じデータパケットの複数のコピーを伝達するかもしれませ
     ん。マルチキャスト経路制御で、オーバヘッドは、ネットワークリンク単位で
     (多くても) 1 つのコピーまで下げられます。

     すべてのマルチキャスト可能なルータは、一般的なマルチキャスト経路制御プロ
     トコルを実行しなければなりません。Protocol Independent Multicast - スパー
     ス (まばらな) モード (PIM-SM)、または、Protocol Independent Multicast -
     デンス (濃い) モード (PIM-DM) のいずれかは、現在、インターネットコミュニ
     ティで一般的に、受け入れられたプロトコルであるので、これらを使用すること
     を勧めます。歴史セクションで、以前のマルチキャスト経路制御プロトコルにつ
     いて議論しています。

     マルチキャスト経路制御を始めるためには、ユーザは、カーネル (カーネル設定
     オプションについては、書式を参照) でマルチキャスト転送を有効にしなければ
     ならなくて、マルチキャスト経路制御可能なユーザレベルプロセスを実行しなけ
     ればなりません。開発者の観点から、プログラミングガイドセクションで説明さ
     れたプログラミングガイドは、カーネルにおけるマルチキャスト転送を制御する
     ために使用されるでしょう。

   プログラミングガイド
     このセクションは、基本的なマルチキャスト経路制御 API に関する情報を提供し
     ます。いわゆる ``高度なマルチキャスト API'' は、高度なマルチキャスト API
     プログラミングガイドデクションで説明されます。

     最初に、マルチキャスト経路制御ソケットがオープンされなければなりません。
     そのソケットは、カーネルでマルチキャスト転送を制御するために使用されるで
     しょう。以下でのほとんどの操作がある種の特権 (すなわち、root の特権) を必
     要とすることに注意してください:

     /* IPv4 */
     int mrouter_s4;
     mrouter_s4 = socket(AF_INET, SOCK_RAW, IPPROTO_IGMP);

     int mrouter_s6;
     mrouter_s6 = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6);

     IGMP か MLD マルチキャストグループメンバシップメッセージの送信か受信にお
     いて、IGMP か ICMPv6 ソケット (それぞれ IPv4 と IPv6 の場合) をルータが
     オープンする必要があるなら、同様に mrouter_s4mrouter_s6 ソケットは、
     それぞれ IGMP か MLD メッセージの送信か受信に使用されるべきであることに注
     意してください。BSD 派生カーネルの場合には、IGMP か MLD メッセージのため
     だけに別々のソケットをオープンできるかもしれません。しかしながら、ある他
     のカーネル (例えば、Linux) は、マルチキャスト経路制御ソケットが IGMP か
     MLD メッセージの送受信を使用しなければならないことを必要とします。した
     がって、移植性の理由で、マルチキャスト経路制御ソケットは、同様に IGMP と
     MLD メッセージのために再利用すべきです。

     マルチキャスト経路制御ソケットがオープンされた後に、それは、カーネルでマ
     ルチキャスト転送を有効にするか無効にするために使用することができます:

     /* IPv4 */
     int v = 1;        /* 1 は、有効, または 0 は、無効 */
     setsockopt(mrouter_s4, IPPROTO_IP, MRT_INIT, (void *)&v, sizeof(v));

     /* IPv6 */
     int v = 1;        /* 1 は、有効, または 0 は、無効 */
     setsockopt(mrouter_s6, IPPROTO_IPV6, MRT6_INIT, (void *)&v, sizeof(v));
     ...
     /* 必要なら, すべての ICMPv6 メッセージをフィルタする */
     struct icmp6_filter filter;
     ICMP6_FILTER_SETBLOCKALL(&filter);
     setsockopt(mrouter_s6, IPPROTO_ICMPV6, ICMP6_FILTER, (void *)&filter,
                sizeof(filter));

     マルチキャスト転送が有効にされた後に、マルチキャスト経路制御ソケットは、
     PIM-SM か PIM-DM が実行されているなら、カーネルで PIM 処理を有効にするた
     めに使用することができます (pim(4) 参照)。

     マルチキャスト転送に使用される、それぞれのネットワークインタフェース (例
     えば、物理または仮想トンネル) については、対応するマルチキャストインタ
     フェースがカーネルに追加されなければなりません:

     /* IPv4 */
     struct vifctl vc;
     memset(&vc, 0, sizeof(vc));
     /* すべての vifctl フィールドを適切に割り当てます */
     vc.vifc_vifi = vif_index;
     vc.vifc_flags = vif_flags;
     vc.vifc_threshold = min_ttl_threshold;
     vc.vifc_rate_limit = 0;
     memcpy(&vc.vifc_lcl_addr, &vif_local_address, sizeof(vc.vifc_lcl_addr));
     setsockopt(mrouter_s4, IPPROTO_IP, MRT_ADD_VIF, (void *)&vc,
                sizeof(vc));

     vif_index は、vif 単位でユニークでなければなりません。vif_flags は、
     <netinet/ip_mroute.h> で定義されるように VIFF_* フラグを含んでいます。
     VIFF_TUNNEL フラグは、もはや FreeBSD でサポートされません。トンネル上でマ
     ルチキャストデータグラムを転送したいユーザは、gif(4) または gre(4) トンネ
     ルを設定して、物理インタフェースとして、それを使用することを考慮すべきで
     す。

     min_ttl_threshold は、マルチキャストデータパケットがその vif で転送される
     ためになければならない最小の TTL (有効期間) を含んでいます。通常、それ
     は、1 の値となります。

     max_rate_limit 引数は、もはや FreeBSD でサポートされず、0 に設定されるべ
     きです。マルチキャストデータグラムをレート制限したいユーザは、dummynet(4)
     または altq(4) の使用を考慮すべきです。

     vif_local_address は、対応するローカルインタフェースのローカル IP アドレ
     スを含んでいます。vif_remote_address は、DVMRP マルチキャストトンネルの場
     合にリモート IP アドレスを含んでいます。

     /* IPv6 */
     struct mif6ctl mc;
     memset(&mc, 0, sizeof(mc));
     /* すべての mif6ctl フィールドを適切に割り当てます */
     mc.mif6c_mifi = mif_index;
     mc.mif6c_flags = mif_flags;
     mc.mif6c_pifi = pif_index;
     setsockopt(mrouter_s6, IPPROTO_IPV6, MRT6_ADD_MIF, (void *)&mc,
                sizeof(mc));

     mif_index は、vif 単位でユニークでなければなりません。mif_flags は、
     <netinet6/ip6_mroute.h> で定義されるように MIFF_* を含んでいます。
     pif_index は、対応するローカルインタフェースの物理的なインタフェースイン
     デックスです。

     マルチキャストインタフェースは、次によって削除されます:

     /* IPv4 */
     vifi_t vifi = vif_index;
     setsockopt(mrouter_s4, IPPROTO_IP, MRT_DEL_VIF, (void *)&vifi,
                sizeof(vifi));

     /* IPv6 */
     mifi_t mifi = mif_index;
     setsockopt(mrouter_s6, IPPROTO_IPV6, MRT6_DEL_MIF, (void *)&mifi,
                sizeof(mifi));

     マルチキャスト転送が有効にされて、マルチキャスト仮想インタフェースが追加
     された後に、カーネルは、以前に MRT_INIT または MRT6_INIT でオープンされて
     いるマルチキャスト経路制御ソケット上で upcall メッセージ (このテキストの
     後ろでまたの名は、シグナルです) を配信できます。IPv4 upcall は、フィール
     ド im_mbz を 0 に設定した struct igmpmsg ヘッダ (<netinet/ip_mroute.h> 参
     照) があります。このヘッダは、プロトコルフィールド ip_p を 0 に設定した
     struct ip 構造体が後に続くことに注意してください。IPv6 upcall は、フィー
     ルド im6_mbz を 0 に設定した struct mrt6msg ヘッダ
     (<netinet6/ip6_mroute.h> 参照) があります。このヘッダは、次のヘッダフィー
     ルド ip6_nxt を 0 に設定した struct ip6_hdr 構造体が後に続くことに注意し
     てください。

     upcall ヘッダは、それぞれ IPv4 と IPv6 のための upcall のタイプ IGMPMSG_*
     と MRT6MSG_* でフィールド im_msgtypeim6_msgtype を含んでいます。
     upcall ヘッダフィールドの残りの値と upcall メッセージの本体は、特定の
     upcall タイプに依存します。

     upcall メッセージタイプが IGMPMSG_NOCACHE または MRT6MSG_NOCACHE であるな
     ら、これは、マルチキャストパケットがマルチキャストルータに到達したことを
     示しますが、ルータには、そのパケットのための転送状態がありません。通常、
     upcall は、適切な Multicast Forwarding Cache (MFC) エントリをカーネルにイ
     ンストールするためにマルチキャストのユーザレベルのプロセスのためのシグナ
     ルとなります。

     MFC エントリは、次によって追加されます:

     /* IPv4 */
     struct mfcctl mc;
     memset(&mc, 0, sizeof(mc));
     memcpy(&mc.mfcc_origin, &source_addr, sizeof(mc.mfcc_origin));
     memcpy(&mc.mfcc_mcastgrp, &group_addr, sizeof(mc.mfcc_mcastgrp));
     mc.mfcc_parent = iif_index;
     for (i = 0; i < maxvifs; i++)
     mc.mfcc_ttls[i] = oifs_ttl[i];
     setsockopt(mrouter_s4, IPPROTO_IP, MRT_ADD_MFC,
            (void *)&mc, sizeof(mc));

     /* IPv6 */
     struct mf6cctl mc;
     memset(&mc, 0, sizeof(mc));
     memcpy(&mc.mf6cc_origin, &source_addr, sizeof(mc.mf6cc_origin));
     memcpy(&mc.mf6cc_mcastgrp, &group_addr, sizeof(mf6cc_mcastgrp));
     mc.mf6cc_parent = iif_index;
     for (i = 0; i < maxvifs; i++)
     if (oifs_ttl[i] > 0)
         IF_SET(i, &mc.mf6cc_ifset);
     setsockopt(mrouter_s6, IPPROTO_IPV6, MRT6_ADD_MFC,
            (void *)&mc, sizeof(mc));

     source_addrgroup_addr は、(upcall メッセージで設定されるような) マル
     チキャストパケットのソースとグループアドレスです。iif_index は、この特定
     のソースとグループアドレスのためのマルチキャストパケットが受信されるべき
     であるマルチキャストインタフェースの仮想インタフェースインデックスです。
     oifs_ttl[] 配列は、マルチキャストパケットが発信インタフェースで転送される
     ために持つべきである最小の TTL (インタフェース毎の) を含んでいます。TTL
     値が 0 であるなら、対応するインタフェースは、発信インタフェースのセットに
     含まれていません。IPv6 だけの場合に発信インタフェースのセットが指定できる
     ことに注意してください。

     MFC エントリは、次によって削除されます:

     /* IPv4 */
     struct mfcctl mc;
     memset(&mc, 0, sizeof(mc));
     memcpy(&mc.mfcc_origin, &source_addr, sizeof(mc.mfcc_origin));
     memcpy(&mc.mfcc_mcastgrp, &group_addr, sizeof(mc.mfcc_mcastgrp));
     setsockopt(mrouter_s4, IPPROTO_IP, MRT_DEL_MFC,
            (void *)&mc, sizeof(mc));

     /* IPv6 */
     struct mf6cctl mc;
     memset(&mc, 0, sizeof(mc));
     memcpy(&mc.mf6cc_origin, &source_addr, sizeof(mc.mf6cc_origin));
     memcpy(&mc.mf6cc_mcastgrp, &group_addr, sizeof(mf6cc_mcastgrp));
     setsockopt(mrouter_s6, IPPROTO_IPV6, MRT6_DEL_MFC,
            (void *)&mc, sizeof(mc));

     次の方法は、カーネルにインストールされた MFC エントリ毎に様々な統計値 (例
     えば、ソースとグループアドレス毎の転送パケットの数) を得るために使用でき
     ます:

     /* IPv4 */
     struct sioc_sg_req sgreq;
     memset(&sgreq, 0, sizeof(sgreq));
     memcpy(&sgreq.src, &source_addr, sizeof(sgreq.src));
     memcpy(&sgreq.grp, &group_addr, sizeof(sgreq.grp));
     ioctl(mrouter_s4, SIOCGETSGCNT, &sgreq);

     /* IPv6 */
     struct sioc_sg_req6 sgreq;
     memset(&sgreq, 0, sizeof(sgreq));
     memcpy(&sgreq.src, &source_addr, sizeof(sgreq.src));
     memcpy(&sgreq.grp, &group_addr, sizeof(sgreq.grp));
     ioctl(mrouter_s6, SIOCGETSGCNT_IN6, &sgreq);

     次の方法は、カーネルでマルチキャスト仮想インタフェース毎の様々な統計値
     (例えば、インタフェース毎の転送パケットの数) を得るために使用できます:

     /* IPv4 */
     struct sioc_vif_req vreq;
     memset(&vreq, 0, sizeof(vreq));
     vreq.vifi = vif_index;
     ioctl(mrouter_s4, SIOCGETVIFCNT, &vreq);

     /* IPv6 */
     struct sioc_mif_req6 mreq;
     memset(&mreq, 0, sizeof(mreq));
     mreq.mifi = vif_index;
     ioctl(mrouter_s6, SIOCGETMIFCNT_IN6, &mreq);

   高度なマルチキャスト API プログラミングガイド
     カーネルに新しい機能を追加したいと思うなら、後方互換性 (バイナリと API)
     を保つのが難しくなって、同時にユーザレベルプロセスに (カーネルがそれらを
     サポートするなら) 新しい機能を利用することを許容します。

     私たちが後方互換性を保つことができるようするメカニズムの 1 つは、ユーザレ
     ベルプロセスとカーネルの間の一種のネゴシエーション (交渉) です:

     1.   ユーザレベルプロセスは、カーネルで使用したい新しい機能 (と対応する
          API) のセットを有効にしようとします。

     2.   カーネルは、それについて知っている機能の (サブ) セットを返して、進ん
          で有効にします。

     3.   ユーザレベルプロセスは、カーネルが同意した機能のセットだけを使用しま
          す。

     後方互換性をサポートするために、ユーザレベルプロセスが少しも新しい機能を
     要求しないなら、カーネルは、基本的なマルチキャスト API (プログラミングガ
     イドセクションを参照) をデフォルトとします現在は、高度なマルチキャスト
     API は、IPv4 のためだけに存在します。将来は、同様に IPv6 サポートがあるで
     しょう。

     下記は、拡張可能な API ソリューション (解決法) の概要です。すべての新しい
     オプションと構造体は、ほかに規定されたものがある場合を除き
     <netinet/ip_mroute.h> と <netinet6/ip6_mroute.h> で定義されることに注意し
     てください。

     ユーザレベルプロセスは、カーネルとの API 機能ネゴシエーション (交渉) を実
     行するために、新しい getsockopt()/setsockopt() オプションを使用します。こ
     のネゴシエーション (交渉) は、マルチキャスト経路制御ソケットがオープンさ
     れた直後に実行しなければなりません。要求/許容の機能のセット (集合) は、
     ビットセットとして保存されます (現在、uint32_t で、すなわち、最大 32 の新
     しい機能です)。新しい getsockopt()/setsockopt() オプションは、
     MRT_API_SUPPORT と MRT_API_CONFIG です。例えば:

     uint32_t v;
     getsockopt(sock, IPPROTO_IP, MRT_API_SUPPORT, (void *)&v, sizeof(v));

     これは、v にカーネル API サポートで前もって定義されたビットを設定します。
     uint32_t 中の 8 つの最下位ビットは、他の新しい機能について 24 個のフラグ
     を残す struct mfcctl (これらのフラグについては、下記参照) の新しい定義の
     一部として mfcc_flags で使用することができる、可能性がある 8 つのフラグ
     MRT_MFC_FLAGS_* と同様です。getsockopt(MRT_API_SUPPORT) によって返された
     値は、読み込み専用です。言い換えれば、setsockopt(MRT_API_SUPPORT) 失敗す
     るでしょう。

     API を変更して、カーネルに何らかの特有の機能を設定するためには:

     uint32_t v = MRT_MFC_FLAGS_DISABLE_WRONGVIF;
     if (setsockopt(sock, IPPROTO_IP, MRT_API_CONFIG, (void *)&v, sizeof(v))
         != 0) {
         return (ERROR);
     }
     if (v & MRT_MFC_FLAGS_DISABLE_WRONGVIF)
         return (OK);        /* 成功 */
     else
         return (ERROR);

     言い換えれば、setsockopt(MRT_API_CONFIG) が呼び出されるとき、それへの引数
     は、API とカーネルで有効にされる機能の要求されるセットを指定します。v の
     リターン値は、カーネルで有効にされた機能の実際の (サブ) セットです。有効
     にされた機能の同じセットを後で取得ためには:

     getsockopt(sock, IPPROTO_IP, MRT_API_CONFIG, (void *)&v, sizeof(v));

     有効にされた機能のセットは、グローバルです。言い換えれば、
     setsockopt(MRT_API_CONFIG) は、setsockopt(MRT_INIT) の直後に呼び出される
     べきです。

     現在は、新しい機能の次のセットは、次のように定義されます:

     #define MRT_MFC_FLAGS_DISABLE_WRONGVIF (1 << 0) /* WRONGVIF シグナルを
                                                        無効にする */
     #define MRT_MFC_FLAGS_BORDER_VIF   (1 << 1)  /* ボーダ vif              */
     #define MRT_MFC_RP                 (1 << 8)  /* RP アドレスを有効にする */
     #define MRT_MFC_BW_UPCALL          (1 << 9)  /* bw upcall を有効にする  */

     高度なマルチキャスト API は、旧来の struct mfcctl2 の代わりに新たに定義さ
     れた struct mfcctl を使用します。オリジナルの struct mfcctl は、そのまま
     に保持されます。新しい struct mfcctl2 は、以下の通りです:

     /*
      * MRT_ADD_MFC と MRT_DEL_MFC のための新しい引数の構造体は、
      * 古い struct mfcctl をオーバレイして拡張しています。
      */
     struct mfcctl2 {
             /* the mfcctl fields */
             struct in_addr  mfcc_origin;       /* マルチキャストの ip 始点  */
             struct in_addr  mfcc_mcastgrp;     /* マルチキャストグループ関連*/
             vifi_t          mfcc_parent;       /* 着信 vif                  */
             u_char          mfcc_ttls[MAXVIFS];/* vif の転送 ttl            */

             /* extension fields */
             uint8_t         mfcc_flags[MAXVIFS];/* MRT_MFC_FLAGS_* フラグ   */
             struct in_addr  mfcc_rp;            /* RP アドレス              */
     };

     新しいフィールドは、mfcc_flags[MAXVIFS]mfcc_rp です。互換性の理由のた
     めにそれらが終わりに追加されることに注意してください。

     mfcc_flags[MAXVIFS] フィールドは、(S,G) エントリ単位でインタフェース毎の
     様々なフラグを設定するために使用されます。現在、定義されたフラグは、次の
     通りです:

     #define MRT_MFC_FLAGS_DISABLE_WRONGVIF (1 << 0) /* WRONGVIF シグナルを
                                                        無効にする */
     #define MRT_MFC_FLAGS_BORDER_VIF       (1 << 1) /* ボーダ vif          */

     MRT_MFC_FLAGS_DISABLE_WRONGVIF フラグは、マルチキャストデータパケットが間
     違ったインタフェースで到着するなら、(S,G) 精度で IGMPMSG_WRONGVIF カーネ
     ルシグナルを明らかに無効にするために使用されます。通常、このシグナルは、
     PIM-SM マルチキャスト経路制御の場合に最短パスのスイッチを完了するか、また
     は PIM アサートメッセージをトリガするために使用されます。しかしながら、発
     信インタフェースセットでなくて、着信インタフェースになると期待していない
     インタフェースに配信するべきではありません。したがって、
     MRT_MFC_FLAGS_DISABLE_WRONGVIF フラグがインタフェースのいくつかに設定され
     るなら、データパケットは、MFC エントリが WRONGVIF シグナルをトリガしない
     インタフェースで到着します。そのフラグが設定されないなら、シグナルは、ト
     リガされます (デフォルト動作)。

     MRT_MFC_FLAGS_BORDER_VIF フラグは、PIM レジスタメッセージの境界ビットが設
     定されるべきであるかどうか (レジスタカプセル化がカーネルの中で実行される
     ときの場合に) 指定するために使用されます。それが特別な PIM レジスタカーネ
     ル仮想インタフェースに設定されるなら (pim(4) 参照)、RP に送られたレジスタ
     メッセージ中の境界ビットが設定されます。

     残っている 6 ビットは、将来の使用のために予約されています。

     mfcc_rp フィールドは、カーネルレベル PIM レジスタカプセル化を実行したいと
     思うなら、マルチキャストグループ G に (PIM-SM マルチキャスト経路制御の場
     合に) RP アドレスを指定するためにに使用されます。mfcc_rp フィールドは、
     MRT_MFC_RP 高度な API フラグ/ケーパビリティが setsockopt(MRT_API_CONFIG)
     によってうまく設定された場合にだけ、使用されます。

     MRT_MFC_RP フラグが setsockopt(MRT_API_CONFIG) によってうまく設定されたな
     ら、カーネルは、ユーザレベルカプセル化のためにマルチキャストデータパケッ
     トをユーザレベル (IGMPMSG_WHOLEPKT upcall の中の) に送る代わりに PIM レジ
     スタカプセル化自体を実行するのを試みます。RP アドレスは、新しい struct
     mfcctl2 内の mfcc_rp フィールドから取られるでしょう。しかしながら、
     MRT_MFC_RP フラグがうまく設定されたとしても、mfcc_rp フィールドが
     INADDR_ANY に設定されたなら、カーネルは、まだマルチキャストデータパケット
     と共に IGMPMSG_WHOLEPKT upcall をユーザレベルプロセスに配信します。

     さらに、マルチキャストデータパケットが PIM レジスタカプセル化の後で単一の
     IP パケットの中で適合することができないくらい大きいなら (例えば、約 65500
     バイトのサイズがあったなら)、データパケットは、断片化され、それぞれの断片
     は、別々にカプセル化されます。通常、カプセル化を実行するのと同じホストか
     ら局所的に送出された場合にだけ、マルチキャストデータパケットが大きい場合
     があることに注意してください。そうでなければ、例えばイーサネット上のマル
     チキャストデータパケットの送信は、もっと小さな部分に断片化したでしょう。

     通常、マルチキャスト経路制御のユーザレベルプロセスは、何らかのデータフ
     ローについて転送帯域幅を知る必要があるでしょう。例えば、マルチキャスト経
     路制御プロセスがタイムアウトアイドル MFC エントリを必要とするかもしれませ
     ん、または例えば、帯域幅レートがスレッシュホールドを超えているなら、PIM
     SM の場合に (S,G) 最短パススイッチを開始することができます。

     データフローの帯域幅を測定する独創的な解決策は、ユーザレベルプロセスが定
     期的に (S,G) あたりの転送パケット/バイトの数に関してカーネルに問い合わせ
     ることでした、そして、そしてそれらの数に基づいて、ソース (始点) がアイド
     ルであるかどうか、またはソースの通信帯域幅がスレッシュホールドを超えてい
     るかどうかを評価するでしょう。その解決策は、決してスケーラブル (測定可能)
     ではありません、したがって、帯域幅モニタリングのための新しいメカニズムが
     必要です。

     次は、帯域幅のモニタリングのメカニズムの説明です。

     •   データフローの帯域幅がいくつかの前もって定義されたフィルタを満足させ
         るなら、カーネルは、マルチキャスト経路制御ソケット上の upcall をその
         フィルタをインストールしたマルチキャスト経路制御プロセスに配信しま
         す。

     •   帯域幅 upcall フィルタは、(S,G) 単位でインストールされます。(S,G) ご
         とに 1 つ以上のフィルタがあり得ます。

     •   すべての可能な比較操作 (すなわち、< <= == != > >= ) をサポートする代
         わりに、カーネルレベルの実装をより簡単にして、実質的にそれらの 2 だけ
         を必要とするので、<= と >=  操作だけサポートがあります。さらに、不足
         している操作は、それらの <= と >= フィルタの二次ユーザレベルフィルタ
         リングによってシミュレートすることができます。例えば、!= をシミュレー
         トするために、フィルタ ``bw <= 0xffffffff'' をインストールする必要が
         あり、そして、upcall が受け付けられた後に ``measured_bw !=
         expected_bw'' であるかどうかチェックする必要があります。

     •   帯域幅 upcall メカニズムは、MRT_MFC_BW_UPCALL フラグのために
         setsockopt(MRT_API_CONFIG) によって有効にされます。

     •   帯域幅 upcall フィルタは、それぞれ新しい
         setsockopt(MRT_ADD_BW_UPCALL) と setsockopt(MRT_DEL_BW_UPCALL) (もち
         ろん、適切な struct bw_upcall 引数で) によって追加されるか/削除されま
         す。

     アプリケーション観点から、開発者は、次のことについて知る必要があります:

     /*
      * 測定される帯域幅がスレッシュホールドを越えているかまたは下回るなら、
      * upcall をインストールするか、または配信するるための構造体。
      *
      * ユーザプログラム (例えば、デーモン) は、いくつかのデータフローに
      * よって使用される帯域幅がいつ、スレッシュホールドが越えているか
      * または下回るかを知る必要があるかもしれません。このインタフェースは、
      * ユーザランドが (バイト単位、およびパケット単位で) スレッシュホールド
      * と測定される間隔を指定できるようにします。フローは、同じ発信元 (始点)
      * と宛先 (終点) IP アドレスがあるすべてのパケットです。
      * 現在のところ、コードは、マルチキャストの宛先 (終点) に使用される
      * だけですが、ユニキャストの使用を防ぐものはありません。
      *
      * 測定される間隔は、いくらかの Tmin (現在 3 秒) より短いはずがありません。
      * スレッシュホールドは、per_interval のパケット単位およびバイト単位で
      * 設定されます。
      *
      * 測定は、次の通り動作します:
      *
      * >= 測定値のために:
      * 最初のパケットは、測定される間隔の始まりを示します。間隔の間、私たちは、
      * パケットとバイトを数えます、そして、スレッシュホールドが渡されたとき、
      * 私たちは、upcall を配信し、終わります。間隔の終わりの後の最初のパケット
      * は、カウントをリセットして、測定を再開します。
      *
      * <= 測定値のために:
      * 私たちは、間隔の終わりで発火するようにタイマを始動し、それぞれの着信
      * パケットに関して、パケットとバイトを数えます。タイマが発火するとき、
      * 私たちは、スレッシュホールドと値を比べて、下回っているなら upcall
      * をスケジュールし、(タイマを再スケジュールしカウンタを 0 にして)
      * 測定を再開します。
      */

     struct bw_data {
             struct timeval  b_time;
             uint64_t        b_packets;
             uint64_t        b_bytes;
     };

     struct bw_upcall {
             struct in_addr  bu_src;         /* ソース (始点) アドレス    */
             struct in_addr  bu_dst;         /* 宛先 (終点) アドレス      */
             uint32_t        bu_flags;       /* その他のフラグ (下記参照) */
     #define BW_UPCALL_UNIT_PACKETS (1 << 0) /* (パケット単位の)
                                                スレッシュホールド        */
     #define BW_UPCALL_UNIT_BYTES   (1 << 1) /* (バイト単位の)
                                                スレッシュホールド        */
     #define BW_UPCALL_GEQ          (1 << 2) /* bw >= スレッシュホールド
                                                なら, upcall              */
     #define BW_UPCALL_LEQ          (1 << 3) /* bw <= スレッシュホールド
                                                なら, upcall              */
     #define BW_UPCALL_DELETE_ALL   (1 << 4) /* s,d のための upcall
                                                をすてべ削除 */
             struct bw_data  bu_threshold;   /* bw スレッシュホールド     */
             struct bw_data  bu_measured;    /* 測定される bw             */
     };

     /* 一緒に配送する upcall の最大数 */
     #define BW_UPCALLS_MAX                          128
     /* 帯域幅測定のための最小スレッシュホールド時間の間隔 */
     #define BW_UPCALL_THRESHOLD_INTERVAL_MIN_SEC    3
     #define BW_UPCALL_THRESHOLD_INTERVAL_MIN_USEC   0

     bw_upcall 構造体は、setsockopt(MRT_ADD_BW_UPCALL) と
     setsockopt(MRT_DEL_BW_UPCALL) への引数として使用されます。各
     setsockopt(MRT_ADD_BW_UPCALL) は、bw_upcall 引数で送信元 (始点) と宛先
     (終点) アドレスのためにカーネルにフィルタをインストールし、そして、その
     フィルタは、次の疑似アルゴリズムに従って upcall をトリガします:

      if (bw_upcall_oper IS ">=") {
         if (((bw_upcall_unit & PACKETS == PACKETS) &&
              (measured_packets >= threshold_packets)) ||
             ((bw_upcall_unit & BYTES == BYTES) &&
              (measured_bytes >= threshold_bytes)))
            SEND_UPCALL("measured bandwidth is >= threshold");
       }
       if (bw_upcall_oper IS "<=" && measured_interval >= threshold_interval) {
         if (((bw_upcall_unit & PACKETS == PACKETS) &&
              (measured_packets <= threshold_packets)) ||
             ((bw_upcall_unit & BYTES == BYTES) &&
              (measured_bytes <= threshold_bytes)))
            SEND_UPCALL("measured bandwidth is <= threshold");
       }

     同じ bw_upcall では、BYTE と PACKET の両方でユニットを指定することができ
     ます。しかしながら、GEQ と LEQ フラグは、互いに排他的です。

     基本的に、upcall は、測定される帯域幅が (指定された測定間隔中に) スレッ
     シュホールド帯域幅より >= か <= なら、配信されます。実際的な理由で、測定
     する間隔の最も小さい値は、3 秒です。より小さい値が許可されるなら、帯域幅
     見積りがそれほど正確でないし、潜在的に生成された upcall の大変高い頻度
     は、あまりに多くのオーバヘッドを持ち込むかもしれません。>= 操作のために、
     答えは、threshold_interval の終わりまでに知っているかもしれません、した
     がって、upcall は、より早く配信されるかもしれません。しかしながら、<= 操
     作のために、スレッシュホールドの間隔が答えを知るための期限が切れるまで、
     私たちは、待たなければなりません。

     使用例:

     struct bw_upcall bw_upcall;
     /* すべての bw_upcall フィールドを適切に割り当てます */
     memset(&bw_upcall, 0, sizeof(bw_upcall));
     memcpy(&bw_upcall.bu_src, &source, sizeof(bw_upcall.bu_src));
     memcpy(&bw_upcall.bu_dst, &group, sizeof(bw_upcall.bu_dst));
     bw_upcall.bu_threshold.b_data = threshold_interval;
     bw_upcall.bu_threshold.b_packets = threshold_packets;
     bw_upcall.bu_threshold.b_bytes = threshold_bytes;
     if (is_threshold_in_packets)
         bw_upcall.bu_flags |= BW_UPCALL_UNIT_PACKETS;
     if (is_threshold_in_bytes)
         bw_upcall.bu_flags |= BW_UPCALL_UNIT_BYTES;
     do {
         if (is_geq_upcall) {
             bw_upcall.bu_flags |= BW_UPCALL_GEQ;
             break;
         }
         if (is_leq_upcall) {
             bw_upcall.bu_flags |= BW_UPCALL_LEQ;
             break;
         }
         return (ERROR);
     } while (0);
     setsockopt(mrouter_s4, IPPROTO_IP, MRT_ADD_BW_UPCALL,
               (void *)&bw_upcall, sizeof(bw_upcall));

     単一のフィルタを削除するために、MRT_DEL_BW_UPCALL を使用し、bw_upcall の
     フィールドは、MRT_ADD_BW_UPCALL が呼び出された時と全く同じに設定しなけれ
     ばなりません。

     与えられた (S,G) のためのすべての帯域幅を削除するために、struct bw_upcall
     中の bu_srcbu_dst フィールドのみを設定する必要があり、つぎにフィール
     ド bw_upcall.bu_flags 内の BW_UPCALL_DELETE_ALL フラグだけを設定します。

     帯域幅 upcall は、新しい upcall メッセージでそれらを集めることによって受
     け付けます:

     #define IGMPMSG_BW_UPCALL  4  /* BW モニタリング upcall */

     このメッセージは、struct bw_upcall (BW_UPCALLS_MAX = 128 までの) 要素の配
     列です。128 保留中 (pending) の upcall があるとき、または前の upcall 以来
     1 秒の期限が切れているとき (どれが最初になっても)、upcall は、配信されま
     す。struct upcall 要素では、bu_measured フィールドは、特定の測定値を示す
     ために書き込まれます。しかしながら、特定の間隔が測定される方法のために、
     ユーザは、bu_measured.b_time がどのように使用されているか注意するべきで
     す。例えば、フィルタが upcall をトリガするためにインストールされ、パケッ
     トの数が  >= 1 であるなら、bu_measured は、>= フィルタのための測定される
     間隔が転送されたパケットによって ``時間を計る'' ので、最初のものの後の
     upcall で 0 の値であるかもしれません。したがって、転送されたデータの帯域
     幅の正確な値を測定するのにこの upcall メカニズムを使用するべきではありま
     せん。正確な帯域幅を測定するために、ユーザは、ioctl(SIOCGETSGCNT) メカニ
     ズム (プログラミングガイドセクションを参照) で転送されたパケット統計値を
     得る必要があるでしょう。

     フィルタのための upcall は、特定のフィルタが削除されるまで、配信されます
     が、bu_threshold.b_time 毎に一度より頻繁ではないことに注意してください。
     例えば、フィルタがシグナルを配信するために指定され、bw >= 1 パケットであ
     るなら、最初のパケットは、シグナルのトリガとなりますが、次の upcall は、
     前の upcall の後に bu_threshold.b_time より早くトリガされません。

関連項目
     getsockopt(2), recvfrom(2), recvmsg(2), setsockopt(2), socket(2),
     sourcefilter(3), altq(4), dummynet(4), gif(4), gre(4), icmp6(4), igmp(4),
     inet(4), inet6(4), intro(4), ip(4), ip6(4), mld(4), pim(4)

歴史
     Distance Vector Multicast Routing Protocol (DVMRP) は、最初に開発されたマ
     ルチキャスト経路制御プロトコルでした。その後に、Multicast Extensions to
     OSPF (MOSPF) のような他のプロトコルと Core Based Trees (CBT) が同様に開発
     されました。現在、自律システム境界のルータは、Border Gateway Protocol
     (BGP) を通してピア (相手側) とマルチキャスト経路を交換できます。他の多く
     の経路制御プロトコルは、PIM-SM と PIM-DM で使用するためにマルチキャスト経
     路を再配信することができます。

作者
     元のマルチキャストコードは、David Waitzman (BBN Labs) によって書かれ、後
     で次の個人によって修正されました: Steve Deering (Stanford), Mark J.
     Steiglitz (Stanford), Van Jacobson (LBL), Ajit Thyagarajan (PARC), Bill
     Fenner (PARC)。IPv6 マルチキャストサポートは、KAME プロジェクト
     (http://www.kame.net) によって実装され、IPv4 マルチキャストコードに基づい
     ています。高度なマルチキャスト API とマルチキャスト帯域幅モニタリングは、
     Chris Brown (NextHop) と共同して Pavlin Radoslavov (ICSI) によって実装さ
     れました。

     このマニュアルページは、Pavlin Radoslavov (ICSI) によって書かれました。

FreeBSD 12.2                     May 27, 2009                     FreeBSD 12.2

Table of Contents

FreeBSD マニュアル検索