提问,思考,学习,分享,积累
droplet's picture

哈希分布测试小程序

一个哈希分布测试小程序。测试0 ~ 0xFFFFFFFF在哈希函数上的分布。可以看出分布非常均匀,如果要构造出哈希碰撞还是不太容易的。如果加上一个随机数,就能更好地防范对哈希函数的攻击。

---------------------------------------------------------------

$cat test_hash.c

#include <stdlib.h>

#include <stdio.h>

#include <stdint.h>

#include <string.h>

#include <sys/socket.h>

#include <netinet/in.h>

#include <arpa/inet.h>

#include <unistd.h>

 

static inline uint32_t

hash_crc_4byte(uint32_t data, uint32_t init_val)

{

    asm volatile ("crc32 %[data], %[init_val]":[init_val] "=r"(init_val)

                  :[data] "r"(data), "[init_val]"(init_val));

    return init_val;

}

 

static uint32_t

hash_crc(void *key, int len, uint32_t init_val)

{

    unsigned i;

    uint32_t temp = 0;

    uint32_t *p32 = (uint32_t *)key;

 

    for(i = 0; i < len / 4; i++){

        init_val = hash_crc_4byte(*p32++, init_val);

    }

 

    switch(3 - (len & 0x03)){

        case 0:

            temp |= *((uint8_t *)p32 + 2) << 16;

            /* Fallthrough */

        case 1:

            temp |= *((uint8_t *)p32 + 1) << 8;

            /* Fallthrough */

        case 2:

            temp |= *((uint8_t *)p32);

            init_val = hash_crc_4byte(temp, init_val);

        default:

            break;

    }

 

droplet's picture

inet_ntoa的小问题

先看代码

#cat test_ntoa.c

#include "stdlib.h"

#include "stdio.h"

#include "stdint.h"

#include <sys/socket.h>

#include <netinet/in.h>

#include <arpa/inet.h>

 

int main(int argc, char *argv[])

{

struct in_addr ip1 = {

.s_addr = htonl(16843009),  /* 1.1.1.1 */

};

struct in_addr ip2 = {

.s_addr = htonl(33686018),  /* 2.2.2.2 */

};

 

printf("ip1: %s, ip2: %s\n", inet_ntoa(ip1), inet_ntoa(ip2));

printf("ip1: %s\n", inet_ntoa(ip1));

printf("ip2: %s\n", inet_ntoa(ip2));

 

    return 0;

}

运行结果

#./test_ntoa

ip1: 1.1.1.1, ip2: 1.1.1.1

ip1: 1.1.1.1

ip2: 2.2.2.2

为什么哪?因为inet_ntoa用的是全局数组,后面的调用会覆盖前面的值。从汇编里面也可以看出,在第一个printf里面,先计算的是inet_ntoa("2.2.2.2"),后计算的是inet_ntoa("1.1.1.1")。

droplet's picture

又一次陷入了运算符优先级的陷阱

刚开始是这样的,发现结果不对。其实编译器已经提示错误了,要加括号,但是忽略了。 

  if ( rt->key.ip&rt_mask == n->key.ip&n_mask)

需要改成这样

if ( (rt->key.ip&rt_mask) == (n->key.ip&n_mask))

“==”的优先级要比“&"高,所以结果不是你想要的结果。写程序一是养成好习惯,再就是不要忽略编译器的告警,毕竟,这不是什么高难的技巧。

droplet's picture

c语言整数提升的一个小问题

先看一段代码

$cat test.c

#include "stdlib.h"

#include "stdio.h"

#include "stdint.h"

 

#define SIZE1 256

#define SIZE2 256UL

 

int main(int argc, char *argv[])

{

    struct test_s {

        uint32_t offset:31;

        uint32_t flag:1;

    }test;

    uint64_t a[64] = {0};

    uint64_t *p = a, *p1, *p2, *p3, *p4;

    uint64_t i;

 

    test.offset = 8388608;

    test.flag = 1;

 

    i = test.offset * SIZE1;

    p1 = p + i;

    i = (uint64_t)(test.offset * SIZE1);

    p2 = p + i;

    i = (uint64_t)test.offset * SIZE1;

    p3 = p + i;

    i = test.offset * SIZE2;

    p4 = p + i;

 

    printf("p %p, p1 %p, p2 %p, p3 %p, p4 %p\n", p, p1, p2, p3, p4);

 

    return 0;

}

运行结果

$./test

p 0x7fff562f6bc0, p1 0x7ffb562f6bc0, p2 0x7ffb562f6bc0, p3 0x8003562f6bc0, p4 0x8003562f6bc0

这个问题是在访问一个非常大的数组时碰到的。这个数组有20亿个元素,下标已经超过了32bits的最大值。数组下标是计算出来的,用一个32位数乘以256。如果使用方法不正确,就会得到一个非法地址。刚开始还以为是地址映射出错了,后来在调试过程中意识到非法地址到数组起始地址的offset正好是0x80000000,这正好是一个负数(如果是32位有符号数)。所以在有意识提升整数时,需要把其中一个先提升了,否则结果还是32bits。

droplet's picture

c语言函数返回值

c语言函数返回值,在没有声明函数原型的情况下是int。这会导致一些很奇特的问题,比如你要把函数返回的指针赋值给一个变量,然后又要访问这个指针。

http://stackoverflow.com/questions/2575153/must-declare-function-prototype-in-c

比如下面这个程序,crash之后,你会觉得莫名其妙。

int main() {

  char *array = foo(5);

  /* No declaration for `foo`, no prototype for `foo`.

     Will work in C89/90. Assumes `int foo(int)` */

 

  return 0;

}

 

char *foo(int i) {

  return (char*)malloc(i);

}

droplet's picture

linux的coredump

linux 进程生成完整的coredump需要检查以下配置项

1) ulimit

默认是不会生成coredump的,需要用ulimit -c size设置coredump的大小,unlimited是没有限制。也可以修改/etc/security/limit.conf,让系统默认生成coredump。

2)sysctl 与coredump相关的几个参数

#sysctl -a | grep core

kernel.core_uses_pid = 1

kernel.core_pattern = /home/coredump/core-%e-%p-%t-%h

kernel.core_pipe_limit = 0

3)进程coredump时,dump哪些内存,默认是有些内存不会dump的,避免coredump文件太大,特别是进程申请很多内存的情况下。当然,有时完整的内存dump是必须的

/proc/pid/coredump_filter

有了这些设置,就可以在linux下调试coredump了。当然,真实环境下,还是尽可能打开coredump,因为不是每个问题都能复现。

下面这个脚本也可以用,如果在当前shell上生效,需要使用source命令执行。

#!/bin/bash

 

#unlimited core file size

ulimit -c unlimited

 

#dump all memory

pid=`pgrep xxx`

echo "0xFF" > /proc/$pid/coredump_filter

 

#core file name

sysctl -w kernel.core_pattern=/home/coredump/core-%e-%p-%t-%h

droplet's picture

bitfield in union

先看两个tcp头的定义

struct tcp_hdr_v1 {

        uint16_t src_port;  /**< TCP source port. */

        uint16_t dst_port;  /**< TCP destination port. */

        uint32_t sent_seq;  /**< TX data sequence number. */

        uint32_t recv_ack;  /**< RX data acknowledgement sequence number. */

        union {

                uint8_t data_off;  /**< Data offset. */

                struct {

                        uint8_t rsvd:4,

                                hlen:4;

                };

        }u1;

        union {

                uint8_t  tcp_flags; /**< TCP flags */

                uint8_t  fin:1,

                         syn:1,

                         rst:1,

                         psh:1,

                         ack:1,

                         urg:1,

                         ece:1,

                         cwr:1;

        }u2;

droplet's picture

SDN是什么?

1)SDN是控制和转发分离吗?网络设备从一开始就强调控制平面和转发平面分离,http://if.ustc.edu.cn/~zhouwei/tech/rfc/rfc3746.txt早就试图把控制平面和转发平面的接口标准化。这样不同厂家的控制平面和转发平面能够组成一个完整的系统。当然这个尝试失败了。一般讲网络设备互操作,都是指在协议层次,不同厂家的产品能够协同工作。指望一个控制平面控制不同厂商的转发平面,目前来看还有很大的难度。都是自己的控制系统控制自己的转发平面。情况依然没有改观。

2)SDN和NOC/SOC有什么区别?一个简单的区别就是NoC缺少智能,当然这也不是绝对的。设备的配置管理本来就是控制平面的一个重要工作。或者可以把配置管理分离出来,做成一个专门的管理平面。控制平面只跑网络协议,比如路由协议。感觉更清晰一点。

3)SND必须是集中式的吗?集中式还是分布式?逻辑的集中,并不排除实现上是分布式的。控制平面如此重要,需要高可用性,高可靠性。一台机器肯定是不够的。但是如果是分布式,是自学习,自适应的分布式,还是静态划分的分布式。有层次,静态切分的方式更多一些。

4)SDN的好处是什么?软件升级,替换更简单?但可靠性是不是更差了?所以SDN适合数据中心,而不是广域网。

droplet's picture

Patterns

droplet's picture

Data center network

Syndicate content Syndicate content