LINUX.ORG.RU

Непонятная фигня с подсчетом времени

 , ,


0

2

Суть проблемы : Я сделал сетевой эмулятор на FPGA который позволяет имитировать разные проблемы сети - задержку, уменьшение Daterate, потерю пакетов и т.д. Мой эмулятор может имитировать задержку прохождения пакетов в диапозоне 1 нс до 4 сек. Что бы проверить, была написана программа на с++ которая работает с сырыми сокетами. Я формирую пакеты вручную и отправляю их, а потом жду когда они придут обратно и замерю время. И вот тут начинается какая то непонятная фигня. Иногда показывает правильное время - более менее правдоподобное 840 мс, а иногда 1421165742397 мс. Что конечно не может быть в принципе.

Для замера времени использую функцию :

long mtime() {
  struct timeval t;
  gettimeofday(&t, NULL);
  long mt = (long)t.tv_sec * 1000 + t.tv_usec / 1000;
  return mt;
}

и в коде после отслыки

long t;
if ( sendto(sock[0], sendbuf, tx_len, 0, (struct sockaddr*)&socket_address, sizeof(struct sockaddr_ll)) )
    t = mtime();
и при приеме :
numbytes = recvfrom(sock[1], buf, BUF_SIZE, 0, NULL, NULL);
if ( eh_rec->ether_dhost == MY_MAC )
    t = mtime() - t;

printf ("Delay is %ld milliseconds.\n",t);
Где может быть проблема ?

OS: Ubuntu 14.04.1 LTS Desktop (64-bit)



Последнее исправление: guskov_roman (всего исправлений: 7)

Так, быстро оберни свой код в тег [code=c][/code]

Waterlaz ★★★★★
()

Архитектура какая? На i386 long 32 бита, есличо.

Ну и смотри что тебе приходит, потому что если eh_rec->ether_dhost != MY_MAC в t будет абсолютное время.

slovazap ★★★★★
()
Последнее исправление: slovazap (всего исправлений: 1)
Ответ на: комментарий от slovazap

Архитектура какая? На i386 long 32 бита, есличо

Поправил пост.

потому что если eh_rec->ether_dhost != MY_MAC в t будет абсолютное >время.

eh_rec->ether_dhost != MY_MAC не может быть в принципе, это исключенно, отдельная сетевушка соеденная напрямую только с FPGA, и больше ни с чем

guskov_roman
() автор топика
Ответ на: комментарий от Waterlaz

Срабатывает, уже проверял. И вообще все возможные проблемы в стиле «А стёкла протирал? А колёса пинал? - ну тогда тогда я даже не знаю» уже проверил.

Проблема еще и в том что дебажить на целевой машине не могу, там у меня нет рута.

Но чую ошибка настолько тупая, что сходу и не поймешь..

guskov_roman
() автор топика
Ответ на: комментарий от guskov_roman

Вот именно, что на С, потому что за такие касты в С++ по рукам бьют. И я бы в твоём случае поменял long на long long в расчетах.

asaw ★★★★★
()
Ответ на: комментарий от guskov_roman

не может быть в принципе, это исключенно

Наивно. А ничего что прошивка может быть кривая, пакеты могут биться по разным причинам? Делов-то, собственно - добавь пару printf чтобы печатать абсолютное значение времени и eh_rec->ether_dhost, root для этого не нужен. Ну и в любом случае long я бы поменял на int64_t.

slovazap ★★★★★
()
Ответ на: комментарий от beastie

При любом раскладе этот код неверный.

Поясните пожалуйста, в чем код неверный ? Данные отправляються, обратно получаються, в wireshark все проконтролировал. Время задержки только не пойми как считаеться.. Я, ради теста, ставил задержку на 3 секунды, все нормально задерживаеться.

И ещё — размер long (в mtime) — может быть 4, а может быть и 8 битов.

Что надо сделать, что бы он был строго 8 бит ?

guskov_roman
() автор топика
Ответ на: комментарий от asaw

потому что за такие касты в С++ по рукам бьют.

а в C — по голове. Канделябром.

emulek
()
Ответ на: комментарий от guskov_roman

Что надо сделать, что бы он был строго 8 бит ?

очевидно скастовать в int64_t. (Но НЕ НАОБОРОТ!)

emulek
()
Ответ на: комментарий от guskov_roman

Поясните пожалуйста, в чем код неверный ?

Тем, что в t может быть что угодно. Если пакет по каким либо причинам не ушёл — там будет что-то случайное. Что, возможно, мы и наблюдаем. Лучше инициализировать, хотя бы как

long long t = 0

Что надо сделать, что бы он был строго 8 бит ?

long long или uint64_t.

PS: хотя, в частности, на OpenBSD этого уже хватать не будет, там tv_sec и tv_useс уже 64 бита.

beastie ★★★★★
()
Последнее исправление: beastie (всего исправлений: 2)
Ответ на: комментарий от slovazap

Наивно.

Очевидно я уже проверил, раз пишу что нет.

А ничего что прошивка может быть кривая, пакеты могут биться по разным причинам?

у меня не могут, приходят как надо.

А ничего что прошивка может быть кривая

Прошивка чего ? Я делаю микрочип, а FPGA - плата для прототипов. Там нет никакой сторонней прошивки, только моя - полная реализация сетевой карты с разными дополнительными возможностями.

Делов-то, собственно - добавь пару printf

Уже. Все равно какая то фигня получается.

guskov_roman
() автор топика
Ответ на: комментарий от beastie

long long или uint64_t.

Хм, а это идея. Мне говорил колега, что лучше стандартные типы вроде long не использовать. Надо будет завтра потестить.

PS: хотя, в частности, на OpenBSD этого уже хватать не будет, там tv_sec и tv_useс уже 64 бита.

Это не важно, я разрабатываю железо, а не софт. Мне надо для верификации посчитать, что мой чип все правильно задерживает. Кстати, а если вообще смысл делать задержку передачи данных на 1 Наносекунду ? Ethernet все равно ведь не real-time.

guskov_roman
() автор топика
Ответ на: комментарий от elijah_sd

А что gettimeofday возвращает проверял?

Да вроде все правильно возращает.. Но не уверен :-) Я дома уже просто, завтра проверю еще раз.

guskov_roman
() автор топика
t = mtime() - t;

Ты, кстати, в курсе, что 1421165742397 - количество миллисекунд, прошедшее с 1 января 1970-го года до примерно сегодняшнего дня? Думай над вышеприведенной цитатой и проверяй свой макаронный код в общем.

asaw ★★★★★
()
Ответ на: комментарий от guskov_roman

Это не важно, я разрабатываю железо, а не софт.

Это так, JFYI. Через 23 года уже не влезет. А так, как ты разрабатываешь железо, может быть вполне актуально задуматься об этом уже сейчас.

beastie ★★★★★
()
Ответ на: комментарий от guskov_roman

Это не важно, я разрабатываю железо, а не софт. Мне надо для верификации посчитать, что мой чип все правильно задерживает.

С таким подходом к программированию тебе надежнее для этих целей соорудить железку))

asaw ★★★★★
()
Ответ на: комментарий от asaw

Ты, кстати, в курсе, что 1421165742397 - количество миллисекунд, прошедшее с 1 января 1970-го года

Ну теперь в курсе, опупеть какой ты дотошный :-)

У меня появились нехорошие подозрения. Кажется, я начинаю догадываться в чем проблема. Но в любом случае я их проверить могу только завтра.

А сегодня, как говорят у нас на немчине - фаерабенд.

guskov_roman
() автор топика
Ответ на: комментарий от guskov_roman

У меня появились нехорошие подозрения. Кажется, я начинаю догадываться в чем проблема.

Вообще-то после написанного мной ответ должен быть просто очевиден. Поэтому я и сказал про макаронный код: хотя весь ты его не привел, но очевидно что он именно такой.

asaw ★★★★★
()
Последнее исправление: asaw (всего исправлений: 1)
Ответ на: комментарий от asaw

Поэтому я и сказал про макаронный код, хотя весь ты его не привел

Код тут не при чем, он так - на коленке написан. Важно не то как код работает, а что железо, которое я сделал - все коректно отрабатывает. Завтра проведу еще один тест и напишу. Я уже почти уверен, что нашел ошибку.

guskov_roman
() автор топика
Ответ на: комментарий от guskov_roman

только моя - полная реализация сетевой карты с разными дополнительными возможностями

Я про неё и пишу.

Уже. Все равно какая то фигня получается.

Описать ситуацию как «какая-то фигня» может только первоклассник. А вы сразу должны понять, приходят ли к вам неправильные пакеты или у вас ошибка в обработке времени.

slovazap ★★★★★
()

Я бы сделал так:


void storeTime(struct timeval* t);
long getDelta(const struct timeval& s, const struct timeval& end);

struct timeval start, end;
storeTime(&start);

{
   // sendto
}

storeTime(&end);
long delta = getDelta(start, end);

andreyu ★★★★★
()
Ответ на: комментарий от beastie

И ещё — размер long (в mtime) — может быть 4, а может быть и 8 битов.

Тогда уже байтов. Ну или 32 или 64 бита.

andreyu ★★★★★
()
Ответ на: комментарий от guskov_roman

Мне говорил колега, что лучше стандартные типы вроде long не использовать

правильно говорил, их размер не определён. Если ты работаешь напрямую с железом, юзай uint*_t.

emulek
()

Есть подозрение что сценарий такой

1. Отправили пакет №1 t = mtime();
2. Отправили пакет №2 t = mtime();
3. Получили пакет №1 t = mtime() - t; (время похоже на правду 840мс)
4. Получили пакет №2 t = mtime() - t; (now - 840ms = 1421165742397 мс)

zaz ★★★★
()

не стоило изобретать велосипед с mtime() :-) в родной документации libc рассказано как правильно сравнивать(вычитать) timeval: http://www.gnu.org/software/libc/manual/html_node/Elapsed-Time.html

если остальная ваша копипаста соответсвует тому что у вас в коде, то ещё вы пакет отсылаете неправильно :-) у вас t=mtime() всегда, даже когда ничего не улетело в сеть. И принимаете в том-же стиле.

То есть замерено время между __попытками__ приёма/передачи, отсчёты близкие и иногда (на границах секунд) происходит сбой - время отправления получается больше чем время получения «mtime() - t» отрицательный. Неучтён перенос (carry) в функции mtime

MKuznetsov ★★★★★
()
Ответ на: комментарий от asaw

Поэтому я и сказал про макаронный код: хотя весь ты его не привел, но очевидно что он именно такой.

Там кода минимум - строчек 100, одна функция main. В ней сформирован пакет, отправлен, подождать когда придет обратно, посчитать время, выйти из программы. Пара If, пара циклов. Программа предельно примитивная.

Программа запускаеться несколько раз через скрипт баша.

Проблема была в том, что утром тестировали потерю пакетов. Чип терял рандомно каждые пять пакетов из 100. Коллега поленился отключить и заново синтезировать чип, и ушел на обед. А после обеда забыл, а мне сказал что сделал.

Сделал синтез заново, теперь все отлично считает.

Тему можно закрывать.

guskov_roman
() автор топика
Ответ на: комментарий от guskov_roman

Там кода минимум - строчек 100

И ты вот эти 100 строчек умудрился написать так, что сам без помощи ЛОРа не смог понять как они работают. С чем тебя и поздравляю)

asaw ★★★★★
()
Ответ на: комментарий от guskov_roman

Очевидно я уже проверил, раз пишу что нет.

Очевидно, надо было бы уже давно поменять код, чтобы ничего проверять не надо было, а видно было по работе. Ты хотя бы printf поставил бы, блин. Иначе, тебе в этой теме будут лишь с дерьмом мешать, вполне справедливо, между прочим.

Waterlaz ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.