diff --git a/test/performance/odp_l2fwd.c b/test/performance/odp_l2fwd.c
index 2daf0e2db..0ebb0dd17 100644
--- a/test/performance/odp_l2fwd.c
+++ b/test/performance/odp_l2fwd.c
@@ -92,6 +92,7 @@ static inline int sched_mode(pktin_mode_t in_mode)
  * Parsed command line application arguments
  */
 typedef struct {
+	int extra_check;        /**< Some extra checks have been enabled */
 	int cpu_count;
 	int if_count;		/**< Number of interfaces to be used */
 	int addr_count;		/**< Number of dst addresses to be used */
@@ -106,6 +107,7 @@ typedef struct {
 	int dst_change;		/**< Change destination eth addresses */
 	int src_change;		/**< Change source eth addresses */
 	int error_check;        /**< Check packet errors */
+	int chksum;             /**< Checksum offload */
 	int sched_mode;         /**< Scheduler mode */
 	int num_groups;         /**< Number of scheduling groups */
 	int verbose;		/**< Verbose output */
@@ -293,6 +295,18 @@ static inline int event_queue_send(odp_queue_t queue, odp_packet_t *pkt_tbl,
 	return sent;
 }
 
+static inline void chksum_insert(odp_packet_t *pkt_tbl, int pkts)
+{
+	odp_packet_t pkt;
+	int i;
+
+	for (i = 0; i < pkts; i++) {
+		pkt = pkt_tbl[i];
+		odp_packet_l3_chksum_insert(pkt, 1);
+		odp_packet_l4_chksum_insert(pkt, 1);
+	}
+}
+
 /**
  * Packet IO worker thread using scheduled queues
  *
@@ -366,18 +380,23 @@ static int run_worker_sched_mode(void *arg)
 		for (i = 0; i < pkts; i++)
 			pkt_tbl[i] = odp_packet_from_event(ev_tbl[i]);
 
-		if (gbl_args->appl.error_check) {
-			int rx_drops;
+		if (odp_unlikely(gbl_args->appl.extra_check)) {
+			if (gbl_args->appl.chksum)
+				chksum_insert(pkt_tbl, pkts);
 
-			/* Drop packets with errors */
-			rx_drops = drop_err_pkts(pkt_tbl, pkts);
+			if (gbl_args->appl.error_check) {
+				int rx_drops;
 
-			if (odp_unlikely(rx_drops)) {
-				stats->s.rx_drops += rx_drops;
-				if (pkts == rx_drops)
-					continue;
+				/* Drop packets with errors */
+				rx_drops = drop_err_pkts(pkt_tbl, pkts);
 
-				pkts -= rx_drops;
+				if (odp_unlikely(rx_drops)) {
+					stats->s.rx_drops += rx_drops;
+					if (pkts == rx_drops)
+						continue;
+
+					pkts -= rx_drops;
+				}
 			}
 		}
 
@@ -487,18 +506,23 @@ static int run_worker_plain_queue_mode(void *arg)
 		for (i = 0; i < pkts; i++)
 			pkt_tbl[i] = odp_packet_from_event(event[i]);
 
-		if (gbl_args->appl.error_check) {
-			int rx_drops;
+		if (odp_unlikely(gbl_args->appl.extra_check)) {
+			if (gbl_args->appl.chksum)
+				chksum_insert(pkt_tbl, pkts);
 
-			/* Drop packets with errors */
-			rx_drops = drop_err_pkts(pkt_tbl, pkts);
+			if (gbl_args->appl.error_check) {
+				int rx_drops;
 
-			if (odp_unlikely(rx_drops)) {
-				stats->s.rx_drops += rx_drops;
-				if (pkts == rx_drops)
-					continue;
+				/* Drop packets with errors */
+				rx_drops = drop_err_pkts(pkt_tbl, pkts);
 
-				pkts -= rx_drops;
+				if (odp_unlikely(rx_drops)) {
+					stats->s.rx_drops += rx_drops;
+					if (pkts == rx_drops)
+						continue;
+
+					pkts -= rx_drops;
+				}
 			}
 		}
 
@@ -605,18 +629,23 @@ static int run_worker_direct_mode(void *arg)
 		if (odp_unlikely(pkts <= 0))
 			continue;
 
-		if (gbl_args->appl.error_check) {
-			int rx_drops;
+		if (odp_unlikely(gbl_args->appl.extra_check)) {
+			if (gbl_args->appl.chksum)
+				chksum_insert(pkt_tbl, pkts);
+
+			if (gbl_args->appl.error_check) {
+				int rx_drops;
 
-			/* Drop packets with errors */
-			rx_drops = drop_err_pkts(pkt_tbl, pkts);
+				/* Drop packets with errors */
+				rx_drops = drop_err_pkts(pkt_tbl, pkts);
 
-			if (odp_unlikely(rx_drops)) {
-				stats->s.rx_drops += rx_drops;
-				if (pkts == rx_drops)
-					continue;
+				if (odp_unlikely(rx_drops)) {
+					stats->s.rx_drops += rx_drops;
+					if (pkts == rx_drops)
+						continue;
 
-				pkts -= rx_drops;
+					pkts -= rx_drops;
+				}
 			}
 		}
 
@@ -707,9 +736,17 @@ static int create_pktio(const char *dev, int idx, int num_rx, int num_tx,
 	}
 
 	odp_pktio_config_init(&config);
-	config.parser.layer = gbl_args->appl.error_check ?
+	config.parser.layer = gbl_args->appl.extra_check ?
 			ODP_PKTIO_PARSER_LAYER_ALL :
 			ODP_PKTIO_PARSER_LAYER_NONE;
+
+	if (gbl_args->appl.chksum) {
+		printf("Checksum offload enabled\n");
+		config.pktout.bit.ipv4_chksum_ena = 1;
+		config.pktout.bit.udp_chksum_ena  = 1;
+		config.pktout.bit.tcp_chksum_ena  = 1;
+	}
+
 	odp_pktio_config(pktio, &config);
 
 	odp_pktin_queue_param_init(&pktin_param);
@@ -1132,9 +1169,12 @@ static void usage(char *progname)
 	       "                          Requires also the -d flag to be set\n"
 	       "  -e, --error_check <arg> 0: Don't check packet errors (default)\n"
 	       "                          1: Check packet errors\n"
+	       "  -k, --chksum <arg>      0: Don't use checksum offload (default)\n"
+	       "                          1: Use checksum offload\n"
 	       "  -g, --groups <num>      Number of groups to use: 0 ... num\n"
 	       "                          0: SCHED_GROUP_ALL (default)\n"
 	       "                          num: must not exceed number of interfaces or workers\n"
+	       "  -v, --verbose           Verbose output.\n"
 	       "  -h, --help              Display help and exit.\n\n"
 	       "\n", NO_PATH(progname), NO_PATH(progname), MAX_PKTIOS
 	    );
@@ -1166,13 +1206,14 @@ static void parse_args(int argc, char *argv[], appl_args_t *appl_args)
 		{"dst_change", required_argument, NULL, 'd'},
 		{"src_change", required_argument, NULL, 's'},
 		{"error_check", required_argument, NULL, 'e'},
+		{"chksum", required_argument, NULL, 'k'},
 		{"groups", required_argument, NULL, 'g'},
 		{"verbose", no_argument, NULL, 'v'},
 		{"help", no_argument, NULL, 'h'},
 		{NULL, 0, NULL, 0}
 	};
 
-	static const char *shortopts =  "+c:+t:+a:i:m:o:r:d:s:e:g:vh";
+	static const char *shortopts =  "+c:+t:+a:i:m:o:r:d:s:e:k:g:vh";
 
 	/* let helper collect its own arguments (e.g. --odph_proc) */
 	odph_parse_options(argc, argv, shortopts, longopts);
@@ -1184,6 +1225,7 @@ static void parse_args(int argc, char *argv[], appl_args_t *appl_args)
 	appl_args->num_groups = 0; /* use default group */
 	appl_args->error_check = 0; /* don't check packet errors by default */
 	appl_args->verbose = 0;
+	appl_args->chksum = 0; /* don't use checksum offload by default */
 
 	opterr = 0; /* do not issue errors on helper options */
 
@@ -1308,6 +1350,9 @@ static void parse_args(int argc, char *argv[], appl_args_t *appl_args)
 		case 'e':
 			appl_args->error_check = atoi(optarg);
 			break;
+		case 'k':
+			appl_args->chksum = atoi(optarg);
+			break;
 		case 'g':
 			appl_args->num_groups = atoi(optarg);
 			break;
@@ -1335,6 +1380,8 @@ static void parse_args(int argc, char *argv[], appl_args_t *appl_args)
 		exit(EXIT_FAILURE);
 	}
 
+	appl_args->extra_check = appl_args->error_check || appl_args->chksum;
+
 	optind = 1;		/* reset 'extern optind' from the getopt lib */
 }
 
