/* * PROTOTYPE cs_uint8 app_ipintf_pkt_recv(cs_pkt_t* pkt) * INPUT pkt * OUTPUT None. * Description receive packet from HW. * Pre-condition * Post-condition * Note special: only packets from PON need vlan id check * general: allow ARP from GE/FE, without checking vlanid */ cs_uint8 app_ipintf_pkt_recv(cs_pkt_t* pkt) { cs_status rc = CS_E_OK; cs_uint32 len = 0; cs_uint8 *pbuf = NULL; APP_IPINTF_LOG(IROS_LOG_LEVEL_DBG0,"%s, sport %d, len %d, vlan %d, type %d\n", __func__, pkt->port, pkt->len, pkt->svlan, pkt->eth_type); IPINTF_STATIS_INC(RECV, pkt->port); //app_ipintf_mac_learning(pkt); if(pkt->eth_type == EPON_ETHERTYPE_ARP) { rc = app_ipintf_arp_pre_process(pkt); } else { rc = app_ipintf_ip_pre_process(pkt); } if(rc != 0) { APP_IPINTF_LOG(IROS_LOG_LEVEL_DBG3,"%s, does not send to IP stack, 0x%x\n", __func__, (int)pkt); IPINTF_STATIS_INC(DROP, pkt->port); return rc; } app_ipintf_mac_learning(pkt); if(pkt->svlan) { len = (cs_uint32)pkt->len; pbuf = ETH_GET_FRAME_BUFFER(pkt); pop_vlan(pbuf,pbuf,&len); //pkt->stpid = 0; //pkt->svlan = 0; pkt->len = len; if(pkt->tag_num >= 1) pkt->tag_num -= 1; } APP_IPINTF_LOG(IROS_LOG_LEVEL_DBG3,"%s, forward pkt to IP stack, len %d\n", __func__, pkt->len); netdev_pkt_recv(pkt); return CS_E_OK; }
/* Execute a list of actions against 'skb'. */ static int do_execute_actions(struct datapath *dp, struct sk_buff *skb, const struct nlattr *attr, int len, bool keep_skb) { /* Every output action needs a separate clone of 'skb', but the common * case is just a single output action, so that doing a clone and * then freeing the original skbuff is wasteful. So the following code * is slightly obscure just to avoid that. */ int prev_port = -1; const struct nlattr *a; int rem; for (a = attr, rem = len; rem > 0; a = nla_next(a, &rem)) { int err = 0; if (prev_port != -1) { do_output(dp, skb_clone(skb, GFP_ATOMIC), prev_port); prev_port = -1; } switch (nla_type(a)) { case OVS_ACTION_ATTR_OUTPUT: prev_port = nla_get_u32(a); break; case OVS_ACTION_ATTR_USERSPACE: output_userspace(dp, skb, a); break; case OVS_ACTION_ATTR_PUSH_VLAN: err = push_vlan(skb, nla_data(a)); if (unlikely(err)) /* skb already freed. */ return err; break; case OVS_ACTION_ATTR_POP_VLAN: err = pop_vlan(skb); break; case OVS_ACTION_ATTR_SET: err = execute_set_action(skb, nla_data(a)); break; case OVS_ACTION_ATTR_SAMPLE: err = sample(dp, skb, a); break; } if (unlikely(err)) { kfree_skb(skb); return err; } } if (prev_port != -1) { if (keep_skb) skb = skb_clone(skb, GFP_ATOMIC); do_output(dp, skb, prev_port); } else if (!keep_skb) consume_skb(skb); return 0; }
static int do_execute_actions(struct datapath *dp, struct sk_buff *skb, const struct nlattr *attr, int len, bool keep_skb) { /* */ int prev_port = -1; const struct nlattr *a; int rem; for (a = attr, rem = len; rem > 0; a = nla_next(a, &rem)) { int err = 0; if (prev_port != -1) { do_output(dp, skb_clone(skb, GFP_ATOMIC), prev_port); prev_port = -1; } switch (nla_type(a)) { case OVS_ACTION_ATTR_OUTPUT: prev_port = nla_get_u32(a); break; case OVS_ACTION_ATTR_USERSPACE: output_userspace(dp, skb, a); break; case OVS_ACTION_ATTR_PUSH_VLAN: err = push_vlan(skb, nla_data(a)); if (unlikely(err)) /* */ return err; break; case OVS_ACTION_ATTR_POP_VLAN: err = pop_vlan(skb); break; case OVS_ACTION_ATTR_SET: err = execute_set_action(skb, nla_data(a)); break; case OVS_ACTION_ATTR_SAMPLE: err = sample(dp, skb, a); break; } if (unlikely(err)) { kfree_skb(skb); return err; } } if (prev_port != -1) { if (keep_skb) skb = skb_clone(skb, GFP_ATOMIC); do_output(dp, skb, prev_port); } else if (!keep_skb) consume_skb(skb); return 0; }