DF-5707 / probe2.c
/* * probe2.c - DF-5707: single forced-state sendto with us-resolution randseed * polling around it. Prints a timeline of every randseed change. */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <fcntl.h> #include <errno.h> #include <time.h> #include <sys/socket.h> #include <netinet/in.h> #include <netinet/ip.h> #include <netinet/ip_icmp.h> #include <arpa/inet.h> #define RSPHYS 0x1120c80 static uint64_t rrs(int fd) { uint64_t v=0; if (pread(fd,&v,8,RSPHYS)!=8){perror("pread");exit(1);} return v; } static double now(struct timespec *t0) { struct timespec ts; clock_gettime(CLOCK_MONOTONIC, &ts); return (ts.tv_sec - t0->tv_sec) + 1e-9*(ts.tv_nsec - t0->tv_nsec); } static unsigned short cksum(unsigned short *p, int n) { unsigned long s = 0; while (n > 1) { s += *p++; n -= 2; } if (n) s += *(unsigned char *)p; s = (s >> 16) + (s & 0xffff); s += (s >> 16); return ~s; } int main(int argc, char **argv) { int mfd = open("/dev/mem", O_RDONLY); if (mfd < 0) { perror("/dev/mem"); return 1; } struct timespec t0; clock_gettime(CLOCK_MONOTONIC, &t0); int s = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP); if (s < 0) { perror("socket"); return 1; } struct sockaddr_in dst; memset(&dst,0,sizeof(dst)); dst.sin_family=AF_INET; dst.sin_addr.s_addr=inet_addr("127.0.0.1"); char pkt[64]; memset(pkt,0,sizeof(pkt)); struct icmp *icp=(struct icmp*)pkt; icp->icmp_type=ICMP_ECHO; icp->icmp_code=0; icp->icmp_id=htons(0x5708); icp->icmp_seq=htons(1); icp->icmp_cksum=0; icp->icmp_cksum=cksum((unsigned short*)pkt,64); /* pre-poll 5ms to catch pre-send activity */ uint64_t prev = rrs(mfd); printf("t=%.6f rs=%llu (pre)\n", now(&t0), (unsigned long long)prev); while (now(&t0) < 0.005) { uint64_t v = rrs(mfd); if (v != prev) { printf("t=%.6f rs=%llu\n", now(&t0), (unsigned long long)v); prev=v; } } int r = sendto(s, pkt, 64, 0, (struct sockaddr*)&dst, sizeof(dst)); printf("t=%.6f sendto=%d errno=%d rs=%llu\n", now(&t0), r, errno, (unsigned long long)rrs(mfd)); /* post-poll 30ms */ while (now(&t0) < 0.035) { uint64_t v = rrs(mfd); if (v != prev) { printf("t=%.6f rs=%llu\n", now(&t0), (unsigned long long)v); prev=v; } } /* drain any reply */ char buf[128]; struct sockaddr_in from; socklen_t fl=sizeof(from); struct timeval tv={0,200000}; setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)); ssize_t rr = recvfrom(s, buf, sizeof(buf), 0, (struct sockaddr*)&from, &fl); printf("t=%.6f recv=%zd rs=%llu\n", now(&t0), rr, (unsigned long long)rrs(mfd)); while (now(&t0) < 0.100) { uint64_t v = rrs(mfd); if (v != prev) { printf("t=%.6f rs=%llu\n", now(&t0), (unsigned long long)v); prev=v; } } return 0; } |