checkpoint-restore / go-criu

Go Bindings for CRIU
Apache License 2.0
172 stars 47 forks source link

crit: parse data fields in files.img #144

Open rst0git opened 1 year ago

rst0git commented 1 year ago

The Go version of CRIT currently outputs raw data decoded from files.img. However, it would be more user-friendly if we map constants used in certain fields to human readable strings and decode the value used for IP address. The following example shows a comparison between the output of the Go and Python versions of CRIT:

snprajwal commented 1 year ago

Hmm, this will require some reworking of the marshaling and unmarshaling logic that we're using currently. We'll probably have to replace protojson.Marshal with our own custom logic to marshal it field by field. I'll look into this.

Parthiba-Hazra commented 9 months ago

@rst0git if this issue is still on, can I work on this?

rst0git commented 9 months ago

@Parthiba-Hazra sure, please feel free to open a pull request!

Parthiba-Hazra commented 8 months ago

@rst0git is there any documentations for all types of constants ? -

// Constants for families
const (
    AF_INET  = 2
    AF_INET6 = 10
)

// Constants for socket types
const (
    SOCK_STREAM = 1
    SOCK_DGRAM  = 2
)

// Constants for protocols
const (
    IPPROTO_TCP = 6
    IPPROTO_UDP = 17
)

// Constants for socket states
const (
    TCP_CLOSE    = 1
    TCP_LISTEN   = 2
    TCP_SYN_SENT = 3
)
rst0git commented 8 months ago

@rst0git is there any documentations for all types of constants ?

Parthiba-Hazra commented 8 months ago

@rst0git should we update the proto file for this or write our own logic .. also we are using proto2 and I think there are many changes in proto3 as I am getting trouble to generate the go code.

I updated the sk-inet.proto like this -

// SPDX-License-Identifier: MIT

syntax = "proto2";

import "opts.proto";
import "fown.proto";
import "sk-opts.proto";

enum AddressFamily {
  UNSPEC = 0;
  LOCAL = 1;
  INET = 2;
  AX25 = 3;
  IPX = 4;
  APPLETALK = 5;
  NETROM = 6;
  BRIDGE = 7;
  ATMPVC = 8;
  X25 = 9;
  INET6 = 10;
  ROSE = 11;
  DECnet = 12;
  NETBEUI = 13;
  SECURITY = 14;
  KEY = 15;
  NETLINK = 16;
  PACKET = 17;
  ASH = 18;
  ECONET = 19;
  ATMSVC = 20;
  RDS = 21;
  SNA = 22;
  IRDA = 23;
  PPPOX = 24;
  WANPIPE = 25;
  LLC = 26;
  IB = 27;
  MPLS = 28;
  CAN = 29;
  TIPC = 30;
  BLUETOOTH = 31;
  IUCV = 32;
  RXRPC = 33;
  ISDN = 34;
  PHONET = 35;
  IEEE802154 = 36;
  CAIF = 37;
  ALG = 38;
  NFC = 39;
  VSOCK = 40;
  KCM = 41;
  QIPCRTR = 42;
  SMC = 43;
  XDP = 44;
  MCTP = 45;
  MAX = 46;
}

enum SocketType {
  STREAM = 1;
  DGRAM = 2;
  RAW = 3;
}

enum Protocol {
  ICMP = 1;
  IGMP = 2;
  TCP = 6;
  UDP = 17;
  IPv6 = 41;
  OSPF = 89;
}

enum State {
  UNKNOWN = 0;
  LISTEN = 1;
  SYN_SENT = 2;
  SYN_RECV = 3;
  ESTABLISHED = 4;
  FIN_WAIT1 = 5;
  FIN_WAIT2 = 6;
  CLOSE = 7;
  CLOSE_WAIT = 8;
  LAST_ACK = 9;
  TIME_WAIT = 10;
  CLOSED = 11;
}

message ip_opts_raw_entry {
  optional bool hdrincl = 1;
  optional bool nodefrag = 2;
  optional bool checksum = 3;
  repeated uint32 icmpv_filter = 4;
}

message ip_opts_entry {
  optional bool freebind = 1;
  // Fields 2 and 3 are reserved for vz7 use
  optional ip_opts_raw_entry raw = 4;
  optional bool pktinfo = 5;
}

message inet_sk_entry {
    /*
     * We have two IDs here -- id and ino. The first one
     * is used when restoring socket behind a file descriprot.
     * The fdinfo image's id is it. The second one is used
     * in sk-inet.c internally, in particular we identify
     * a TCP stream to restore into this socket using the
     * ino value.
     */
    required uint32         id      =  1;
    required uint32         ino     =  2;
    required AddressFamily          family      =  3 [(criu).dict = "sk"];
    required SocketType         type        =  4 [(criu).dict = "sk"];
    required Protocol           proto       =  5 [(criu).dict = "sk"];
    required State          state       =  6 [(criu).dict = "sk"];
    required uint32         src_port    =  7;
    required uint32         dst_port    =  8;
    required uint32         flags       =  9 [(criu).hex = true];
    required uint32         backlog     = 10;

    repeated uint32         src_addr    = 11 [(criu).ipadd = true];
    repeated uint32         dst_addr    = 12 [(criu).ipadd = true];

    required fown_entry     fown        = 13;
    required sk_opts_entry      opts        = 14;
    optional bool           v6only      = 15;
    optional ip_opts_entry      ip_opts     = 16;

    /* for ipv6, we need to send the ifindex to bind(); we keep the ifname
     * here and convert it on restore */
    optional string         ifname      = 17;
    optional uint32         ns_id       = 18;
    optional sk_shutdown        shutdown    = 19;
}
adrianreber commented 8 months ago

@Parthiba-Hazra Unfortunately it is not possible to change the proto files. Those files are imported from CRIU and can only be changed in the CRIU repository. We just copy those files.

Parthiba-Hazra commented 8 months ago

@adrianreber ohh I see, then we have to change the unmarshal logic here.

Parthiba-Hazra commented 8 months ago

@rst0git I was using map[string]interface{} for unmarshaling the each types(eg; "isk", "reg") and change the necessary fields into human readable format by replacing the integer value with its actual value, but the problem is that the order of json fields are changed after marshaling it again in json bytes cause map store the key value pair in alphabetic order, I think it maybe possible to preserve the order as before. the question is it necessary to keep the order same as before or should we use custom struct instead of map?

edit- another idea could be copy the structs(eg; RegFileEntry{}, inetSkEntry{}) from .proto files for each types and make the each fields of struct to json.RawMessage type .. or it's comfortable type, then we can unmarshal the json bytes into something similar to FileEntry{} struct