mirror of
https://github.com/checkpoint-restore/criu
synced 2025-08-30 22:05:36 +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:
@@ -21,5 +21,16 @@ extern int packet_receive_one(struct nlmsghdr *h, void *arg);
|
|||||||
|
|
||||||
#ifndef PACKET_FANOUT
|
#ifndef PACKET_FANOUT
|
||||||
#define PACKET_FANOUT 18
|
#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
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@@ -7,6 +7,17 @@ message packet_mclist {
|
|||||||
required bytes addr = 3;
|
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 {
|
message packet_sock_entry {
|
||||||
required uint32 id = 1;
|
required uint32 id = 1;
|
||||||
required uint32 type = 2;
|
required uint32 type = 2;
|
||||||
@@ -27,4 +38,6 @@ message packet_sock_entry {
|
|||||||
required uint32 copy_thresh = 15;
|
required uint32 copy_thresh = 15;
|
||||||
repeated packet_mclist mclist = 16;
|
repeated packet_mclist mclist = 16;
|
||||||
optional uint32 fanout = 17 [ default = 0xffffffff ];
|
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;
|
int mreq_n;
|
||||||
struct packet_diag_mclist *mreqs;
|
struct packet_diag_mclist *mreqs;
|
||||||
unsigned int fanout;
|
unsigned int fanout;
|
||||||
|
struct packet_diag_ring *rx, *tx;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define NO_FANOUT ((unsigned int)-1)
|
#define NO_FANOUT ((unsigned int)-1)
|
||||||
@@ -104,6 +105,44 @@ err:
|
|||||||
return -1;
|
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)
|
static int dump_one_packet_fd(int lfd, u32 id, const struct fd_parms *p)
|
||||||
{
|
{
|
||||||
PacketSockEntry psk = PACKET_SOCK_ENTRY__INIT;
|
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;
|
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);
|
ret = pb_write_one(fdset_fd(glob_fdset, CR_FD_PACKETSK), &psk, PB_PACKETSK);
|
||||||
out:
|
out:
|
||||||
|
xfree(psk.rx_ring);
|
||||||
|
xfree(psk.tx_ring);
|
||||||
for (i = 0; i < psk.n_mclist; i++)
|
for (i = 0; i < psk.n_mclist; i++)
|
||||||
xfree(psk.mclist[i]->addr.data);
|
xfree(psk.mclist[i]->addr.data);
|
||||||
xfree(psk.mclist);
|
xfree(psk.mclist);
|
||||||
@@ -215,6 +260,18 @@ int packet_receive_one(struct nlmsghdr *hdr, void *arg)
|
|||||||
else
|
else
|
||||||
sd->fanout = NO_FANOUT;
|
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);
|
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;
|
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)
|
static int open_packet_sk(struct file_desc *d)
|
||||||
{
|
{
|
||||||
struct packet_sock_info *psi;
|
struct packet_sock_info *psi;
|
||||||
@@ -312,6 +400,9 @@ static int open_packet_sk(struct file_desc *d)
|
|||||||
if (restore_mreqs(sk, pse))
|
if (restore_mreqs(sk, pse))
|
||||||
goto err_cl;
|
goto err_cl;
|
||||||
|
|
||||||
|
if (restore_rings(sk, pse))
|
||||||
|
goto err_cl;
|
||||||
|
|
||||||
if (pse->has_fanout) {
|
if (pse->has_fanout) {
|
||||||
pr_info("Restoring fanout %x\n", pse->fanout);
|
pr_info("Restoring fanout %x\n", pse->fanout);
|
||||||
if (restore_opt(sk, SOL_PACKET, PACKET_FANOUT, &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_family = AF_PACKET;
|
||||||
req.r.p.sdiag_protocol = 0;
|
req.r.p.sdiag_protocol = 0;
|
||||||
req.r.p.pdiag_show = PACKET_SHOW_INFO | PACKET_SHOW_MCLIST |
|
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);
|
tmp = do_rtnl_req(nl, &req, sizeof(req), packet_receive_one, NULL);
|
||||||
if (tmp)
|
if (tmp)
|
||||||
err = tmp;
|
err = tmp;
|
||||||
|
Reference in New Issue
Block a user