mirror of
https://github.com/checkpoint-restore/criu
synced 2025-08-30 05:48:05 +00:00
packet: Rings support
There's no way (currently) to check that the ring got restored. Will do it once we implement mapping of a packet socket and tcpdump app test. Signed-off-by: Pavel Emelyanov <xemul@parallels.com>
This commit is contained in:
parent
398bec28a9
commit
2660b810d9
@ -21,5 +21,16 @@ extern int packet_receive_one(struct nlmsghdr *h, void *arg);
|
||||
|
||||
#ifndef PACKET_FANOUT
|
||||
#define PACKET_FANOUT 18
|
||||
|
||||
struct tpacket_req3 {
|
||||
unsigned int tp_block_size;
|
||||
unsigned int tp_block_nr;
|
||||
unsigned int tp_frame_size;
|
||||
unsigned int tp_frame_nr;
|
||||
unsigned int tp_retire_blk_tov;
|
||||
unsigned int tp_sizeof_priv;
|
||||
unsigned int tp_feature_req_word;
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
@ -7,6 +7,17 @@ message packet_mclist {
|
||||
required bytes addr = 3;
|
||||
}
|
||||
|
||||
message packet_ring {
|
||||
required uint32 block_size = 1;
|
||||
required uint32 block_nr = 2;
|
||||
required uint32 frame_size = 3;
|
||||
required uint32 frame_nr = 4;
|
||||
|
||||
required uint32 retire_tmo = 5;
|
||||
required uint32 sizeof_priv = 6;
|
||||
required uint32 features = 7;
|
||||
}
|
||||
|
||||
message packet_sock_entry {
|
||||
required uint32 id = 1;
|
||||
required uint32 type = 2;
|
||||
@ -27,4 +38,6 @@ message packet_sock_entry {
|
||||
required uint32 copy_thresh = 15;
|
||||
repeated packet_mclist mclist = 16;
|
||||
optional uint32 fanout = 17 [ default = 0xffffffff ];
|
||||
optional packet_ring rx_ring = 18;
|
||||
optional packet_ring tx_ring = 19;
|
||||
}
|
||||
|
91
sk-packet.c
91
sk-packet.c
@ -36,6 +36,7 @@ struct packet_sock_desc {
|
||||
int mreq_n;
|
||||
struct packet_diag_mclist *mreqs;
|
||||
unsigned int fanout;
|
||||
struct packet_diag_ring *rx, *tx;
|
||||
};
|
||||
|
||||
#define NO_FANOUT ((unsigned int)-1)
|
||||
@ -104,6 +105,44 @@ err:
|
||||
return -1;
|
||||
}
|
||||
|
||||
static PacketRing *dump_ring(struct packet_diag_ring *dr)
|
||||
{
|
||||
PacketRing *ring;
|
||||
|
||||
ring = xmalloc(sizeof(*ring));
|
||||
if (!ring)
|
||||
return NULL;
|
||||
|
||||
packet_ring__init(ring);
|
||||
|
||||
ring->block_size = dr->pdr_block_size;
|
||||
ring->block_nr = dr->pdr_block_nr;
|
||||
ring->frame_size = dr->pdr_frame_size;
|
||||
ring->frame_nr = dr->pdr_frame_nr;
|
||||
ring->retire_tmo = dr->pdr_retire_tmo;
|
||||
ring->sizeof_priv = dr->pdr_sizeof_priv;
|
||||
ring->features = dr->pdr_features;
|
||||
|
||||
return ring;
|
||||
}
|
||||
|
||||
static int dump_rings(PacketSockEntry *psk, struct packet_sock_desc *sd)
|
||||
{
|
||||
if (sd->rx) {
|
||||
psk->rx_ring = dump_ring(sd->rx);
|
||||
if (!psk->rx_ring)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (sd->tx) {
|
||||
psk->tx_ring = dump_ring(sd->tx);
|
||||
if (!psk->tx_ring)
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dump_one_packet_fd(int lfd, u32 id, const struct fd_parms *p)
|
||||
{
|
||||
PacketSockEntry psk = PACKET_SOCK_ENTRY__INIT;
|
||||
@ -148,8 +187,14 @@ static int dump_one_packet_fd(int lfd, u32 id, const struct fd_parms *p)
|
||||
psk.fanout = sd->fanout;
|
||||
}
|
||||
|
||||
ret = dump_rings(&psk, sd);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
ret = pb_write_one(fdset_fd(glob_fdset, CR_FD_PACKETSK), &psk, PB_PACKETSK);
|
||||
out:
|
||||
xfree(psk.rx_ring);
|
||||
xfree(psk.tx_ring);
|
||||
for (i = 0; i < psk.n_mclist; i++)
|
||||
xfree(psk.mclist[i]->addr.data);
|
||||
xfree(psk.mclist);
|
||||
@ -215,6 +260,18 @@ int packet_receive_one(struct nlmsghdr *hdr, void *arg)
|
||||
else
|
||||
sd->fanout = NO_FANOUT;
|
||||
|
||||
if (tb[PACKET_DIAG_RX_RING]) {
|
||||
sd->rx = xmalloc(sizeof(*sd->rx));
|
||||
memcpy(sd->rx, RTA_DATA(tb[PACKET_DIAG_RX_RING]), sizeof(*sd->rx));
|
||||
} else
|
||||
sd->rx = NULL;
|
||||
|
||||
if (tb[PACKET_DIAG_TX_RING]) {
|
||||
sd->tx = xmalloc(sizeof(*sd->tx));
|
||||
memcpy(sd->tx, RTA_DATA(tb[PACKET_DIAG_TX_RING]), sizeof(*sd->tx));
|
||||
} else
|
||||
sd->tx = NULL;
|
||||
|
||||
return sk_collect_one(m->pdiag_ino, PF_PACKET, &sd->sd);
|
||||
}
|
||||
|
||||
@ -246,6 +303,37 @@ static int restore_mreqs(int sk, PacketSockEntry *pse)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int restore_ring(int sk, int type, PacketRing *ring)
|
||||
{
|
||||
struct tpacket_req3 req;
|
||||
|
||||
if (!ring)
|
||||
return 0;
|
||||
|
||||
pr_debug("\tRestoring %d ring\n", type);
|
||||
|
||||
req.tp_block_size = ring->block_size;
|
||||
req.tp_block_nr = ring->block_nr;
|
||||
req.tp_frame_size = ring->frame_size;
|
||||
req.tp_frame_nr = ring->frame_nr;
|
||||
req.tp_retire_blk_tov = ring->retire_tmo;
|
||||
req.tp_sizeof_priv = ring->sizeof_priv;
|
||||
req.tp_feature_req_word = ring->features;
|
||||
|
||||
return restore_opt(sk, SOL_PACKET, type, &req);
|
||||
}
|
||||
|
||||
static int restore_rings(int sk, PacketSockEntry *psk)
|
||||
{
|
||||
if (restore_ring(sk, PACKET_RX_RING, psk->rx_ring))
|
||||
return -1;
|
||||
|
||||
if (restore_ring(sk, PACKET_TX_RING, psk->tx_ring))
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int open_packet_sk(struct file_desc *d)
|
||||
{
|
||||
struct packet_sock_info *psi;
|
||||
@ -312,6 +400,9 @@ static int open_packet_sk(struct file_desc *d)
|
||||
if (restore_mreqs(sk, pse))
|
||||
goto err_cl;
|
||||
|
||||
if (restore_rings(sk, pse))
|
||||
goto err_cl;
|
||||
|
||||
if (pse->has_fanout) {
|
||||
pr_info("Restoring fanout %x\n", pse->fanout);
|
||||
if (restore_opt(sk, SOL_PACKET, PACKET_FANOUT, &pse->fanout))
|
||||
|
@ -274,7 +274,7 @@ int collect_sockets(int pid)
|
||||
req.r.p.sdiag_family = AF_PACKET;
|
||||
req.r.p.sdiag_protocol = 0;
|
||||
req.r.p.pdiag_show = PACKET_SHOW_INFO | PACKET_SHOW_MCLIST |
|
||||
PACKET_SHOW_FANOUT;
|
||||
PACKET_SHOW_FANOUT | PACKET_SHOW_RING_CFG;
|
||||
tmp = do_rtnl_req(nl, &req, sizeof(req), packet_receive_one, NULL);
|
||||
if (tmp)
|
||||
err = tmp;
|
||||
|
Loading…
x
Reference in New Issue
Block a user