[ovs-discuss] Netlink for Dump-flow command

Ben Pfaff blp at ovn.org
Fri Mar 12 20:13:57 UTC 2021


I don't see how this can hope to dump flows because it doesn't have the
name of the Generic Netlink group for the flow table in it anywhere.

It also has some oddities that might show a misunderstanding of how
Netlink works.  A netlink dump operation can't fail due to packet drops
or buffer overruns because the buffer isn't filled on a timer or all at
once; it's generated by the kernel chunk by chunk as userspace reads it.

You might want to read the OVS code for dumping flows.

On Fri, Mar 12, 2021 at 08:42:17PM +0530, Muddu Prasad wrote:
> Hi,
> 
> I am trying to develop netlink interface to fetch flow details that are
> displayed as part of ovs-dpctl dump-flow command.
> 
> For the request I send I am getting invalid response from kernel.
> Can somebody help me please?
> 
> Attached is the code that I am using to capture flow details,
> 
> Regards,
> Prasad
> 
> -- 
> Disclaimer:This message is intended only for the designated recipient(s). 
> It may contain confidential or proprietary information and may be subject 
> to other confidentiality protections. If you are not a designated 
> recipient, you may not review, copy or distribute this message. Please 
> notify the sender by e-mail and delete this message. GlobalEdge does not 
> accept any liability for virus infected mails.
> 

> 
> static int data_cb(const struct nlmsghdr *nlh, void *data)
> {
>     struct nf_conntrack *ct;
>     char buf[BUFF_SIZE];
>     memset(buf, OK, sizeof(buf));
>     unsigned int flags = NFCT_OF_ID;
> #if 0
>     ct = nfct_new();
>     if (ct == NULL) return MNL_CB_OK;
> 
>     nfct_nlmsg_parse(nlh, ct);
>     nfct_snprintf(buf, sizeof(buf), ct, NFCT_T_UNKNOWN, NFCT_O_DEFAULT, flags);
>     printf("%s\n\n", buf);
> 
>     nfct_destroy(ct);
> #endif
>     return MNL_CB_OK;
> }
> 
> static void  timeout_cb(EV_P_ ev_timer *w, int revents)
> {
>     struct mnl_socket *nl;
>     struct nlmsghdr *nlh;
>     //struct nfgenmsg *nfh;
>     struct genlmsghdr *nfh;
>     char buf[MNL_SOCKET_DUMP_SIZE];
>     unsigned int seq, portid;
>     int ret= OK, on = OK,  buffersize = (1 << 22);
> 
>     /* Set high priority for this process, less chances to overrun
>      * the netlink receiver buffer since the scheduler gives this process
>      * more chances to run.
>      */
>     nice(-20);
>  //   nl = mnl_socket_open(NETLINK_NETFILTER);
>     nl = mnl_socket_open(NETLINK_GENERIC);
>     if (nl == NULL)
>     {
>         printf("%s: mnl_socket_open failed: %s", __func__, strerror(errno));
>         exit(EXIT_FAILURE);
>     }
> 
>     ret = mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID);
>     if(ret < OK)
>     {
>         printf("%s: mnl_socket_bind failed: %s", __func__, strerror(errno));
>         exit(EXIT_FAILURE);
>     }
> 
>     /* Set netlink receiver buffer to 16 MBytes, to avoid packet drops */
>     setsockopt(mnl_socket_get_fd(nl), SOL_SOCKET, SO_RCVBUFFORCE,
>             &buffersize, sizeof(socklen_t));
> 
>     /* The two tweaks below enable reliable event delivery, packets may
>      * be dropped if the netlink receiver buffer overruns. This happens ...
>      *
>      * a) if the kernel spams this user-space process until the receiver
>      *    is filled.
>      *
>      * or:
>      *
>      * b) if the user-space process does not pull messages from the
>      *    receiver buffer so often.
>      */
>     mnl_socket_setsockopt(nl, NETLINK_BROADCAST_ERROR, &on, sizeof(int));
>     mnl_socket_setsockopt(nl, NETLINK_NO_ENOBUFS, &on, sizeof(int));
> 
>     portid = mnl_socket_get_portid(nl);
>     nlh = mnl_nlmsg_put_header(buf);
>     nlh->nlmsg_type =  16; //(NFNL_SUBSYS_CTNETLINK << 8) | IPCTNL_MSG_CT_GET;
>     nlh->nlmsg_flags = NLM_F_ACK | NLM_F_REQUEST | NLM_F_DUMP;
>     nlh->nlmsg_seq = seq = time(NULL);
> 
>     nfh = mnl_nlmsg_put_extra_header(nlh, sizeof(struct genlmsghdr /*nfgenmsg*/));
>    // nfh->nfgen_family = AF_INET;
>     nfh->cmd = OVS_DP_CMD_GET; //AF_INET;
>     nfh->version = NFNETLINK_V0;
>     //nfh->res_id = OK;
>     nfh->reserved = OK;
> printf("Before sending \n");
>     ret = mnl_socket_sendto(nl, nlh, nlh->nlmsg_len);
> 
>     printf("After Sending %d  \n", ret);
>     if (ret == NO_OK)
>     {
>         printf("%s: mnl_socket_sendto failed: %s", __func__, strerror(errno));
>         exit(EXIT_FAILURE);
>     }
> 
>     ret = mnl_socket_recvfrom(nl, buf, sizeof(buf));
>     printf("After receiving %d \n ", ret);
>     while (ret > OK)
>     {
> 	    printf(" Processing Retrun value \n ");
>       ret = mnl_cb_run(buf, ret, seq, portid, data_cb, NULL);
>         if (ret <= MNL_CB_STOP) break;
> 
>         ret = mnl_socket_recvfrom(nl, buf, sizeof(buf));
>     }
>     if (ret == NO_OK)
>     {
>         printf("%s: mnl_socket_recvfrom failed: %s", __func__, strerror(errno));
>         exit(EXIT_FAILURE);
>     }
> 
>     mnl_socket_close(nl);
>     return;
> 
> }
> 
> int main(void)
> {
>     struct ev_loop *loop = ev_default_loop(0);
>    // target_log_open("CONNTRACK Test\n", 0);
>    // log_severity_set(unix_server_log_severity);
>     // now wait for events to arrive
>     while (true)
>     {
>         // initialise a timer watcher, then start it
>         ev_timer_init(&timeout_watcher, timeout_cb,
>                         ev_time() - ev_now(EV_DEFAULT_UC)+5.0, 0.0);
>         ev_timer_start(loop, &timeout_watcher);
>         ev_loop(loop, 0);
>     }
> 
>     return OK;
> }
> 

> _______________________________________________
> discuss mailing list
> discuss at openvswitch.org
> https://mail.openvswitch.org/mailman/listinfo/ovs-discuss



More information about the discuss mailing list