LINUX.ORG.RU

Сообщения so_much_light

 

[ARM] clock_nanosleep и RT_PREEMPT

Форум — Development

есть одна железка на АРМ с RT_PREEMPT ядром. задача простая: через ethernet отправлять пакеты с заданным интервалом - 250мкс. проблема в том, что интервал плавает. вот тестовый код:

#define _POSIX_C_SOURCE  200112L

#include <stdio.h>
#include <time.h>
#include <sched.h>
#include <stdlib.h>

int main() {
    sched_setscheduler(0, SCHED_FIFO, &(struct sched_param) {
        .sched_priority = sched_get_priority_max(SCHED_FIFO)
    });

    for (int n = 10; n--;) {
        struct timespec a, b;
        clock_gettime(CLOCK_MONOTONIC, &a);

        clock_nanosleep(CLOCK_MONOTONIC, 0, &(struct timespec) {
            .tv_sec  = 0,
            .tv_nsec = 250000
        }, NULL);

        clock_gettime(CLOCK_MONOTONIC, &b);
        printf("%ld\n", b.tv_nsec - a.tv_nsec + (b.tv_sec - a.tv_sec) * 1000000000l);
    }
    return 0;
}
выдает такие результаты:
482984
402445
361446
378612
365238
362738
359113
359113
363654
358821
как видно задержка в некоторых случаях почти двукратная.

cat /proc/timer_list говорит, что используется hi-res timer. на всякий случай полный вывод:

# cat /proc/timer_list
Timer List Version: v0.5
HRTIMER_MAX_CLOCK_BASES: 2
now at 9784755808068 nsecs

cpu: 0
 clock 0:
  .base:       c03fbfa8
  .index:      0
  .resolution: 1 nsecs
  .get_time:   ktime_get_real
  .offset:     1330069279622958539 nsecs
active timers:
 clock 1:
  .base:       c03fbfe0
  .index:      1
  .resolution: 1 nsecs
  .get_time:   ktime_get
  .offset:     0 nsecs
active timers:
 #0: <c03fc550>, tick_sched_timer, S:01
 # expires at 9784760000000-9784760000000 nsecs [in 4191932 to 4191932 nsecs]
 #1: <c0423a10>, sched_rt_period_timer, S:01
 # expires at 9785000000000-9785000000000 nsecs [in 244191932 to 244191932 nsecs]
 #2: <c1c1da98>, hrtimer_wakeup, S:01
 # expires at 9787882326277-9787887326259 nsecs [in 3126518209 to 3131518191 nsecs]
  .expires_next   : 9784760000000 nsecs
  .hres_active    : 1
  .nr_events      : 4303769
  .nr_retries     : 2718
  .nr_hangs       : 0
  .max_hang_time  : 0 nsecs
  .nohz_mode      : 2
  .idle_tick      : 9784730000000 nsecs
  .tick_stopped   : 0
  .idle_jiffies   : 948472
  .idle_calls     : 4027935
  .idle_sleeps    : 3643985
  .idle_entrytime : 9784720504270 nsecs
  .idle_waketime  : 9784735100438 nsecs
  .idle_exittime  : 9784735153646 nsecs
  .idle_sleeptime : 7111169596582 nsecs
  .last_jiffies   : 948472
  .next_jiffies   : 948491
  .idle_expires   : 9784910000000 nsecs
jiffies: 948475


Tick Device: mode:     1
Per CPU device: 0
Clock Event Device: timer0_0
 max_delta_ns:   178956970763
 min_delta_ns:   50000
 mult:           103079215
 shift:          32
 mode:           3
 next_event:     9784760000000 nsecs
 set_next_event: davinci_set_next_event
 set_mode:       davinci_set_mode
 event_handler:  hrtimer_interrupt
тут вроде бы все ок.

подскажите, как приблизиться к заветным 250мкс? куда копать?

 

so_much_light
()

raw socket + vlan header

Форум — Development

надо отправить ethernet кадр с vlan хидером. пакет отправляется, но не могу изменить хидере vlan'a TPid, VID, priority и т.п. как это сделать? код отправки примерно такой:

int s;
s = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
...
struct ifreq ifr;
strncpy(ifr.ifr_name, "eth0", IFNAMSIZ);
ioctl(s, SIOCGIFINDEX, &ifr);
...
struct sockaddr_ll socketAddr;
socketAddr.sll_family   = PF_PACKET;
socketAddr.sll_protocol = htons(ETH_P_ALL);
socketAddr.sll_ifindex  = ifr.ifr_ifindex;
socketAddr.sll_hatype   = ARPHRD_ETHER;
socketAddr.sll_pkttype  = PACKET_OTHERHOST;
socketAddr.sll_halen    = ETH_ALEN;
socketAddr.sll_addr[0]  = dstMac[0];
socketAddr.sll_addr[1]  = dstMac[1];
socketAddr.sll_addr[2]  = dstMac[2];
socketAddr.sll_addr[3]  = dstMac[3];
socketAddr.sll_addr[4]  = dstMac[4];
socketAddr.sll_addr[5]  = dstMac[5];
socketAddr.sll_addr[6]  = 0x00;
socketAddr.sll_addr[7]  = 0x00;
...
struct EthHeader
{
	u_char		dstMac[6];
	u_char		srcMac[6];
	u_int16_t	vlanTpid;
	u_char		vlanUserPriority:3;
	u_char		vlanCfi:1;
	u_int16_t	vlanVid:12;
	u_int16_t	ethertype;
            ...
}__attribute__ ((__packed__));
...
struct EthHeader ethHeader;

memset(ethHeader, 0, sizeof(struct EthHeader));

memcpy(&ethHeader.dstMac,dstMac,ETH_ALEN);
memcpy(&ethHeader.srcMac,srcMac,ETH_ALEN);
ethHeader.vlanTpid = htons(0x8100);
ethHeader.vlanUserPriority = htons(4);
ethHeader.vlanVid = htons(5);
ethHeader.ethertype = htons(SOME_ETHERTYPE);
...
sendto(s, &ethHeader, sizeof(struct EthHeader), 0, (struct sockaddr*)&socketAddr, sizeof(socketAddr));
Пакет отправляется, но поле Tag Protocol ID все равно ставится ETH_P_ALL (0x0003). Если установить
socketAddr.sll_protocol = htons(ETH_P_8021Q);
то Tag Protocol ID выставляется нужный (0x8100) но поля vlan хидера все равно не заполняются моими значениями. Куда рыть? Как vlan заполнить правильно?

so_much_light
()

RSS подписка на новые темы