AirVantage / sbulb

UDP load balancer prototype using bcc (XDP/Bpf)
36 stars 9 forks source link

About the calculation of udp checksum #37

Closed iGwkang closed 1 year ago

iGwkang commented 1 year ago

Hello, in your code, only the checksum of the udp modification target ip is recalculated. If I change the source ip:port of this packet, and also modify the destination ip:port, how can I compute the checksum efficiently? My current implementation is to use a for loop to calculate the checksum on the packet, but it feels very inefficient.

sbernard31 commented 1 year ago

Hi, maybe RFC1624 - Computation of the Internet Checksum via Incremental Update could help you ?

iGwkang commented 1 year ago

Hi, maybe RFC1624 - Computation of the Internet Checksum via Incremental Update could help you ?

@sbernard31

Hi, I wrote a function to update the udp checksum according to the formula HC' = HC - ~m - m' in RFC1624, but it is still wrong, can you help me? thanks

typedef union {
  struct {
    u16 ip1;
    u16 ip2;
  };
  u32 ip;
} ip_num;

static __always_inline void udp_checksum_update(struct iphdr *old_iph, struct iphdr *iph, struct udphdr *old_udp, struct udphdr *udph)
{
  // ip
  ip_num old_src_ip, new_src_ip, old_dst_ip, new_dst_ip;
  old_src_ip.ip = old_iph->saddr;
  new_src_ip.ip = iph->saddr;
  old_dst_ip.ip = old_iph->daddr;
  new_dst_ip.ip = iph->daddr;

  // port
  u16 old_src_port = old_udp->source, new_src_port = udph->source;
  u16 old_dst_port = old_udp->dest, new_dst_port = udph->dest;

  // calc checksum
  u16 new_csum = old_udp->check;

  // src ip
  new_csum = new_csum - (~old_src_ip.ip1) - new_src_ip.ip1;
  new_csum = new_csum - (~old_src_ip.ip2) - new_src_ip.ip2;
  // dest ip
  new_csum = new_csum - (~old_dst_ip.ip1) - new_dst_ip.ip1;
  new_csum = new_csum - (~old_dst_ip.ip2) - new_dst_ip.ip2;

  // src port
  new_csum = new_csum - (~old_src_port) - new_src_port;

  // dest port
  new_csum = new_csum - (~old_dst_port) - new_dst_port;

  udph->check = new_csum;
}
sbernard31 commented 1 year ago

Did you also looked at : https://github.com/AirVantage/sbulb/blob/master/sbulb/bpf/checksum.c

iGwkang commented 1 year ago

Did you also looked at : master/sbulb/bpf/checksum.c

@sbernard31 thanks I misunderstood this function before, thinking that this function restricted u32, now my code has been changed to the following, and the verification has passed.

static __always_inline void udp_checksum_update(struct iphdr *old_iph, struct iphdr *iph, struct udphdr *old_udp, struct udphdr *udph)
{
  u16 new_csum = old_udp->check;
  update_csum(&new_csum, old_iph->saddr, iph->saddr);
  update_csum(&new_csum, old_iph->daddr, iph->daddr);
  update_csum(&new_csum, old_udp->source, udph->source);
  update_csum(&new_csum, old_udp->dest, udph->dest);
  udph->check = new_csum;
  return;
}