Подтвердить что ты не робот

Передача UDP-пакетов с использованием нескольких сетевых адаптеров

Я создаю встроенную систему для контроллера камеры в Linux (не в режиме реального времени). У меня проблемы с сетью, чтобы делать то, что я хочу. Система имеет 3 сетевых адаптера, 1 100base-T и 2 гигабитных порта. Я подключаю более медленный к камере (все, что он поддерживает), а более быстрые - это соединения точка-точка с другими машинами. То, что я пытаюсь сделать, это получить изображение с камеры, сделать небольшую обработку, а затем передать ее с использованием UDP для каждой из других сетевых адаптеров.

Вот моя конфигурация сети:

eth0: addr: 192.168.1.200 Bcast 192.168.1.255 Маска: 255.255.255.0 (это 100base-t)
eth1: addr: 192.168.2.100 Bcast 192.168.2.255 Маска: 255.255.255.0
eth2: addr: 192.168.3.100 Bcast 192.168.3.255 Маска: 255.255.255.0

Изображение выходит из eth0 в проприетарном протоколе, так что это сырой сокет. Я могу транслировать его на eth1 или eth2 просто отлично. Но когда я пытаюсь транслировать его на оба, один за другим, я получаю много сетевых иконов и ошибок на eth0.

Я инициализирую сокеты UDP следующим образом:

sock2=socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP); // Or sock3
sa.sin_family=AF_INET;
sa.sin_port=htons(8000);
inet_aton("192.168.2.255",&sa.sin_addr); // Or 192.168.3.255
setsockopt(sock2, SOL_SOCKET, SO_BROADCAST, &broadcast, sizeof(broadcast));
bind(sock2,(sockaddr*)&sa,sizeof(sa));

sendto(sock2,&data,sizeof(data),0,(sockaddr*)&sa,sizeof(sa)); // sizeof(data)<1100 bytes

Я делаю это для каждого сокета отдельно и вызываю sendto отдельно. Когда я делаю то или другое, все в порядке. Когда я пытаюсь отправить на обоих, eth0 начинает получать плохие пакеты.

Любые идеи о том, почему это происходит? Это ошибка конфигурации, есть ли лучший способ сделать это?

EDIT: Спасибо за всю помощь, я кое-что пробовал и смотрел на это больше. Судя по всему, вопрос не является широковещательным. Я заменил широковещательный код на одноадресную команду, и он имеет такое же поведение. Я думаю, что я лучше понимаю поведение, но не как это исправить.

Вот что происходит. На eth0 я должен получить изображение каждые 50 мс. Когда я отправляю изображение на eth1 (или 2), для отправки изображения требуется около 1,5 мс. Когда я пытаюсь отправить на eth1 и eth2 одновременно, это занимает около 45 мс, иногда перепрыгивая на 90 мс. Когда это выходит за рамки окна 50 мс, буфера eth0 начинает строить. Я теряю пакеты, когда буфер заполняется, конечно.

Итак, мой пересмотренный вопрос. Почему он должен идти от 1,5 мс до 45 мс, просто перейдя от одного порта Ethernet к двум?

Вот мой код инициализации:

sock[i]=socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP);
sa[i].sin_family=AF_INET;
sa[i].sin_port=htons(8000);
inet_aton(ip,&sa[i].sin_addr);

//If Broadcasting
char buffer[]="eth1" // or eth2
setsockopt(sock[i],SOL_SOCKET,SO_BINDTODEVICE,buffer,5);
int b=1;
setsockopt(sock[i],SOL_SOCKET,SO_BROADCAST,&b,sizeof(b));

Вот мой код отправки:

for(i=0;i<65;i++) {
  sendto(sock[0],&data[i],sizeof(data),0,sa[0],sizeof(sa[0]));
  sendto(sock[1],&data[i],sizeof(data),0,sa[1],sizeof(sa[1]));
}

Это довольно простой.

Любые идеи? Спасибо за вашу большую помощь!

Пол

4b9b3361

Ответ 1

Это было долгое время, но я нашел ответ на свой вопрос, поэтому я подумал, что поставлю его здесь, если кто-нибудь еще его найдет.

Два порта Gigabit Ethernet были на самом деле на мосту PCI с шины PCI-express. Шина PCI-Express была внутренней для материнской платы, но это была шина PCI, идущая к картам. Мост и автобус не имели достаточной пропускной способности, чтобы действительно быстро отправлять изображения. С включенным только одним сетевым адаптером данные были отправлены в буфер, и это выглядело очень быстро для меня, но потребовалось намного больше времени, чтобы фактически пройти через автобус, вне карты и на провод. Второй сетевой адаптер был медленнее, потому что буфер был заполнен. Хотя изменение размера буфера маскировало проблему, оно фактически не отправляло данные быстрее, и я все еще получал упавшие пакеты на третьей сетевой карте.

В конце концов, плата 100Base-T была фактически построена на материнской плате, поэтому имела более быструю шину, что привело к общей пропускной способности по сравнению с гигабитными портами. Путем переключения камеры на гигабитную линию и одну из Гигабитные линии к линии 100Base-T, которые я смог удовлетворить требованиям.

Странно.

Ответ 2

Может быть, ваш UDP-стек исчерпан?

(1) Проверьте /proc/sys/net/ipv4/udp_mem (подробнее см. man 7 udp). Убедитесь, что первое число не менее 8 раз больше размера изображения. Это устанавливает память для всех сокетов UDP в системе.

(2) Убедитесь, что буфера сокета для отправки сокета достаточно велики. Используйте setsockopt(sock2, SOL_SOCKET, SO_SNDBUF, image_size*2), чтобы установить буфер отправки в обоих сокетах. Возможно, вам нужно увеличить максимальное допустимое значение в /proc/sys/net/core/wmem_max. Подробнее см. man 7 socket.

(3) Вы также можете увеличить буфер RX для приема сокета. Запишите большое число в .../rmem_max, затем используйте SO_RCVBUF, чтобы увеличить размер принимаемого буфера.

Ответ 3

Обходной путь до тех пор, пока эта проблема не будет решена, может быть создана для создания eth1 + eth2 и отправки пакета на этот мост. Таким образом, он только отображается в память ядра один раз, а не дважды на изображение.