0

そのため、ルーティング エントリから可能な限り一致するインターフェイスを返そうとしています。しかし、それは私が望むように正確に機能しているわけではありません。6 つの値のうち 5 つが本来あるべき方法で返されましたが、アルゴリズムが機能しないルーティング テーブルに 100 万のエントリがあると確信しています。この問題を解決するために二分探索を使用しています。しかし、たとえば、返したいインターフェイスの ipaddress が、引数として渡している ipaddress よりも小さい場合、二分探索アルゴリズムは機能しません。構造は次のようになります。

struct routeEntry_t
{
    uint32_t ipAddr;
    uint32_t netMask;
    int interface;
};
routeEntry_t routing_table[100000];

ルーティング テーブルが次のようになっているとします。

{ 0x00000000, 0x00000000, 1 }, // [0]

{ 0x0A000000, 0xFF000000, 2 }, // [1]

{ 0x0A010000, 0xFFFF0000, 10 }, // [2]

{ 0x0D010100, 0xFFFFFF00, 4 }, // [3]

{ 0x0B100000, 0xFFFF0000, 3 }, // [4]

{ 0x0A010101, 0xFFFFFFFF, 5 }, // [5]

入力/出力の例:

  1. 通常の検索

入力: 0x0D010101 出力: 4 (エントリ [3])

入力: 0x0B100505 出力: 3 (エントリ [4])

  1. 任意のアドレスを見つけるには、デフォルト インターフェイスに移動する必要があります。

入力: 0x0F0F0F0F 出力: 1 (エントリ [0])

  1. 複数のエントリに一致するアドレスを見つけるには、最も一致するものを取得します。

入力: 0x0A010200 出力: 10 (エントリ [2])

入力: 0x0A050001 出力: 2 (エントリ [1])

入力: 0x0A010101 出力: 5 (エントリ [5])

しかし、私の出力は 2, 3, 1, 10, 1, 5 のように見えます。私がどこで間違っているのか説明していただけますか?どんな助けでも素晴らしいでしょう。前もって感謝します。ただし、これは私のアルゴリズムがどのように見えるかです (エントリがソートされていると仮定します):

int interface(uint32_t ipAddr)

{ int 開始 = 0;

int end = SIZE-1;

int mid = 0;

vector<int> matched_entries;

vector<int>::iterator it;

matched_entries.reserve(SIZE);

it = matched_entries.begin();


if (start > end)
    return -1;

while (start <= end)
{
    mid = start + ((end-start)/2);

    if (routing_table[mid].ipAddr == ipAddr)
        return routing_table[mid].interface;
    else if (routing_table[mid].ipAddr > ipAddr)
    {
        uint32_t result = routing_table[mid].netMask & ipAddr;
        if (result == routing_table[mid].ipAddr)
        {
            matched_entries.push_back(mid);
        }
        end = mid-1;
    }
    else
    {
        uint32_t result = routing_table[mid].netMask & ipAddr;
        if (result == routing_table[mid].ipAddr)
        {
            matched_entries.insert(it,mid);
        }
        start = mid+1;
    }
}


int matched_ip = matched_entries.back();
if (routing_table[matched_ip].netMask & ipAddr)
    return routing_table[matched_ip].interface;
else
    return routing_table[0].interface;  

}

4

2 に答える 2

1

「正しい」インターフェースは、IP アドレスが入力と同じサブネット上にある最も具体的なネットマスクを持つエントリです。

ネットマスクとは何か、どのように機能するかを詳しく見てみましょう。

表記

通常、ネットマスクはドット付き 10 進数または 16 進数表記で記述されますが、IPv4 ネットマスクのバイナリ表現は常に 32 ビットです。つまり、IP アドレスとまったく同じ長さです。ネットマスクは常に 0 個以上のビットで始まり、32 ビット長になるまでビット1が埋め込まれます。0ネットマスクが IP アドレスに適用されると、ビットごとに「整列」します。1ネットマスクのビットに対応する IP アドレスのビットによって、IP アドレスのネットワーク番号が決まります。0ネットマスクのビットに対応するものによって、デバイス番号が決まります。

目的

ネットマスクは、アドレス空間をより小さなサブネットに分割するために使用されます。同じサブネット上のデバイスは、TCP/IP プロトコル スタックを使用して直接相互に通信できます。異なるサブネット上のデバイスは、1 つ以上のルーターを使用してデバイス間でデータを転送する必要があります。ネットマスクはサブネットを互いに分離するため、デバイスの論理グループを作成する自然な方法です。たとえば、企業内の各場所または部門が独自のサブネットを持っている場合や、各タイプのデバイス (プリンター、PCなど) が独自のサブネットを持っている場合があります。

ネットマスクの例:

255.255.255.128FF FF FF 101111 1111 1111 1111 1111 1111 1000 0000
このネットマスクは、IP アドレスの最初の 25 ビットがネットワーク番号を決定することを指定します。最後の 7 ビットがデバイス番号を決定します。これは、それぞれ 2 7 = 128 のデバイスを持つ 2 25の異なるサブネットが存在できることを意味します。*

255.255.255.0     → FF FF FF 00→このネットマスクは、それぞれが 2 8 = 256 個の個別のアドレスを持つ 2 24のサブネット1111 1111 1111 1111 1111 1111 0000 0000
を持つアドレス空間を指定します。これは非常に一般的な構成であり、単に「クラス C」ネットワークとして知られているほど一般的です。

255.255.192.0     → FF FF FC 001111 1111 1111 1111 1111 1100 0000 0000
このネットマスクは、それぞれ 2 10 = 1024 のアドレスを持つ 2 22のサブネットを指定します。各部門に数百のデバイスがあり、論理的にグループ化する必要がある大企業内で使用される場合があります。

無効なネットマスク (内部ゼロに注意):
255.128.255.0     → FF 80 FF 001111 1111 1000 0000 1111 1111 0000 0000

計算

以下に、ネットマスクが IP アドレスのネットワーク番号とデバイス番号を決定する方法を示すいくつかの例を示します。

  IP アドレス: 192.168.0.1C0 A8 00 01
  ネットマスク: 255.255.255.0FF FF FF 00
このデバイスはサブネット 192.168.0.0 にあります。IP アドレスが 192.168.0 の形式である他のデバイスと直接通信できます。バツ

  IP アドレス: 192.168.0.1     → C0 A8 00 01
  IP アドレス: 192.168.0.130C0 A8 00 82
  ネットマスク: 255.255.255.128FF FF FF 80
これら 2 つのデバイスは異なるサブネット上にあり、ルーターなしでは相互に通信できません。

  IP アドレス: 10.10.195.270A 0A C3 1B
  ネットマスク: 255.255.0.0→これは、10.10.0.0 ネットワーク上の 2 16 個FF FF 00 00
のアドレス と通信できる「クラス B」ネットワーク上のアドレスです。

1ネットマスクの先頭のビット数が多いほど、より具体的であることがわかります。つまり、より多くの1ビットは、より少ないデバイスで構成される「より小さな」サブネットを作成します。

すべてを一緒に入れて

あなたのようなルーティング テーブルには、ネットマスク、IP アドレス、およびインターフェイスのトリプレットが含まれています。(「コスト」メトリックも含まれる場合があります。これは、特定の宛先にデータをルーティングできる場合、いくつかのインターフェイスのうちどれを使用するのが「最も安い」かを示します。たとえば、高価な専用回線を使用する場合があります。)

パケットをルーティングするために、ルーターは、パケットの宛先に最も具体的に一致するインターフェイスを見つけます。の場合、アドレスaddrとネットマスクを含むエントリmaskは宛先 IP アドレスと一致します。ここで、はビット演算を示します。英語では、両方のアドレスに共通する最小のサブネットが必要です。dest(addr & netmask) == (dest & netmask)&AND

なんで?あなたと同僚が、企業の有線ネットワークと無線ネットワークの両方を持つ巨大なチェーンの一部であるホテルにいるとします。会社の VPN にも接続しました。ルーティング テーブルは次のようになります。

宛先ネットマスク インターフェイスに関する注意事項
 ----------- -------- --------- -----
 会社の電子メール FFFFFF00 VPN すべての会社のトラフィックを VPN 経由でルーティングする
 有線ネットワーク FFFF0000 世界中の他のホテル アドレスへの有線トラフィック
 デフォルト 00000000 ワイヤレス その他すべてのトラフィック

最も具体的なルールは、アドレスが有線ネットワークにも一致する場合でも、VPN を介して会社の電子メールを安全にルーティングします. ホテル チェーン内の他のアドレスへのすべてのトラフィックは、有線ネットワークを介してルーティングされます。そして、それ以外はすべてワイヤレス ネットワーク経由で送信されます。



*実際には、すべてのサブネットで、最も高いアドレスと最も低いアドレスの 2 つが予約されています。すべて 1 のアドレスはブロードキャストアドレスです。このアドレスは、サブネット上のすべてのデバイスにデータを送信します。また、すべてゼロのアドレスは、デバイスがまだ独自の IP アドレスを持っていない場合に、デバイスが自身を参照するために使用されます。簡単にするためにそれらを無視しました。


したがって、アルゴリズムは次のようになります。

initialize:
  Sort routing table by netmask from most-specific to least specific.
  Within each netmask, sort by IP address.

search:
  foreach netmask {
    Search IP addresses for (input & netmask) == (IP address & netmask)
    Return corresponding interface if found
  }
  Return default interface
于 2012-04-01T17:58:53.290 に答える
0

わかりましたので、これが私の構造とアルゴリズムが現在どのように見えるかです。それは機能し、私が望む結果をもたらしますが、ネットマスク内で IP アドレスをソートする方法はまだわかりません。STL ソートを使用してネットマスクをソートしました。

struct routeEntry_t

{
uint32_t ipAddr;
uint32_t netMask;
int interface;

bool operator<(const routeEntry_t& lhs) const
{
    return lhs.netMask < netMask;
}
};

const int SIZE = 6;

routeEntry_t routing_table[SIZE];

void sorting()
{
//using STL sort from lib: algorithm
sort(routing_table, routing_table+SIZE);
}

int interface(uint32_t ipAddr)
{
for (int i = 0; i < SIZE; ++i)
{
    if ((routing_table[i].ipAddr & routing_table[i].netMask) == (ipAddr &   routing_table[i].netMask))
        return routing_table[i].interface;
}
return routing_table[SIZE-1].interface;
}
于 2012-04-02T07:20:09.090 に答える